mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Add side-effect-free information for events.
This commit is contained in:
parent
2d823d8eae
commit
d5f5ab8b88
3 changed files with 189 additions and 24 deletions
133
fndata.txt
133
fndata.txt
|
@ -18,11 +18,13 @@
|
||||||
# along with LSL PyOptimizer. If not, see <http://www.gnu.org/licenses/>.
|
# along with LSL PyOptimizer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
# This file provides information to the optimizer about the behaviour of
|
# This file provides information to the optimizer about the behaviour of
|
||||||
# functions. This knowledge can help perform a better job at optimizing.
|
# functions and events. This knowledge can help perform a better job at
|
||||||
# All functions present in builtins.txt must be here and vice versa.
|
# optimizing. All functions and events present in builtins.txt must be here
|
||||||
|
# and vice versa.
|
||||||
|
|
||||||
# Flags are entered with a dash at the beginning of the line, then a space,
|
# Flags are entered with a dash at the beginning of the line, then a space,
|
||||||
# then the flag. Flags apply to the function they are under.
|
# then the flag. Flags apply to the function they are under. There can be none
|
||||||
|
# before the first function.
|
||||||
#
|
#
|
||||||
# Available flags:
|
# Available flags:
|
||||||
#
|
#
|
||||||
|
@ -1454,3 +1456,128 @@ string llXorBase64Strings( string str1, string str2 )
|
||||||
|
|
||||||
string llXorBase64StringsCorrect( string str1, string str2 )
|
string llXorBase64StringsCorrect( string str1, string str2 )
|
||||||
- SEF
|
- SEF
|
||||||
|
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
# Events are SEF if a script with an empty event can't be
|
||||||
|
# distinguished from a script without that event except for the
|
||||||
|
# extra CPU and memory consumption.
|
||||||
|
|
||||||
|
event at_rot_target( integer tnum, rotation targetrot, rotation ourrot )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event at_target( integer tnum, vector targetpos, vector ourpos )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event attach( key id )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event changed( integer change )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event collision( integer num_detected )
|
||||||
|
# Prevents events in the parent from triggering, depending on llPassCollisions,
|
||||||
|
# therefore not SEF.
|
||||||
|
|
||||||
|
event collision_end( integer num_detected )
|
||||||
|
# Same as with collision().
|
||||||
|
|
||||||
|
event collision_start( integer num_detected )
|
||||||
|
# Same as with collision().
|
||||||
|
|
||||||
|
event control( key id, integer level, integer edge )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event dataserver( key queryid, string data )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event email( string time, string address, string subj, string message, integer num_left )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event experience_permissions( key agent )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event experience_permissions_denied( key agent, integer reason )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event http_request( key id, string method, string body )
|
||||||
|
# Since you can't see the URL, you can't notice the difference.
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event http_response( key request_id, integer status, list metadata, string body )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event land_collision( vector pos )
|
||||||
|
# Same as with collision().
|
||||||
|
|
||||||
|
event land_collision_end( vector pos )
|
||||||
|
# Same as with collision().
|
||||||
|
|
||||||
|
event land_collision_start( vector pos )
|
||||||
|
# Same as with collision().
|
||||||
|
|
||||||
|
event link_message( integer sender_num, integer num, string str, key id )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event listen( integer channel, string name, key id, string message )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event money( key id, integer amount )
|
||||||
|
# Adds Pay menu option, therefore not SEF.
|
||||||
|
|
||||||
|
event moving_end( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event moving_start( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event no_sensor( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event not_at_rot_target( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event not_at_target( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event object_rez( key id )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event on_rez( integer start_param )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event path_update( integer type, list reserved )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event remote_data( integer event_type, key channel, key message_id, string sender, integer idata, string sdata )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event run_time_permissions( integer perm )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event sensor( integer num_detected )
|
||||||
|
# There was a time when this was necessary for no_sensor() to trigger, but
|
||||||
|
# that's no longer the case.
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event state_entry( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event state_exit( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event timer( )
|
||||||
|
- SEF
|
||||||
|
|
||||||
|
event touch( integer num_detected )
|
||||||
|
# Adds hand cursor.
|
||||||
|
|
||||||
|
event touch_end( integer num_detected )
|
||||||
|
# Adds hand cursor.
|
||||||
|
|
||||||
|
event touch_start( integer num_detected )
|
||||||
|
# Adds hand cursor.
|
||||||
|
|
||||||
|
event transaction_result( key id, integer success, string data )
|
||||||
|
- SEF
|
||||||
|
|
|
@ -114,7 +114,7 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
u" overwriting: %s"
|
u" overwriting: %s"
|
||||||
% (linenum, ubuiltins, uname))
|
% (linenum, ubuiltins, uname))
|
||||||
del uname
|
del uname
|
||||||
events[name] = tuple(args)
|
events[name] = {'pt':tuple(args), 'NeedsData':True}
|
||||||
else:
|
else:
|
||||||
# Library functions go to the functions table. If
|
# Library functions go to the functions table. If
|
||||||
# they are implemented in lslfuncs.*, they get a
|
# they are implemented in lslfuncs.*, they get a
|
||||||
|
@ -243,6 +243,7 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
try:
|
try:
|
||||||
linenum = 0
|
linenum = 0
|
||||||
curr_fn = None
|
curr_fn = None
|
||||||
|
curr_ty = None
|
||||||
skipping = False
|
skipping = False
|
||||||
try:
|
try:
|
||||||
ufndata = fndata.decode(sys.getfilesystemencoding())
|
ufndata = fndata.decode(sys.getfilesystemencoding())
|
||||||
|
@ -265,30 +266,37 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
rettype = match_fn.group(1) if match_fn else None
|
rettype = match_fn.group(1) if match_fn else None
|
||||||
if match_fn and (rettype == 'void' or rettype in types):
|
if match_fn and (rettype in ('void', 'event') or rettype in types):
|
||||||
skipping = True # until proven otherwise
|
skipping = True # until proven otherwise
|
||||||
name = match_fn.group(2)
|
name = match_fn.group(2)
|
||||||
uname = name.decode('utf8')
|
uname = name.decode('utf8')
|
||||||
if name not in functions:
|
if (rettype == 'event' and name not in events
|
||||||
warning(u"Function %s is not in builtins, in %s line %d,"
|
or rettype != 'event' and name not in functions
|
||||||
|
):
|
||||||
|
warning(u"%s %s is not in builtins, in %s line %d,"
|
||||||
u" skipping."
|
u" skipping."
|
||||||
% (uname, ufndata, linenum))
|
% (u"Function" if rettype != 'event' else u"Event",
|
||||||
|
uname, ufndata, linenum))
|
||||||
continue
|
continue
|
||||||
rettype = rettype if rettype != 'void' else None
|
rettype = rettype if rettype != 'void' else None
|
||||||
if rettype != functions[name]['Type']:
|
if 'event' != rettype != functions[name]['Type']:
|
||||||
warning(u"Function %s returns invalid type, in %s line %d,"
|
warning(u"Function %s returns invalid type, in %s line %d,"
|
||||||
u" skipping."
|
u" skipping."
|
||||||
% (uname, ufndata, linenum))
|
% (uname, ufndata, linenum))
|
||||||
continue
|
continue
|
||||||
argnames = []
|
argnames = []
|
||||||
arglist = match_fn.group(3)
|
arglist = match_fn.group(3)
|
||||||
current_args = functions[name]['ParamTypes']
|
current_args = (functions[name]['ParamTypes']
|
||||||
|
if rettype != 'event'
|
||||||
|
else events[name]['pt'])
|
||||||
if arglist:
|
if arglist:
|
||||||
arglist = arglist.split(',')
|
arglist = arglist.split(',')
|
||||||
if len(current_args) != len(arglist):
|
if len(current_args) != len(arglist):
|
||||||
warning(u"Parameter list mismatch in %s line %d,"
|
warning(u"Parameter list mismatch in %s line %d,"
|
||||||
u" function %s. Skipping."
|
u" %s %s. Skipping."
|
||||||
% (ufndata, linenum, uname))
|
% (ufndata, linenum,
|
||||||
|
u"function" if rettype != 'event'
|
||||||
|
else u"event", uname))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bad = False # used to 'continue' at this loop level
|
bad = False # used to 'continue' at this loop level
|
||||||
|
@ -298,8 +306,10 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
argname = argmatch.group(2)
|
argname = argmatch.group(2)
|
||||||
if current_args[idx] != argtyp:
|
if current_args[idx] != argtyp:
|
||||||
warning(u"Parameter list mismatch in %s line %d,"
|
warning(u"Parameter list mismatch in %s line %d,"
|
||||||
u" function %s. Skipping."
|
u" %s %s. Skipping."
|
||||||
% (ufndata, linenum, uname))
|
% (ufndata, linenum,
|
||||||
|
u"function" if rettype != 'event'
|
||||||
|
else u"event", uname))
|
||||||
bad = True
|
bad = True
|
||||||
break
|
break
|
||||||
argnames.append(argname)
|
argnames.append(argname)
|
||||||
|
@ -308,22 +318,29 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
continue
|
continue
|
||||||
del bad
|
del bad
|
||||||
|
|
||||||
if 'NeedsData' not in functions[name]:
|
if 'NeedsData' not in (functions[name] if rettype != 'event'
|
||||||
warning(u"Duplicate function %s in %s line %d. Skipping."
|
else events[name]):
|
||||||
% (uname, ufndata, linenum))
|
warning(u"Duplicate %s %s in %s line %d. Skipping."
|
||||||
|
% (u"function" if rettype != 'event' else u"event",
|
||||||
|
uname, ufndata, linenum))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# passed all tests
|
# passed all tests
|
||||||
curr_fn = name
|
curr_fn = name
|
||||||
|
curr_ty = rettype
|
||||||
skipping = False
|
skipping = False
|
||||||
del functions[name]['NeedsData'], functions[name]['uns']
|
if curr_ty == 'event':
|
||||||
|
del events[name]['NeedsData']
|
||||||
|
else:
|
||||||
|
del functions[name]['NeedsData'], functions[name]['uns']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
match_flag = parse_flag_re.search(line)
|
match_flag = parse_flag_re.search(line)
|
||||||
if match_flag:
|
if match_flag:
|
||||||
if curr_fn is None and not skipping:
|
if curr_fn is None and not skipping:
|
||||||
warning(u"Flags present before any function in %s"
|
warning(u"Flags present before any function or event"
|
||||||
u" line %d: %s" % (ufndata, linenum, uline))
|
u" in %s line %d: %s"
|
||||||
|
% (ufndata, linenum, uline))
|
||||||
skipping = True
|
skipping = True
|
||||||
continue
|
continue
|
||||||
if not skipping:
|
if not skipping:
|
||||||
|
@ -333,8 +350,22 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
# We don't handle conditions yet. Take the
|
# We don't handle conditions yet. Take the
|
||||||
# condition as never met for now (every function
|
# condition as never met for now (every function
|
||||||
# that is conditionally SEF is taken as not SEF)
|
# that is conditionally SEF is taken as not SEF)
|
||||||
if not match_flag.group(3):
|
if curr_ty == 'event' and match_flag.group(3):
|
||||||
functions[curr_fn]['SEF'] = True
|
warning(u"Events do not support conditions"
|
||||||
|
u" in SEF flags, in line %d, event %s"
|
||||||
|
% (ufndata, linenum, ucurr_fn))
|
||||||
|
continue
|
||||||
|
elif curr_ty == 'event':
|
||||||
|
events[curr_fn]['SEF'] = True
|
||||||
|
else:
|
||||||
|
if not match_flag.group(3):
|
||||||
|
functions[curr_fn]['SEF'] = True
|
||||||
|
|
||||||
|
elif curr_ty == 'event':
|
||||||
|
warning(u"Events only support bare SEF flags"
|
||||||
|
u", in line %d, event %s. Omitting %s."
|
||||||
|
% (ufndata, linenum, ucurr_fn, uline))
|
||||||
|
continue
|
||||||
elif match_flag.group(2):
|
elif match_flag.group(2):
|
||||||
pass # return not handled yet
|
pass # return not handled yet
|
||||||
elif (match_flag.group(4)
|
elif (match_flag.group(4)
|
||||||
|
@ -394,7 +425,8 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
ui = i.decode('utf8')
|
ui = i.decode('utf8')
|
||||||
if 'NeedsData' in functions[i]:
|
if 'NeedsData' in functions[i]:
|
||||||
del functions[i]['NeedsData']
|
del functions[i]['NeedsData']
|
||||||
warning(u"Library data: Function %s has no data." % ui)
|
warning(u"Library data, file %s: Function %s has no data."
|
||||||
|
% (ufndata, ui))
|
||||||
if 'min' in functions[i] and 'max' in functions[i]:
|
if 'min' in functions[i] and 'max' in functions[i]:
|
||||||
if functions[i]['min'] > functions[i]['max']:
|
if functions[i]['min'] > functions[i]['max']:
|
||||||
warning(u"Library data: Function %s has min > max:"
|
warning(u"Library data: Function %s has min > max:"
|
||||||
|
@ -406,5 +438,11 @@ def LoadLibrary(builtins = None, fndata = None):
|
||||||
warning(u"Library data: Side-effect-free function %s contradicts"
|
warning(u"Library data: Side-effect-free function %s contradicts"
|
||||||
u" delay. Removing SEF." % ui)
|
u" delay. Removing SEF." % ui)
|
||||||
del functions[i]['SEF']
|
del functions[i]['SEF']
|
||||||
|
for i in events:
|
||||||
|
ui = i.decode('utf8')
|
||||||
|
if 'NeedsData' in events[i]:
|
||||||
|
del events[i]['NeedsData']
|
||||||
|
warning(u"Library data, file %s: Event %s has no data."
|
||||||
|
% (ufndata, ui))
|
||||||
|
|
||||||
return events, constants, functions
|
return events, constants, functions
|
||||||
|
|
|
@ -2208,7 +2208,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
# NOTE: Parse_events: This is a bit crude, as the error is given at the end of the param list.
|
# NOTE: Parse_events: This is a bit crude, as the error is given at the end of the param list.
|
||||||
# To do it correctly, we can pass the parameter list to Parse_optional_param_list().
|
# To do it correctly, we can pass the parameter list to Parse_optional_param_list().
|
||||||
if tuple(params[0]) != self.events[name]:
|
if tuple(params[0]) != self.events[name]['pt']:
|
||||||
raise EParseSyntax(self)
|
raise EParseSyntax(self)
|
||||||
self.locallabels = set()
|
self.locallabels = set()
|
||||||
body = self.Parse_code_block(None)
|
body = self.Parse_code_block(None)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue