mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Get rid of DoesSomething() in favour of SEF
The missing bit was to mark labels are SEF when they are not referenced. Label references are now counted at parse time, enabling us to do this. Also, make FoldStmt clearer when the node is an expression.
This commit is contained in:
parent
a93ea0ca19
commit
285c7172fd
3 changed files with 71 additions and 55 deletions
|
@ -384,6 +384,12 @@ class deadcode(object):
|
||||||
node = curnode.ch[index]
|
node = curnode.ch[index]
|
||||||
|
|
||||||
if not hasattr(node, 'X'):
|
if not hasattr(node, 'X'):
|
||||||
|
if curnode.ch[index].nt == 'JUMP':
|
||||||
|
# Decrease label reference count
|
||||||
|
scope = curnode.ch[index].scope
|
||||||
|
name = curnode.ch[index].name
|
||||||
|
assert self.symtab[scope][name]['ref'] > 0
|
||||||
|
self.symtab[scope][name]['ref'] -= 1
|
||||||
del curnode.ch[index]
|
del curnode.ch[index]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -107,25 +107,6 @@ class foldconst(object):
|
||||||
else:
|
else:
|
||||||
idx += 1
|
idx += 1
|
||||||
|
|
||||||
def DoesSomething(self, node, labels = False):
|
|
||||||
"""Tell if a subtree does something or is just empty statements
|
|
||||||
(a pure combination of ';' and '{}'). Labels are the top level are
|
|
||||||
considered to do something if labels is True, and vice versa.
|
|
||||||
|
|
||||||
Not to be confused with lslparse.does_something which always includes
|
|
||||||
labels, and applies to a block's statement list, not to a node.
|
|
||||||
"""
|
|
||||||
maybe_label = ';' if labels else '@'
|
|
||||||
if maybe_label != node.nt != ';' and not node.SEF:
|
|
||||||
if node.nt == '{}':
|
|
||||||
for subnode in node.ch:
|
|
||||||
# Labels embedded in {} are not reachable. They do nothing.
|
|
||||||
if self.DoesSomething(subnode):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def CompareTrees(self, node1, node2):
|
def CompareTrees(self, node1, node2):
|
||||||
"""Try to compare two subtrees to see if they are equivalent."""
|
"""Try to compare two subtrees to see if they are equivalent."""
|
||||||
# They MUST be SEF and stable.
|
# They MUST be SEF and stable.
|
||||||
|
@ -186,8 +167,6 @@ class foldconst(object):
|
||||||
def FoldStmt(self, parent, index):
|
def FoldStmt(self, parent, index):
|
||||||
"""Simplify a statement."""
|
"""Simplify a statement."""
|
||||||
node = parent[index]
|
node = parent[index]
|
||||||
if node.nt == 'EXPR':
|
|
||||||
node = node.ch[0]
|
|
||||||
# If the statement is side-effect-free, remove it as it does nothing.
|
# If the statement is side-effect-free, remove it as it does nothing.
|
||||||
if node.SEF:
|
if node.SEF:
|
||||||
# When a statement is side-effect free, it does nothing except
|
# When a statement is side-effect free, it does nothing except
|
||||||
|
@ -205,6 +184,8 @@ class foldconst(object):
|
||||||
# Other unary and binary operators are side effect-free.
|
# Other unary and binary operators are side effect-free.
|
||||||
parent[index] = nr(nt=';', t=None, SEF=True)
|
parent[index] = nr(nt=';', t=None, SEF=True)
|
||||||
return
|
return
|
||||||
|
if node.nt == 'EXPR':
|
||||||
|
node = node.ch[0]
|
||||||
# Post-increments take more space than pre-increments.
|
# Post-increments take more space than pre-increments.
|
||||||
if node.nt in ('V++', 'V--'):
|
if node.nt in ('V++', 'V--'):
|
||||||
node.nt = '++V' if node.nt == 'V++' else '--V';
|
node.nt = '++V' if node.nt == 'V++' else '--V';
|
||||||
|
@ -1525,14 +1506,15 @@ class foldconst(object):
|
||||||
self.CurEvent = node.name
|
self.CurEvent = node.name
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
|
|
||||||
# Test if the event is empty and SEF, and remove it if so.
|
# Test if the event is SEF and does nothing, and remove it if so.
|
||||||
if (not hasattr(node, 'scope') and not self.DoesSomething(child[0])
|
if (not hasattr(node, 'scope') and child[0].SEF
|
||||||
and 'SEF' in self.events[node.name]
|
and 'SEF' in self.events[node.name]
|
||||||
):
|
):
|
||||||
# Delete ourselves.
|
# Delete ourselves.
|
||||||
del parent[index]
|
del parent[index]
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Delete trailing bare RETURNs.
|
||||||
# TODO: This works, but analysis of code paths is DCR's thing
|
# TODO: This works, but analysis of code paths is DCR's thing
|
||||||
# and this is incomplete, e.g. x(){{return;}} is not detected.
|
# and this is incomplete, e.g. x(){{return;}} is not detected.
|
||||||
while child[0].ch:
|
while child[0].ch:
|
||||||
|
@ -1621,7 +1603,7 @@ class foldconst(object):
|
||||||
self.FoldTree(child, 2)
|
self.FoldTree(child, 2)
|
||||||
self.FoldStmt(child, 2)
|
self.FoldStmt(child, 2)
|
||||||
# Check if it makes sense to swap if and else branches
|
# Check if it makes sense to swap if and else branches
|
||||||
if (self.DoesSomething(child[2])):
|
if not child[2].SEF:
|
||||||
# Check if we can gain something by negating the
|
# Check if we can gain something by negating the
|
||||||
# expression.
|
# expression.
|
||||||
# Swap 'if' and 'else' branch when the condition has
|
# Swap 'if' and 'else' branch when the condition has
|
||||||
|
@ -1637,10 +1619,10 @@ class foldconst(object):
|
||||||
child[0].nt = '^'
|
child[0].nt = '^'
|
||||||
child[1], child[2] = child[2], child[1]
|
child[1], child[2] = child[2], child[1]
|
||||||
# Re-test just in case we swapped in the previous check.
|
# Re-test just in case we swapped in the previous check.
|
||||||
if not self.DoesSomething(child[2]):
|
if child[2].SEF:
|
||||||
# no point in "... else ;" - remove else branch
|
# no point in "... else ;" - remove else branch
|
||||||
del child[2]
|
del child[2]
|
||||||
if not self.DoesSomething(child[1]):
|
if child[1].SEF:
|
||||||
# if (X) ; -> X;
|
# if (X) ; -> X;
|
||||||
if len(child) == 2:
|
if len(child) == 2:
|
||||||
parent[index] = nr(nt='EXPR', t=child[0].t,
|
parent[index] = nr(nt='EXPR', t=child[0].t,
|
||||||
|
@ -1676,7 +1658,7 @@ class foldconst(object):
|
||||||
# out anyway. Otherwise we just don't know if it may be infinite,
|
# out anyway. Otherwise we just don't know if it may be infinite,
|
||||||
# even if every component is SEF.
|
# even if every component is SEF.
|
||||||
|
|
||||||
if self.DoesSomething(child[1]):
|
if not child[1].SEF:
|
||||||
|
|
||||||
self.ExpandCondition(child, 0)
|
self.ExpandCondition(child, 0)
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
|
@ -1822,7 +1804,12 @@ class foldconst(object):
|
||||||
node.SEF = True
|
node.SEF = True
|
||||||
return
|
return
|
||||||
|
|
||||||
if nt in ('JUMP', '@', 'V++', 'V--', '--V', '++V', 'LAMBDA'):
|
if nt == '@':
|
||||||
|
# SEF if there are no JUMPs jumping to it
|
||||||
|
node.SEF = not self.symtab[node.scope][node.name]['ref']
|
||||||
|
return
|
||||||
|
|
||||||
|
if nt in ('JUMP', 'V++', 'V--', '--V', '++V', 'LAMBDA'):
|
||||||
# Except LAMBDA, these all have side effects, as in, can't be
|
# Except LAMBDA, these all have side effects, as in, can't be
|
||||||
# eliminated as statements.
|
# eliminated as statements.
|
||||||
# LAMBDA can't be eliminated without scrolling Loc's.
|
# LAMBDA can't be eliminated without scrolling Loc's.
|
||||||
|
|
|
@ -1712,12 +1712,13 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if name in self.locallabels or self.shrinknames:
|
if name in self.locallabels or self.shrinknames:
|
||||||
# Generate a new unique name and attach it to the symbol.
|
# Generate a new unique name and attach it to the symbol.
|
||||||
unique = self.GenerateLabel()
|
unique = self.GenerateLabel()
|
||||||
self.AddSymbol('l', self.scopeindex, name, NewName=unique)
|
self.AddSymbol('l', self.scopeindex, name, NewName=unique,
|
||||||
|
ref=0)
|
||||||
else:
|
else:
|
||||||
# Use the existing name. Faster and more readable.
|
# Use the existing name. Faster and more readable.
|
||||||
unique = name
|
unique = name
|
||||||
self.locallabels.add(name)
|
self.locallabels.add(name)
|
||||||
self.AddSymbol('l', self.scopeindex, name)
|
self.AddSymbol('l', self.scopeindex, name, ref=0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Duplicate labels disallowed.
|
# Duplicate labels disallowed.
|
||||||
|
@ -1726,7 +1727,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if name in self.locallabels:
|
if name in self.locallabels:
|
||||||
raise EParseDuplicateLabel(self)
|
raise EParseDuplicateLabel(self)
|
||||||
self.locallabels.add(name)
|
self.locallabels.add(name)
|
||||||
self.AddSymbol('l', self.scopeindex, name)
|
self.AddSymbol('l', self.scopeindex, name, ref=0)
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
self.expect(';')
|
self.expect(';')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
|
@ -1745,6 +1746,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
jumpnode))
|
jumpnode))
|
||||||
else:
|
else:
|
||||||
jumpnode.scope = sym['Scope']
|
jumpnode.scope = sym['Scope']
|
||||||
|
sym['ref'] += 1
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
self.expect(';')
|
self.expect(';')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
|
@ -1833,8 +1835,11 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
# if (a) { while (b) { ... jump label; } @label; }
|
# if (a) { while (b) { ... jump label; } @label; }
|
||||||
self.PushScope()
|
self.PushScope()
|
||||||
|
|
||||||
self.breakstack.append([self.GenerateLabel(), self.scopeindex, False])
|
self.breakstack.append([self.GenerateLabel(), self.scopeindex,
|
||||||
self.continuestack.append([self.GenerateLabel(), None, False])
|
0])
|
||||||
|
# Scope still unknown; if a block is opened, Parse_code_block()
|
||||||
|
# will fill it in.
|
||||||
|
self.continuestack.append([self.GenerateLabel(), None, 0])
|
||||||
self.expect('(')
|
self.expect('(')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
condition = self.Parse_expression()
|
condition = self.Parse_expression()
|
||||||
|
@ -1862,13 +1867,13 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
assert ret.ch[1].nt == '{}'
|
assert ret.ch[1].nt == '{}'
|
||||||
ret.ch[1].ch.append(nr(nt='@', t=None, name=last[0],
|
ret.ch[1].ch.append(nr(nt='@', t=None, name=last[0],
|
||||||
scope=last[1]))
|
scope=last[1]))
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
|
|
||||||
last = self.breakstack.pop()
|
last = self.breakstack.pop()
|
||||||
if last[2]:
|
if last[2]:
|
||||||
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
||||||
name=last[0], scope=last[1])])
|
name=last[0], scope=last[1])])
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
self.PopScope()
|
self.PopScope()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -1877,14 +1882,19 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if self.breakcont:
|
if self.breakcont:
|
||||||
self.PushScope()
|
self.PushScope()
|
||||||
|
|
||||||
self.breakstack.append([self.GenerateLabel(), self.scopeindex, False])
|
self.breakstack.append([self.GenerateLabel(), self.scopeindex,
|
||||||
self.continuestack.append([self.GenerateLabel(), None, False])
|
0])
|
||||||
|
# Scope still unknown; if a block is opened, Parse_code_block()
|
||||||
|
# will fill it in.
|
||||||
|
self.continuestack.append([self.GenerateLabel(), None, 0])
|
||||||
if self.breakcont and self.tok[0] == '@':
|
if self.breakcont and self.tok[0] == '@':
|
||||||
self.PopScope()
|
self.PopScope()
|
||||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True, InsideLoop = True)
|
stmt = self.Parse_statement(ReturnType, AllowStSw = True,
|
||||||
|
InsideLoop = True)
|
||||||
self.PushScope()
|
self.PushScope()
|
||||||
else:
|
else:
|
||||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True, InsideLoop = True)
|
stmt = self.Parse_statement(ReturnType, AllowStSw = True,
|
||||||
|
InsideLoop = True)
|
||||||
self.expect('WHILE')
|
self.expect('WHILE')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
self.expect('(')
|
self.expect('(')
|
||||||
|
@ -1901,13 +1911,13 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
assert ret.ch[0].nt == '{}'
|
assert ret.ch[0].nt == '{}'
|
||||||
ret.ch[0].ch.append(nr(nt='@', t=None, name=last[0],
|
ret.ch[0].ch.append(nr(nt='@', t=None, name=last[0],
|
||||||
scope=last[1]))
|
scope=last[1]))
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
|
|
||||||
last = self.breakstack.pop()
|
last = self.breakstack.pop()
|
||||||
if last[2]:
|
if last[2]:
|
||||||
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
||||||
name=last[0], scope=last[1])])
|
name=last[0], scope=last[1])])
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
self.PopScope()
|
self.PopScope()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -1916,8 +1926,11 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if self.breakcont:
|
if self.breakcont:
|
||||||
self.PushScope()
|
self.PushScope()
|
||||||
|
|
||||||
self.breakstack.append([self.GenerateLabel(), self.scopeindex, False])
|
self.breakstack.append([self.GenerateLabel(), self.scopeindex,
|
||||||
self.continuestack.append([self.GenerateLabel(), None, False])
|
0])
|
||||||
|
# Scope still unknown; if a block is opened, Parse_code_block()
|
||||||
|
# will fill it in.
|
||||||
|
self.continuestack.append([self.GenerateLabel(), None, 0])
|
||||||
self.expect('(')
|
self.expect('(')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
initializer = self.Parse_optional_expression_list()
|
initializer = self.Parse_optional_expression_list()
|
||||||
|
@ -1931,10 +1944,12 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
if self.breakcont and self.tok[0] == '@':
|
if self.breakcont and self.tok[0] == '@':
|
||||||
self.PopScope()
|
self.PopScope()
|
||||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True, InsideLoop = True)
|
stmt = self.Parse_statement(ReturnType, AllowStSw = True,
|
||||||
|
InsideLoop = True)
|
||||||
self.PushScope()
|
self.PushScope()
|
||||||
else:
|
else:
|
||||||
stmt = self.Parse_statement(ReturnType, AllowStSw = True, InsideLoop = True)
|
stmt = self.Parse_statement(ReturnType, AllowStSw = True,
|
||||||
|
InsideLoop = True)
|
||||||
ret = nr(nt='FOR', t=None,
|
ret = nr(nt='FOR', t=None,
|
||||||
ch=[nr(nt='EXPRLIST', t=None, ch=initializer),
|
ch=[nr(nt='EXPRLIST', t=None, ch=initializer),
|
||||||
condition,
|
condition,
|
||||||
|
@ -1947,13 +1962,13 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
assert ret.ch[3].nt == '{}'
|
assert ret.ch[3].nt == '{}'
|
||||||
ret.ch[3].ch.append(nr(nt='@', t=None, name=last[0],
|
ret.ch[3].ch.append(nr(nt='@', t=None, name=last[0],
|
||||||
scope=last[1]))
|
scope=last[1]))
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
|
|
||||||
last = self.breakstack.pop()
|
last = self.breakstack.pop()
|
||||||
if last[2]:
|
if last[2]:
|
||||||
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
ret = nr(nt='{}', t=None, ch=[ret, nr(nt='@', t=None,
|
||||||
name=last[0], scope=last[1])])
|
name=last[0], scope=last[1])])
|
||||||
self.AddSymbol('l', last[1], last[0])
|
self.AddSymbol('l', last[1], last[0], ref=last[2])
|
||||||
self.PopScope()
|
self.PopScope()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -1965,7 +1980,8 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
self.expect(')')
|
self.expect(')')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
brk = self.GenerateLabel()
|
brk = self.GenerateLabel()
|
||||||
self.breakstack.append([brk, None, False])
|
# Scope is determined in Parse_code_block()
|
||||||
|
self.breakstack.append([brk, None, 0])
|
||||||
blk = self.Parse_code_block(ReturnType, AllowStSw = AllowStSw,
|
blk = self.Parse_code_block(ReturnType, AllowStSw = AllowStSw,
|
||||||
InsideSwitch = True, InsideLoop = InsideLoop)
|
InsideSwitch = True, InsideLoop = InsideLoop)
|
||||||
blkscope = self.breakstack[-1][1]
|
blkscope = self.breakstack[-1][1]
|
||||||
|
@ -1998,14 +2014,14 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if blk[idx].nt == 'CASE':
|
if blk[idx].nt == 'CASE':
|
||||||
lbl = self.GenerateLabel()
|
lbl = self.GenerateLabel()
|
||||||
switchcaselist.append((lbl, blk[idx].ch[0]))
|
switchcaselist.append((lbl, blk[idx].ch[0]))
|
||||||
self.AddSymbol('l', blkscope, lbl)
|
self.AddSymbol('l', blkscope, lbl, ref=0)
|
||||||
blk[idx] = nr(nt='@', t=None, name=lbl, scope=blkscope)
|
blk[idx] = nr(nt='@', t=None, name=lbl, scope=blkscope)
|
||||||
elif blk[idx].nt == 'DEFAULTCASE':
|
elif blk[idx].nt == 'DEFAULTCASE':
|
||||||
if switchcasedefault is not None:
|
if switchcasedefault is not None:
|
||||||
raise EParseManyDefaults(self)
|
raise EParseManyDefaults(self)
|
||||||
lbl = self.GenerateLabel()
|
lbl = self.GenerateLabel()
|
||||||
switchcasedefault = lbl
|
switchcasedefault = lbl
|
||||||
self.AddSymbol('l', blkscope, lbl)
|
self.AddSymbol('l', blkscope, lbl, ref=0)
|
||||||
blk[idx] = nr(nt='@', name=lbl, scope=blkscope)
|
blk[idx] = nr(nt='@', name=lbl, scope=blkscope)
|
||||||
|
|
||||||
prelude = []
|
prelude = []
|
||||||
|
@ -2023,6 +2039,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
nr(nt='==', t='integer', ch=[lexpr, rexpr]),
|
nr(nt='==', t='integer', ch=[lexpr, rexpr]),
|
||||||
nr(nt='JUMP', t=None, name=case[0], scope=blkscope)
|
nr(nt='JUMP', t=None, name=case[0], scope=blkscope)
|
||||||
]))
|
]))
|
||||||
|
self.symtab[blkscope][case[0]]['ref'] += 1
|
||||||
|
|
||||||
if switchcasedefault is None:
|
if switchcasedefault is None:
|
||||||
if self.errmissingdefault:
|
if self.errmissingdefault:
|
||||||
|
@ -2034,7 +2051,6 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
# SEF. But we do a preliminary elimination here.
|
# SEF. But we do a preliminary elimination here.
|
||||||
if self.does_something(blk):
|
if self.does_something(blk):
|
||||||
switchcasedefault = brk
|
switchcasedefault = brk
|
||||||
self.breakstack[-1][2] = True
|
|
||||||
else:
|
else:
|
||||||
# Check if no code up to the default label does anything.
|
# Check if no code up to the default label does anything.
|
||||||
# If so, remove the label and don't generate the jump.
|
# If so, remove the label and don't generate the jump.
|
||||||
|
@ -2052,10 +2068,16 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
if switchcasedefault is not None:
|
if switchcasedefault is not None:
|
||||||
prelude.append(nr(nt='JUMP', t=None, name=switchcasedefault,
|
prelude.append(nr(nt='JUMP', t=None, name=switchcasedefault,
|
||||||
scope=blkscope))
|
scope=blkscope))
|
||||||
|
if switchcasedefault == brk:
|
||||||
|
# add a reference to it in the break stack
|
||||||
|
self.breakstack[-1][2] += 1
|
||||||
|
else:
|
||||||
|
self.symtab[blkscope][switchcasedefault]['ref'] += 1
|
||||||
|
|
||||||
last = self.breakstack.pop()
|
last = self.breakstack.pop()
|
||||||
if last[2]:
|
if last[2]:
|
||||||
blk.append(nr(nt='@', name=brk, scope=blkscope))
|
blk.append(nr(nt='@', name=brk, scope=blkscope))
|
||||||
self.AddSymbol('l', blkscope, brk)
|
self.AddSymbol('l', blkscope, brk, ref=last[2])
|
||||||
return nr(nt='{}', t=None, ch=prelude + blk)
|
return nr(nt='{}', t=None, ch=prelude + blk)
|
||||||
|
|
||||||
if tok0 == 'CASE':
|
if tok0 == 'CASE':
|
||||||
|
@ -2104,7 +2126,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
self.expect(';')
|
self.expect(';')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
try:
|
try:
|
||||||
self.breakstack[n][2] = True
|
self.breakstack[n][2] += 1
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise EParseInvalidBrkContArg(self)
|
raise EParseInvalidBrkContArg(self)
|
||||||
return nr(nt='JUMP', t=None, name=self.breakstack[n][0],
|
return nr(nt='JUMP', t=None, name=self.breakstack[n][0],
|
||||||
|
@ -2133,12 +2155,12 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
# Transform to while(cond) while(cond) while(cond) break 2;
|
# Transform to while(cond) while(cond) while(cond) break 2;
|
||||||
# which is equivalent since there are no {}.
|
# which is equivalent since there are no {}.
|
||||||
n += 1 # e.g. -3 -> -2
|
n += 1 # e.g. -3 -> -2
|
||||||
self.breakstack[n][2] = True # mark the break as used
|
self.breakstack[n][2] += 1 # add a reference to the break
|
||||||
return nr(nt='JUMP', t=None, name=self.breakstack[n][0],
|
return nr(nt='JUMP', t=None, name=self.breakstack[n][0],
|
||||||
scope=self.breakstack[n][1])
|
scope=self.breakstack[n][1])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise EParseInvalidBrkContArg(self)
|
raise EParseInvalidBrkContArg(self)
|
||||||
self.continuestack[n][2] = True
|
self.continuestack[n][2] += 1
|
||||||
return nr(nt='JUMP', t=None, name=self.continuestack[n][0],
|
return nr(nt='JUMP', t=None, name=self.continuestack[n][0],
|
||||||
scope=self.continuestack[n][1])
|
scope=self.continuestack[n][1])
|
||||||
|
|
||||||
|
@ -2544,6 +2566,7 @@ list lazy_list_set(list L, integer i, list v)
|
||||||
self.errorpos = tgt[2]
|
self.errorpos = tgt[2]
|
||||||
raise EParseUndefined(self)
|
raise EParseUndefined(self)
|
||||||
tgt[3].scope = sym['Scope']
|
tgt[3].scope = sym['Scope']
|
||||||
|
sym['ref'] += 1
|
||||||
|
|
||||||
del self.jump_lookups # Finished with it.
|
del self.jump_lookups # Finished with it.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue