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/>.
|
||||
|
||||
# This file provides information to the optimizer about the behaviour of
|
||||
# functions. This knowledge can help perform a better job at optimizing.
|
||||
# All functions present in builtins.txt must be here and vice versa.
|
||||
# functions and events. This knowledge can help perform a better job at
|
||||
# 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,
|
||||
# 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:
|
||||
#
|
||||
|
@ -1454,3 +1456,128 @@ string llXorBase64Strings( string str1, string str2 )
|
|||
|
||||
string llXorBase64StringsCorrect( string str1, string str2 )
|
||||
- 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"
|
||||
% (linenum, ubuiltins, uname))
|
||||
del uname
|
||||
events[name] = tuple(args)
|
||||
events[name] = {'pt':tuple(args), 'NeedsData':True}
|
||||
else:
|
||||
# Library functions go to the functions table. If
|
||||
# they are implemented in lslfuncs.*, they get a
|
||||
|
@ -243,6 +243,7 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
try:
|
||||
linenum = 0
|
||||
curr_fn = None
|
||||
curr_ty = None
|
||||
skipping = False
|
||||
try:
|
||||
ufndata = fndata.decode(sys.getfilesystemencoding())
|
||||
|
@ -265,30 +266,37 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
continue
|
||||
|
||||
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
|
||||
name = match_fn.group(2)
|
||||
uname = name.decode('utf8')
|
||||
if name not in functions:
|
||||
warning(u"Function %s is not in builtins, in %s line %d,"
|
||||
if (rettype == 'event' and name not in events
|
||||
or rettype != 'event' and name not in functions
|
||||
):
|
||||
warning(u"%s %s is not in builtins, in %s line %d,"
|
||||
u" skipping."
|
||||
% (uname, ufndata, linenum))
|
||||
% (u"Function" if rettype != 'event' else u"Event",
|
||||
uname, ufndata, linenum))
|
||||
continue
|
||||
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,"
|
||||
u" skipping."
|
||||
% (uname, ufndata, linenum))
|
||||
continue
|
||||
argnames = []
|
||||
arglist = match_fn.group(3)
|
||||
current_args = functions[name]['ParamTypes']
|
||||
current_args = (functions[name]['ParamTypes']
|
||||
if rettype != 'event'
|
||||
else events[name]['pt'])
|
||||
if arglist:
|
||||
arglist = arglist.split(',')
|
||||
if len(current_args) != len(arglist):
|
||||
warning(u"Parameter list mismatch in %s line %d,"
|
||||
u" function %s. Skipping."
|
||||
% (ufndata, linenum, uname))
|
||||
u" %s %s. Skipping."
|
||||
% (ufndata, linenum,
|
||||
u"function" if rettype != 'event'
|
||||
else u"event", uname))
|
||||
continue
|
||||
|
||||
bad = False # used to 'continue' at this loop level
|
||||
|
@ -298,8 +306,10 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
argname = argmatch.group(2)
|
||||
if current_args[idx] != argtyp:
|
||||
warning(u"Parameter list mismatch in %s line %d,"
|
||||
u" function %s. Skipping."
|
||||
% (ufndata, linenum, uname))
|
||||
u" %s %s. Skipping."
|
||||
% (ufndata, linenum,
|
||||
u"function" if rettype != 'event'
|
||||
else u"event", uname))
|
||||
bad = True
|
||||
break
|
||||
argnames.append(argname)
|
||||
|
@ -308,22 +318,29 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
continue
|
||||
del bad
|
||||
|
||||
if 'NeedsData' not in functions[name]:
|
||||
warning(u"Duplicate function %s in %s line %d. Skipping."
|
||||
% (uname, ufndata, linenum))
|
||||
if 'NeedsData' not in (functions[name] if rettype != 'event'
|
||||
else events[name]):
|
||||
warning(u"Duplicate %s %s in %s line %d. Skipping."
|
||||
% (u"function" if rettype != 'event' else u"event",
|
||||
uname, ufndata, linenum))
|
||||
continue
|
||||
|
||||
# passed all tests
|
||||
curr_fn = name
|
||||
curr_ty = rettype
|
||||
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:
|
||||
match_flag = parse_flag_re.search(line)
|
||||
if match_flag:
|
||||
if curr_fn is None and not skipping:
|
||||
warning(u"Flags present before any function in %s"
|
||||
u" line %d: %s" % (ufndata, linenum, uline))
|
||||
warning(u"Flags present before any function or event"
|
||||
u" in %s line %d: %s"
|
||||
% (ufndata, linenum, uline))
|
||||
skipping = True
|
||||
continue
|
||||
if not skipping:
|
||||
|
@ -333,8 +350,22 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
# We don't handle conditions yet. Take the
|
||||
# condition as never met for now (every function
|
||||
# that is conditionally SEF is taken as not SEF)
|
||||
if not match_flag.group(3):
|
||||
functions[curr_fn]['SEF'] = True
|
||||
if curr_ty == 'event' and match_flag.group(3):
|
||||
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):
|
||||
pass # return not handled yet
|
||||
elif (match_flag.group(4)
|
||||
|
@ -394,7 +425,8 @@ def LoadLibrary(builtins = None, fndata = None):
|
|||
ui = i.decode('utf8')
|
||||
if 'NeedsData' in functions[i]:
|
||||
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 functions[i]['min'] > functions[i]['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"
|
||||
u" delay. Removing SEF." % ui)
|
||||
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
|
||||
|
|
|
@ -2208,7 +2208,7 @@ list lazy_list_set(list L, integer i, list v)
|
|||
self.NextToken()
|
||||
# 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().
|
||||
if tuple(params[0]) != self.events[name]:
|
||||
if tuple(params[0]) != self.events[name]['pt']:
|
||||
raise EParseSyntax(self)
|
||||
self.locallabels = set()
|
||||
body = self.Parse_code_block(None)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue