diff --git a/lslopt/lsldeadcode.py b/lslopt/lsldeadcode.py index 337d3b4..3906b24 100644 --- a/lslopt/lsldeadcode.py +++ b/lslopt/lsldeadcode.py @@ -20,16 +20,6 @@ import lslfuncs class deadcode(object): - # Functions that cause the rest of the current block to never be executed - # e.g. default { state_entry() { llResetScript(); llSetPos(<3,3,3>); } } - # in that example, llSetPos is dead code because llResetScript does not let - # it execute. llRemoveInventory(llGetScriptName()), llDetachFromAvatar() - # and llDie() come close, but evidence shows that it's not the case and the - # script can execute some more lines before stopping. - # llScriptState(..., FALSE) allows resuming after it, so whatever comes - # next isn't really dead code. - # TODO: check if there are any more than this one. - TerminatorFuncs = ('llResetScript',) def MarkReferences(self, node): """Marks each node it passes through as executed (X), and each variable @@ -185,7 +175,7 @@ class deadcode(object): self.MarkReferences(self.tree[sym['Loc']]) node['X'] = self.tree[sym['Loc']]['X'] else: - node['X'] = node['name'] not in self.TerminatorFuncs + node['X'] = 'stop' not in sym # Note that JUMP analysis is incomplete. To do it correctly, we # should follow the jump right to its destination, in order to know # if that branch leads to a RETURN or completely stops the event. diff --git a/lslopt/lslextrafuncs.py b/lslopt/lslextrafuncs.py index 61c2503..0871366 100644 --- a/lslopt/lslextrafuncs.py +++ b/lslopt/lslextrafuncs.py @@ -23,16 +23,12 @@ from lslbasefuncs import ELSLCantCompute, fi,ff,fs,fk,v2f,q2f,fl, \ TOUCH_INVALID_TEXCOORD, cond ff, q2f # keep pyflakes happy as these are not used -TouchEvents = ('touch', 'touch_start', 'touch_end') -DetectionEvents = ('touch', 'touch_start', 'touch_end', - 'collision', 'collision_start', 'collision_end', - 'sensor') -GetEnvSettings = ('agent_limit', 'dynamic_pathfinding', 'estate_id', +GetEnvSettings = frozenset(('agent_limit', 'dynamic_pathfinding', 'estate_id', 'estate_name', 'frame_number', 'region_cpu_ratio', 'region_idle', 'region_product_name', 'region_product_sku', 'region_start_time', 'sim_channel', 'sim_version', 'simulator_hostname', 'region_max_prims', # - 'region_object_bonus') # + 'region_object_bonus')) # xp_error_messages = { -1:u'unknown error id', @@ -68,111 +64,111 @@ def llClearLinkMedia(link, face): return 0 raise ELSLCantCompute -def llDetectedGrab(idx, event=None): +def llDetectedGrab(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event == 'touch' or event is None): + if 0 <= idx <= 15 and (evsym is None or 'grab' in evsym): raise ELSLCantCompute return ZERO_VECTOR -def llDetectedGroup(idx, event=None): +def llDetectedGroup(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return 0 -def llDetectedKey(idx, event=None): +def llDetectedKey(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return Key(NULL_KEY) -def llDetectedLinkNumber(idx, event=None): +def llDetectedLinkNumber(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return 0 -def llDetectedName(idx, event=None): +def llDetectedName(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return NULL_KEY -def llDetectedOwner(idx, event=None): +def llDetectedOwner(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return Key(NULL_KEY) -def llDetectedPos(idx, event=None): +def llDetectedPos(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return ZERO_VECTOR -def llDetectedRot(idx, event=None): +def llDetectedRot(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return ZERO_ROTATION -def llDetectedTouchBinormal(idx, event=None): +def llDetectedTouchBinormal(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in TouchEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym): raise ELSLCantCompute return ZERO_VECTOR -def llDetectedTouchFace(idx, event=None): +def llDetectedTouchFace(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in TouchEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym): raise ELSLCantCompute - return -1 if event in DetectionEvents and 0 <= idx <= 15 else 0 + return -1 if 'detect' in evsym and 0 <= idx <= 15 else 0 -def llDetectedTouchNormal(idx, event=None): +def llDetectedTouchNormal(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in TouchEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym): raise ELSLCantCompute return ZERO_VECTOR -def llDetectedTouchPos(idx, event=None): +def llDetectedTouchPos(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in TouchEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'touch' in evsym): raise ELSLCantCompute return ZERO_VECTOR -def llDetectedTouchST(idx, event=None): +def llDetectedTouchST(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event is None or event in DetectionEvents): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): # In detection events that are not touch events, it returns # TOUCH_INVALID_TEXCOORD if idx < num, else ZERO_VECTOR, # but we only know that num >= 1. - if idx == 0 and event is not None and event not in TouchEvents: + if idx == 0 and evsym is not None and 'touch' not in evsym: # index 0 always exists, so we know the result return TOUCH_INVALID_TEXCOORD raise ELSLCantCompute return ZERO_VECTOR -def llDetectedTouchUV(idx, event=None): +def llDetectedTouchUV(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event is None or event in DetectionEvents): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): # In detection events that are not touch events, it returns # TOUCH_INVALID_TEXCOORD if idx < num, else ZERO_VECTOR, # but we only know that num >= 1. - if idx == 0 and event is not None and event not in TouchEvents: + if idx == 0 and evsym is not None and 'touch' not in evsym: # index 0 always exists, so we know the result return TOUCH_INVALID_TEXCOORD raise ELSLCantCompute return ZERO_VECTOR -def llDetectedType(idx, event=None): +def llDetectedType(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return 0 -def llDetectedVel(idx, event=None): +def llDetectedVel(idx, evsym=None): idx = fi(idx) - if 0 <= idx <= 15 and (event in DetectionEvents or event is None): + if 0 <= idx <= 15 and (evsym is None or 'detect' in evsym): raise ELSLCantCompute return ZERO_VECTOR diff --git a/lslopt/lslfoldconst.py b/lslopt/lslfoldconst.py index ca64ba3..0c2f087 100644 --- a/lslopt/lslfoldconst.py +++ b/lslopt/lslfoldconst.py @@ -267,7 +267,7 @@ class foldconst(object): return # Nothing to do if it's already simplified. child = node['ch'] if 'ch' in node else None - if nt == 'FNCALL' and node['name'] == 'llStringLength': + if nt == 'FNCALL' and 'strlen' in self.symtab[0][node['name']]: # llStringLength(expr) -> !(expr == "") node = {'nt':'==', 't':'integer', 'ch':[child[0], @@ -1427,8 +1427,10 @@ class foldconst(object): try: # May raise ELSLCantCompute - if name[:10] == 'llDetected': - value = fn(*args, event=self.CurEvent) + if 'detect' in self.symtab[0][name]: + value = fn(*args, + evsym=None if self.CurEvent is None + else self.events[self.CurEvent]) else: value = fn(*args) finally: diff --git a/lslopt/lsloptimizer.py b/lslopt/lsloptimizer.py index 7492463..e8191ae 100644 --- a/lslopt/lsloptimizer.py +++ b/lslopt/lsloptimizer.py @@ -99,3 +99,6 @@ class optimizer(foldconst, renamer, deadcode, lastpass): del self.tree del self.symtab return treesymtab + + def __init__(self, lib): + self.events = lib[0] diff --git a/main.py b/main.py index 3a1eb1d..2238b21 100755 --- a/main.py +++ b/main.py @@ -662,7 +662,7 @@ def main(argv): return 1 del p, script - opt = optimizer() + opt = optimizer(lib) ts = opt.optimize(ts, options) del opt diff --git a/testparser.py b/testparser.py index 5ec6af6..3fce13a 100644 --- a/testparser.py +++ b/testparser.py @@ -248,8 +248,9 @@ class Test02_Parser(UnitTestCase): class Test03_Optimizer(UnitTestCase): def setUp(self): - self.parser = parser(lslloadlib.LoadLibrary()) - self.opt = optimizer() + lib = lslloadlib.LoadLibrary() + self.parser = parser(lib) + self.opt = optimizer(lib) self.outscript = outscript() def test_coverage(self):