From 76f483fc118a19ca4647a04d2e130bab83de6389 Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Wed, 26 Dec 2018 19:47:22 +0100 Subject: [PATCH] Add scope field to {} nodes Since we need to add variables, we need to know which scope to add them to. Add this information to the {} node, which is what creates a new scope. An alternative would be to scan for any variable or label declaration within the braces and use that or create a new one if none, which is more expensive and may waste symbol tables. --- lslopt/lslfoldconst.py | 15 +++++++++++---- lslopt/lsllastpass.py | 4 +++- lslopt/lslparse.py | 27 ++++++++++++++++++--------- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/lslopt/lslfoldconst.py b/lslopt/lslfoldconst.py index d67c158..2ba5357 100644 --- a/lslopt/lslfoldconst.py +++ b/lslopt/lslfoldconst.py @@ -199,7 +199,9 @@ class foldconst(object): if (node.nt == 'FNCALL' and 'Loc' in self.symtab[0][node.name] and self.FnSEF(node) ): - parent[index] = nr(nt='{}', t=None, ch=[ + scope = len(self.symtab) + self.symtab.append({}) + parent[index] = nr(nt='{}', t=None, scope=scope, ch=[ nr(nt='EXPR', t=x.t, ch=[x]) for x in node.ch]) self.FoldTree(parent, index) return @@ -1662,9 +1664,11 @@ class foldconst(object): self.FoldTree(child, idx) if not child: # All events removed - add a dummy timer() + scope = len(self.symtab) + self.symtab.append({}) child.append(nr(nt='FNDEF', t=None, name='timer', - pscope=0, ptypes=[], pnames=[], - ch=[nr(nt='{}', t=None, ch=[])] + pscope=scope, ptypes=[], pnames=[], + ch=[nr(nt='{}', t=None, scope=scope, ch=[])] )) return @@ -1867,7 +1871,10 @@ class foldconst(object): # We're in the case where there are expressions. If any # remain, they are not SEF (or they would have been # removed earlier) so don't mark this node as SEF. - parent[index] = nr(nt='{}', t=None, ch=exprlist) + scope = len(self.symtab) + self.symtab.append({}) + parent[index] = nr(nt='{}', t=None, scope=scope, + ch=exprlist) else: parent[index] = nr(nt=';', t=None, SEF=True) return diff --git a/lslopt/lsllastpass.py b/lslopt/lsllastpass.py index 0a9e9a9..9251258 100644 --- a/lslopt/lsllastpass.py +++ b/lslopt/lsllastpass.py @@ -124,7 +124,9 @@ class lastpass(object): # function (must be the result of optimization). # Insert dummy IF(1){...} statement covering the whole function # (if it returs a value, insert a return statement too). - child[0] = nr(nt='{}', t=None, ch=[ + scope = len(self.symtab) + self.symtab.append({}) + child[0] = nr(nt='{}', t=None, scope=scope, ch=[ nr(nt='IF', t=None, ch=[ nr(nt='CONST', t='integer', value=1, SEF=True), child[0] diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index 86ac786..f7e51f2 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -994,6 +994,8 @@ class parser(object): if 'lazy_list_set' not in self.symtab[0]: self.PushScope() paramscope = self.scopeindex + self.PushScope() + blockscope = self.scopeindex params = (['list', 'integer', 'list'], ['L', 'i', 'v']) self.AddSymbol('f', 0, 'lazy_list_set', Loc=self.usedspots, @@ -1025,6 +1027,7 @@ list lazy_list_set(list L, integer i, list v) nr(nt='{}' , t=None , LIR=True + , scope=blockscope , ch=[ nr(nt='WHILE' , t=None @@ -1118,7 +1121,7 @@ list lazy_list_set(list L, integer i, list v) ] ) self.usedspots += 1 - #self.PopScope() # no locals + self.PopScope() self.PopScope() if expr.t is None: @@ -1873,8 +1876,9 @@ list lazy_list_set(list L, integer i, list v) last = self.breakstack.pop() if last[2]: - ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None, - name=last[0], scope=last[1])]) + assert last[1] is not None + ret = nr(nt='{}', t=None, scope=last[1], ch=[ret, + nr(nt='@', t=None, name=last[0], scope=last[1])]) self.AddSymbol('l', last[1], last[0], ref=last[2]) self.PopScope() return ret @@ -1917,8 +1921,9 @@ list lazy_list_set(list L, integer i, list v) last = self.breakstack.pop() if last[2]: - ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None, - name=last[0], scope=last[1])]) + assert last[1] is not None + ret = nr(nt='{}', t=None, scope=last[1], ch=[ret, + nr(nt='@', t=None, name=last[0], scope=last[1])]) self.AddSymbol('l', last[1], last[0], ref=last[2]) self.PopScope() return ret @@ -1968,8 +1973,9 @@ list lazy_list_set(list L, integer i, list v) last = self.breakstack.pop() if last[2]: - ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None, - name=last[0], scope=last[1])]) + assert last[1] is not None + ret = nr(nt='{}', t=None, scope=last[1], ch=[ret, + nr(nt='@', t=None, name=last[0], scope=last[1])]) self.AddSymbol('l', last[1], last[0], ref=last[2]) self.PopScope() return ret @@ -2080,7 +2086,7 @@ list lazy_list_set(list L, integer i, list v) if last[2]: blk.append(nr(nt='@', name=brk, scope=blkscope)) self.AddSymbol('l', blkscope, brk, ref=last[2]) - return nr(nt='{}', t=None, ch=prelude + blk) + return nr(nt='{}', t=None, scope=blkscope, ch=prelude + blk) if tok0 == 'CASE': if not InsideSwitch: @@ -2225,12 +2231,13 @@ list lazy_list_set(list L, integer i, list v) LastIsReturn = getattr(stmt, 'LIR', False) body.append(stmt) + scope_braces = self.scopeindex self.PopScope() self.expect('}') self.NextToken() - node = nr(nt='{}', t=None, ch=body) + node = nr(nt='{}', t=None, scope=scope_braces, ch=body) if LastIsReturn: node.LIR = True return node @@ -2784,6 +2791,8 @@ list lazy_list_set(list L, integer i, list v) # Stack to track the labels for break targets, their scope table index, # and whether they are used. + # Elements are sublist with 0 = destination label name, 1 = scope for + # that label, and 2 = reference count of the label. self.breakstack = [] # Stack to track the labels for continue targets, their scope index, # and whether they are used.