# HG changeset patch # User paulb@jeremy # Date 1153006382 -7200 # Node ID fd231fc3d4aedfdbbd45df667a8458920cf63015 # Parent c227a822ddc7355e363c9b3085a08c4e5af37eb8 Changed If and TryExcept replacements to employ subprograms similar to those employed in the And, Or and Compare replacements. diff -r c227a822ddc7 -r fd231fc3d4ae simplified.py --- a/simplified.py Sat Jul 15 20:43:50 2006 +0200 +++ b/simplified.py Sun Jul 16 01:33:02 2006 +0200 @@ -28,10 +28,16 @@ original The original node from which this node was created. name Any name involved (variable or attribute). + index Any index involved (temporary variable name). + value Any constant value. + ref Any reference to (for example) subprograms. + + Expression-related attributes: + expr Any contributing expression. lvalue Any target expression. test Any test expression in a conditional instruction. - ref Any reference to (for example) subprograms. + handler Any exception handler selector expression. Invocation and subprogram attributes: @@ -44,11 +50,6 @@ else_ Any conditional code depending on the failure of a test. finally_ Any code which will be executed regardless. code Any unconditional code. - - Table-style attributes: - - tests Any collection of tests and accompanying code. - handlers Any collection of tests applicable in exception handling. """ def __init__(self, original=None, **kw): @@ -86,16 +87,16 @@ self._pprint(indent + 2, "( ", "%s -> %s" % (name, default)) if getattr(self, "acquire_locals", 0): self._pprint(indent + 2, "( ", "acquiring locals") - if hasattr(self, "spec"): - self.spec.pprint(indent + 2, "E ") if hasattr(self, "test"): self.test.pprint(indent + 2, "? ") - for attr in "code", "tests", "body", "handlers", "else_", "finally_": + for attr in "code", "body", "else_", "finally_": if hasattr(self, attr) and getattr(self, attr): self._pprint(indent, "", "{ (%s)" % attr) for node in getattr(self, attr): node.pprint(indent + 2) self._pprint(indent, "", "}") + if hasattr(self, "handler"): + self.handler.pprint(indent + 2, "! ") if hasattr(self, "expr"): self.expr.pprint(indent + 2, "- ") if hasattr(self, "nodes"): @@ -127,10 +128,8 @@ class StoreName(Node): "Associate a name with an object." class StoreAttr(Node): "Associate an object's attribute with a value." class ReleaseTemp(Node): "Release a temporary value." -class If(Node): "A multitest conditional node." class Conditional(Node): "A conditional node consisting of a test and outcomes." class Try(Node): "A try...except...else...finally grouping node." -class Except(Node): "An exception handler node." class Raise(Node): "An exception raising node." class Not(Node): "A negation of an expression." diff -r c227a822ddc7 -r fd231fc3d4ae simplify.py --- a/simplify.py Sat Jul 15 20:43:50 2006 +0200 +++ b/simplify.py Sun Jul 16 01:33:02 2006 +0200 @@ -155,22 +155,6 @@ result.traceback = self.dispatch(raise_.expr3) return result - def visitIf(self, if_): - result = If(if_, else_=[]) - tests = [] - for compare, stmt in if_.tests: - # Produce something like... - # expr.__true__() ? body - test = Conditional(else_=[], test=Invoke( - expr=LoadAttr(expr=self.dispatch(compare), name="__true__"), - params=[], star=None, dstar=None)) - test.body = self.dispatch(stmt) - tests.append(test) - result.tests = tests - if if_.else_ is not None: - result.else_ = self.dispatch(if_.else_) - return result - def _visitBuiltin(self, builtin, name): result = Invoke(builtin, expr=LoadName(name=name)) result.args = self.dispatches(builtin.nodes) @@ -192,7 +176,95 @@ result.args = args return result - # Logical and comparison operations. + # Logical and comparison operations plus chained statements. + + def visitIf(self, if_): + + # Make a subprogram for the statement and record it outside the main tree. + + subprogram = Subprogram(name=hex(id(if_)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None) + self.current_subprograms.append(subprogram) + + # In the subprogram, make conditionals for each test plus statement, + # adding a return onto the end of each statement block. + + nodes = [] + for compare, stmt in if_.tests: + # Produce something like... + # expr.__true__() ? body + test = Conditional(else_=[], test=Invoke( + expr=LoadAttr(expr=self.dispatch(compare), name="__true__"), + args=[], star=None, dstar=None)) + test.body = self.dispatch(stmt) + [Return()] + nodes.append(test) + + # Add the compound statement from any else clause to the end. + + if if_.else_ is not None: + nodes += self.dispatch(if_.else_) + + subprogram.code = nodes + + self.current_subprograms.pop() + self.subprograms.append(subprogram) + + # Make an invocation of the subprogram. + + result = Invoke(compare, same_frame=1, star=None, dstar=None, args=[]) + result.expr = LoadRef(ref=subprogram) + return result + + def _visitTryExcept(self, tryexcept): + + # Make a subprogram for the statement and record it outside the main tree. + + subprogram = Subprogram(name=hex(id(tryexcept)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None) + self.current_subprograms.append(subprogram) + + # In the subprogram, make conditionals for each test plus statement, + # adding a return onto the end of each statement block. + + nodes = [] + for spec, assign, stmt in tryexcept.handlers: + + # If no specification exists, produce an unconditional block. + + if spec is None: + nodes += self.dispatch(stmt) + + # Produce something like... + # isinstance(, ) + + else: + new_spec = self.dispatch(spec) + test = Conditional(body=[], else_=[], test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None)) + if assign is not None: + test.body.append(Assign(code=[StoreTemp(expr=LoadExc()), self.dispatch(assign), ReleaseTemp()])) + test.body += self.dispatch(stmt) + [Return()] + nodes.append(test) + + # Add a raise operation to deal with unhandled exceptions. + + nodes.append(Raise(expr=LoadExc())) + subprogram.code = nodes + + self.current_subprograms.pop() + self.subprograms.append(subprogram) + + # Make an invocation of the subprogram. + + result = Invoke(same_frame=1, star=None, dstar=None, args=[]) + result.expr = LoadRef(ref=subprogram) + return result + + def visitTryExcept(self, tryexcept): + result = Try(tryexcept, body=[], else_=[], finally_=[]) + if tryexcept.body is not None: + result.body = self.dispatch(tryexcept.body) + if tryexcept.else_ is not None: + result.else_ = self.dispatch(tryexcept.else_) + result.handler = self._visitTryExcept(tryexcept) + return result comparison_methods = { "==" : "__eq__", "!=" : "__ne__", "<" : "__lt__", "<=" : "__le__", @@ -586,7 +658,7 @@ test = Conditional(else_=[]) test.test = Invoke(expr=LoadAttr(expr=self.dispatch(while_.test), name="__true__"), - params=[], star=None, dstar=None) + args=[], star=None, dstar=None) # Inside the conditional, add a recursive invocation to the subprogram # if the test condition was satisfied. @@ -614,13 +686,17 @@ subprogram = Subprogram(name=hex(id(for_)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) + if for_.else_ is not None: + else_stmt = self.dispatch(for_.else_) + else: + else_stmt = [] + # Wrap the assignment in a try...except statement. - try_except = Try(body=[], handlers=[], else_=[], finally_=[]) - except_spec = Invoke(expr=LoadName(name="Tuple"), params=[LoadName(name="StopIteration")]) - stopiteration = Except(spec=except_spec) - stopiteration.code = self.dispatch(for_.else_) - try_except.handlers = [stopiteration] + try_except = Try(body=[], else_=[], finally_=[]) + try_except.handler = Conditional(test=Invoke(expr=LoadName(name="isinstance"), + args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None), + body=else_stmt, else_=[Raise(expr=LoadExc())]) assign = Assign() assign.code = [ @@ -653,27 +729,6 @@ # Exception node transformations. - def visitTryExcept(self, tryexcept): - result = Try(tryexcept, body=[], handlers=[], else_=[], finally_=[]) - if tryexcept.body is not None: - result.body = self.dispatch(tryexcept.body) - if tryexcept.else_ is not None: - result.else_ = self.dispatch(tryexcept.else_) - handlers = [] - for spec, assign, stmt in tryexcept.handlers: - get_exc = Assign() - get_exc.code = [StoreTemp(expr=LoadExc())] - if assign is not None: - get_exc.code.append(self.dispatch(assign)) - get_exc.code.append(ReleaseTemp()) - handler = Except() - if spec is not None: - handler.spec = self.dispatch(spec) - handler.code = [get_exc] + self.dispatch(stmt) - handlers.append(handler) - result.handlers = handlers - return result - def visitTryFinally(self, tryfinally): result = Try(tryfinally, body=[], handlers=[], else_=[], finally_=[]) if tryfinally.body is not None: