mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Add FoldCond as a stub. Change cond constant to -1. Add support for EXPR.
(EXPR as a statement, not as a general 'expression')
This commit is contained in:
parent
67f3061e19
commit
17e94a0d0f
3 changed files with 31 additions and 10 deletions
|
@ -42,6 +42,15 @@ class optimizer(renamer, deadcode):
|
||||||
if parent[index]['nt'] in ('CONST', 'IDENT', 'FIELD'):
|
if parent[index]['nt'] in ('CONST', 'IDENT', 'FIELD'):
|
||||||
parent[index] = {'nt':';','t':None}
|
parent[index] = {'nt':';','t':None}
|
||||||
|
|
||||||
|
def FoldCond(self, parent, index):
|
||||||
|
"""When we know that the parent is interested only in the truth value
|
||||||
|
of the node, we can perform further optimizations. This function deals
|
||||||
|
with them.
|
||||||
|
"""
|
||||||
|
if parent[index]['nt'] in ('CONST', 'IDENT', 'FIELD'):
|
||||||
|
return # Nothing to do if it's already simplified.
|
||||||
|
# TODO: Implement FoldCond
|
||||||
|
|
||||||
def Cast(self, value, newtype):
|
def Cast(self, value, newtype):
|
||||||
# Return a CAST node if the types are not equal, otherwise the
|
# Return a CAST node if the types are not equal, otherwise the
|
||||||
# value unchanged
|
# value unchanged
|
||||||
|
@ -100,7 +109,8 @@ class optimizer(renamer, deadcode):
|
||||||
|
|
||||||
if nt == '!':
|
if nt == '!':
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
# !! can *not* be simplified to !, but !!! can be simplified to !!
|
self.FoldCond(child, 0)
|
||||||
|
# !! does *not* cancel out, but !!! can be simplified to !
|
||||||
subexpr = child[0]
|
subexpr = child[0]
|
||||||
while subexpr['nt'] == '()' and subexpr['ch'][0]['nt'] in ('()', '~', '!', '++V', '--V'):
|
while subexpr['nt'] == '()' and subexpr['ch'][0]['nt'] in ('()', '~', '!', '++V', '--V'):
|
||||||
subexpr = child[0] = subexpr['ch'][0] # Remove parentheses
|
subexpr = child[0] = subexpr['ch'][0] # Remove parentheses
|
||||||
|
@ -427,8 +437,7 @@ class optimizer(renamer, deadcode):
|
||||||
parent[index] = {'nt':'()', 't':'list', 'ch':[node]}
|
parent[index] = {'nt':'()', 't':'list', 'ch':[node]}
|
||||||
return
|
return
|
||||||
|
|
||||||
if nt == 'PRINT':
|
if nt in ('PRINT', 'EXPR'):
|
||||||
# useless but who knows
|
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -468,6 +477,7 @@ class optimizer(renamer, deadcode):
|
||||||
|
|
||||||
if nt == 'IF':
|
if nt == 'IF':
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
|
self.FoldCond(child, 0)
|
||||||
if child[0]['nt'] == 'CONST':
|
if child[0]['nt'] == 'CONST':
|
||||||
# We might be able to remove one of the branches.
|
# We might be able to remove one of the branches.
|
||||||
if lslfuncs.cond(child[0]['value']):
|
if lslfuncs.cond(child[0]['value']):
|
||||||
|
@ -475,10 +485,15 @@ class optimizer(renamer, deadcode):
|
||||||
# If it has a state switch, the if() must be preserved
|
# If it has a state switch, the if() must be preserved
|
||||||
# (but the else branch may be removed).
|
# (but the else branch may be removed).
|
||||||
if 'StSw' in child[1]:
|
if 'StSw' in child[1]:
|
||||||
|
# TODO: Get rid of StSw craziness and make another pass
|
||||||
|
# to put them under conditionals if present (if bald
|
||||||
|
# state switches are present, it means they are the
|
||||||
|
# result of optimization so they must be wrapped in an
|
||||||
|
# IF statement). The current approach leaves unnecessary
|
||||||
|
# IFs behind.
|
||||||
if len(child) > 2:
|
if len(child) > 2:
|
||||||
del child[2] # Delete ELSE if present
|
del child[2] # Delete ELSE if present
|
||||||
child[0]['t'] = 'integer'
|
child[0].update({'t':'integer', 'value':-1})
|
||||||
child[0]['value'] = 1
|
|
||||||
else:
|
else:
|
||||||
self.FoldStmt(child, 1)
|
self.FoldStmt(child, 1)
|
||||||
parent[index] = child[1]
|
parent[index] = child[1]
|
||||||
|
@ -503,12 +518,13 @@ class optimizer(renamer, deadcode):
|
||||||
|
|
||||||
if nt == 'WHILE':
|
if nt == 'WHILE':
|
||||||
self.FoldTree(child, 0)
|
self.FoldTree(child, 0)
|
||||||
|
self.FoldCond(child, 0)
|
||||||
if child[0]['nt'] == 'CONST':
|
if child[0]['nt'] == 'CONST':
|
||||||
# See if the whole WHILE can be eliminated.
|
# See if the whole WHILE can be eliminated.
|
||||||
if lslfuncs.cond(child[0]['value']):
|
if lslfuncs.cond(child[0]['value']):
|
||||||
# Endless loop which must be kept.
|
# Endless loop which must be kept.
|
||||||
# First, replace the constant.
|
# First, replace the constant.
|
||||||
child[0].update({'t':'integer', 'value':1})
|
child[0].update({'t':'integer', 'value':-1})
|
||||||
# Recurse on the statement.
|
# Recurse on the statement.
|
||||||
self.FoldTree(child, 1)
|
self.FoldTree(child, 1)
|
||||||
self.FoldStmt(child, 1)
|
self.FoldStmt(child, 1)
|
||||||
|
@ -524,11 +540,12 @@ class optimizer(renamer, deadcode):
|
||||||
self.FoldTree(child, 0) # This one is always executed.
|
self.FoldTree(child, 0) # This one is always executed.
|
||||||
self.FoldStmt(child, 0)
|
self.FoldStmt(child, 0)
|
||||||
self.FoldTree(child, 1)
|
self.FoldTree(child, 1)
|
||||||
|
self.FoldCond(child, 1)
|
||||||
# See if the latest part is a constant.
|
# See if the latest part is a constant.
|
||||||
if child[1]['nt'] == 'CONST':
|
if child[1]['nt'] == 'CONST':
|
||||||
if lslfuncs.cond(child[1]['value']):
|
if lslfuncs.cond(child[1]['value']):
|
||||||
# Endless loop. Replace the constant.
|
# Endless loop. Replace the constant.
|
||||||
child[1].update({'t':'integer', 'value':1})
|
child[1].update({'t':'integer', 'value':-1})
|
||||||
else:
|
else:
|
||||||
# Only one go. Replace with the statement(s).
|
# Only one go. Replace with the statement(s).
|
||||||
parent[index] = child[0]
|
parent[index] = child[0]
|
||||||
|
@ -540,6 +557,7 @@ class optimizer(renamer, deadcode):
|
||||||
self.FoldAndRemoveEmptyStmts(child[0]['ch'])
|
self.FoldAndRemoveEmptyStmts(child[0]['ch'])
|
||||||
|
|
||||||
self.FoldTree(child, 1) # Condition.
|
self.FoldTree(child, 1) # Condition.
|
||||||
|
self.FoldCond(child, 1)
|
||||||
if child[1]['nt'] == 'CONST':
|
if child[1]['nt'] == 'CONST':
|
||||||
# FOR is delicate. It can have multiple expressions at start.
|
# FOR is delicate. It can have multiple expressions at start.
|
||||||
# And if there is more than one, these expressions will need a
|
# And if there is more than one, these expressions will need a
|
||||||
|
@ -548,7 +566,7 @@ class optimizer(renamer, deadcode):
|
||||||
# it feels creepy.
|
# it feels creepy.
|
||||||
if lslfuncs.cond(child[1]['value']):
|
if lslfuncs.cond(child[1]['value']):
|
||||||
# Endless loop. Just replace the constant and traverse the rest.
|
# Endless loop. Just replace the constant and traverse the rest.
|
||||||
child[1].update({'t':'integer', 'value':1})
|
child[1].update({'t':'integer', 'value':-1})
|
||||||
self.FoldAndRemoveEmptyStmts(child[2]['ch'])
|
self.FoldAndRemoveEmptyStmts(child[2]['ch'])
|
||||||
self.FoldTree(child, 3)
|
self.FoldTree(child, 3)
|
||||||
self.FoldStmt(child, 3)
|
self.FoldStmt(child, 3)
|
||||||
|
|
|
@ -310,7 +310,10 @@ class outscript(object):
|
||||||
for typ, name in zip(node['ptypes'], node['pnames']))
|
for typ, name in zip(node['ptypes'], node['pnames']))
|
||||||
return ret + ')\n' + self.OutCode(child[0])
|
return ret + ')\n' + self.OutCode(child[0])
|
||||||
|
|
||||||
return self.dent() + self.OutExpr(node) + ';\n'
|
if nt == 'EXPR':
|
||||||
|
return self.dent() + self.OutExpr(child[0]) + ';\n'
|
||||||
|
|
||||||
|
assert False, "Internal error: node type not handled: " + nt
|
||||||
|
|
||||||
def output(self, treesymtab, options = ('optsigns','optfloats')):
|
def output(self, treesymtab, options = ('optsigns','optfloats')):
|
||||||
# Build a sorted list of dict entries
|
# Build a sorted list of dict entries
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ class parser(object):
|
||||||
value = self.Parse_expression()
|
value = self.Parse_expression()
|
||||||
self.expect(';')
|
self.expect(';')
|
||||||
self.NextToken()
|
self.NextToken()
|
||||||
return value
|
return {'nt':'EXPR', 't':value['t'], 'ch':[value]}
|
||||||
|
|
||||||
def Parse_code_block(self, ReturnType, AllowStSw = False):
|
def Parse_code_block(self, ReturnType, AllowStSw = False):
|
||||||
"""Grammar parsed here:
|
"""Grammar parsed here:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue