From 17e94a0d0f0ee0bb5241050d06c28fd4f0f21182 Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Sun, 3 Aug 2014 20:06:50 +0200 Subject: [PATCH] Add FoldCond as a stub. Change cond constant to -1. Add support for EXPR. (EXPR as a statement, not as a general 'expression') --- lslopt/lsloptimizer.py | 34 ++++++++++++++++++++++++++-------- lslopt/lsloutput.py | 5 ++++- lslopt/lslparse.py | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/lslopt/lsloptimizer.py b/lslopt/lsloptimizer.py index 407952e..f954f93 100644 --- a/lslopt/lsloptimizer.py +++ b/lslopt/lsloptimizer.py @@ -42,6 +42,15 @@ class optimizer(renamer, deadcode): if parent[index]['nt'] in ('CONST', 'IDENT', 'FIELD'): 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): # Return a CAST node if the types are not equal, otherwise the # value unchanged @@ -100,7 +109,8 @@ class optimizer(renamer, deadcode): if nt == '!': 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] while subexpr['nt'] == '()' and subexpr['ch'][0]['nt'] in ('()', '~', '!', '++V', '--V'): subexpr = child[0] = subexpr['ch'][0] # Remove parentheses @@ -427,8 +437,7 @@ class optimizer(renamer, deadcode): parent[index] = {'nt':'()', 't':'list', 'ch':[node]} return - if nt == 'PRINT': - # useless but who knows + if nt in ('PRINT', 'EXPR'): self.FoldTree(child, 0) return @@ -468,6 +477,7 @@ class optimizer(renamer, deadcode): if nt == 'IF': self.FoldTree(child, 0) + self.FoldCond(child, 0) if child[0]['nt'] == 'CONST': # We might be able to remove one of the branches. 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 # (but the else branch may be removed). 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: del child[2] # Delete ELSE if present - child[0]['t'] = 'integer' - child[0]['value'] = 1 + child[0].update({'t':'integer', 'value':-1}) else: self.FoldStmt(child, 1) parent[index] = child[1] @@ -503,12 +518,13 @@ class optimizer(renamer, deadcode): if nt == 'WHILE': self.FoldTree(child, 0) + self.FoldCond(child, 0) if child[0]['nt'] == 'CONST': # See if the whole WHILE can be eliminated. if lslfuncs.cond(child[0]['value']): # Endless loop which must be kept. # First, replace the constant. - child[0].update({'t':'integer', 'value':1}) + child[0].update({'t':'integer', 'value':-1}) # Recurse on the statement. self.FoldTree(child, 1) self.FoldStmt(child, 1) @@ -524,11 +540,12 @@ class optimizer(renamer, deadcode): self.FoldTree(child, 0) # This one is always executed. self.FoldStmt(child, 0) self.FoldTree(child, 1) + self.FoldCond(child, 1) # See if the latest part is a constant. if child[1]['nt'] == 'CONST': if lslfuncs.cond(child[1]['value']): # Endless loop. Replace the constant. - child[1].update({'t':'integer', 'value':1}) + child[1].update({'t':'integer', 'value':-1}) else: # Only one go. Replace with the statement(s). parent[index] = child[0] @@ -540,6 +557,7 @@ class optimizer(renamer, deadcode): self.FoldAndRemoveEmptyStmts(child[0]['ch']) self.FoldTree(child, 1) # Condition. + self.FoldCond(child, 1) if child[1]['nt'] == 'CONST': # FOR is delicate. It can have multiple expressions at start. # And if there is more than one, these expressions will need a @@ -548,7 +566,7 @@ class optimizer(renamer, deadcode): # it feels creepy. if lslfuncs.cond(child[1]['value']): # 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.FoldTree(child, 3) self.FoldStmt(child, 3) diff --git a/lslopt/lsloutput.py b/lslopt/lsloutput.py index 5634d55..a3e6680 100644 --- a/lslopt/lsloutput.py +++ b/lslopt/lsloutput.py @@ -310,7 +310,10 @@ class outscript(object): for typ, name in zip(node['ptypes'], node['pnames'])) 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')): # Build a sorted list of dict entries diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index 38393c6..a996e6f 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -1336,7 +1336,7 @@ class parser(object): value = self.Parse_expression() self.expect(';') self.NextToken() - return value + return {'nt':'EXPR', 't':value['t'], 'ch':[value]} def Parse_code_block(self, ReturnType, AllowStSw = False): """Grammar parsed here: