1.1 --- a/simplified.py Sat Jul 15 20:43:50 2006 +0200
1.2 +++ b/simplified.py Sun Jul 16 01:33:02 2006 +0200
1.3 @@ -28,10 +28,16 @@
1.4
1.5 original The original node from which this node was created.
1.6 name Any name involved (variable or attribute).
1.7 + index Any index involved (temporary variable name).
1.8 + value Any constant value.
1.9 + ref Any reference to (for example) subprograms.
1.10 +
1.11 + Expression-related attributes:
1.12 +
1.13 expr Any contributing expression.
1.14 lvalue Any target expression.
1.15 test Any test expression in a conditional instruction.
1.16 - ref Any reference to (for example) subprograms.
1.17 + handler Any exception handler selector expression.
1.18
1.19 Invocation and subprogram attributes:
1.20
1.21 @@ -44,11 +50,6 @@
1.22 else_ Any conditional code depending on the failure of a test.
1.23 finally_ Any code which will be executed regardless.
1.24 code Any unconditional code.
1.25 -
1.26 - Table-style attributes:
1.27 -
1.28 - tests Any collection of tests and accompanying code.
1.29 - handlers Any collection of tests applicable in exception handling.
1.30 """
1.31
1.32 def __init__(self, original=None, **kw):
1.33 @@ -86,16 +87,16 @@
1.34 self._pprint(indent + 2, "( ", "%s -> %s" % (name, default))
1.35 if getattr(self, "acquire_locals", 0):
1.36 self._pprint(indent + 2, "( ", "acquiring locals")
1.37 - if hasattr(self, "spec"):
1.38 - self.spec.pprint(indent + 2, "E ")
1.39 if hasattr(self, "test"):
1.40 self.test.pprint(indent + 2, "? ")
1.41 - for attr in "code", "tests", "body", "handlers", "else_", "finally_":
1.42 + for attr in "code", "body", "else_", "finally_":
1.43 if hasattr(self, attr) and getattr(self, attr):
1.44 self._pprint(indent, "", "{ (%s)" % attr)
1.45 for node in getattr(self, attr):
1.46 node.pprint(indent + 2)
1.47 self._pprint(indent, "", "}")
1.48 + if hasattr(self, "handler"):
1.49 + self.handler.pprint(indent + 2, "! ")
1.50 if hasattr(self, "expr"):
1.51 self.expr.pprint(indent + 2, "- ")
1.52 if hasattr(self, "nodes"):
1.53 @@ -127,10 +128,8 @@
1.54 class StoreName(Node): "Associate a name with an object."
1.55 class StoreAttr(Node): "Associate an object's attribute with a value."
1.56 class ReleaseTemp(Node): "Release a temporary value."
1.57 -class If(Node): "A multitest conditional node."
1.58 class Conditional(Node): "A conditional node consisting of a test and outcomes."
1.59 class Try(Node): "A try...except...else...finally grouping node."
1.60 -class Except(Node): "An exception handler node."
1.61 class Raise(Node): "An exception raising node."
1.62 class Not(Node): "A negation of an expression."
1.63
2.1 --- a/simplify.py Sat Jul 15 20:43:50 2006 +0200
2.2 +++ b/simplify.py Sun Jul 16 01:33:02 2006 +0200
2.3 @@ -155,22 +155,6 @@
2.4 result.traceback = self.dispatch(raise_.expr3)
2.5 return result
2.6
2.7 - def visitIf(self, if_):
2.8 - result = If(if_, else_=[])
2.9 - tests = []
2.10 - for compare, stmt in if_.tests:
2.11 - # Produce something like...
2.12 - # expr.__true__() ? body
2.13 - test = Conditional(else_=[], test=Invoke(
2.14 - expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
2.15 - params=[], star=None, dstar=None))
2.16 - test.body = self.dispatch(stmt)
2.17 - tests.append(test)
2.18 - result.tests = tests
2.19 - if if_.else_ is not None:
2.20 - result.else_ = self.dispatch(if_.else_)
2.21 - return result
2.22 -
2.23 def _visitBuiltin(self, builtin, name):
2.24 result = Invoke(builtin, expr=LoadName(name=name))
2.25 result.args = self.dispatches(builtin.nodes)
2.26 @@ -192,7 +176,95 @@
2.27 result.args = args
2.28 return result
2.29
2.30 - # Logical and comparison operations.
2.31 + # Logical and comparison operations plus chained statements.
2.32 +
2.33 + def visitIf(self, if_):
2.34 +
2.35 + # Make a subprogram for the statement and record it outside the main tree.
2.36 +
2.37 + subprogram = Subprogram(name=hex(id(if_)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.38 + self.current_subprograms.append(subprogram)
2.39 +
2.40 + # In the subprogram, make conditionals for each test plus statement,
2.41 + # adding a return onto the end of each statement block.
2.42 +
2.43 + nodes = []
2.44 + for compare, stmt in if_.tests:
2.45 + # Produce something like...
2.46 + # expr.__true__() ? body
2.47 + test = Conditional(else_=[], test=Invoke(
2.48 + expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
2.49 + args=[], star=None, dstar=None))
2.50 + test.body = self.dispatch(stmt) + [Return()]
2.51 + nodes.append(test)
2.52 +
2.53 + # Add the compound statement from any else clause to the end.
2.54 +
2.55 + if if_.else_ is not None:
2.56 + nodes += self.dispatch(if_.else_)
2.57 +
2.58 + subprogram.code = nodes
2.59 +
2.60 + self.current_subprograms.pop()
2.61 + self.subprograms.append(subprogram)
2.62 +
2.63 + # Make an invocation of the subprogram.
2.64 +
2.65 + result = Invoke(compare, same_frame=1, star=None, dstar=None, args=[])
2.66 + result.expr = LoadRef(ref=subprogram)
2.67 + return result
2.68 +
2.69 + def _visitTryExcept(self, tryexcept):
2.70 +
2.71 + # Make a subprogram for the statement and record it outside the main tree.
2.72 +
2.73 + subprogram = Subprogram(name=hex(id(tryexcept)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.74 + self.current_subprograms.append(subprogram)
2.75 +
2.76 + # In the subprogram, make conditionals for each test plus statement,
2.77 + # adding a return onto the end of each statement block.
2.78 +
2.79 + nodes = []
2.80 + for spec, assign, stmt in tryexcept.handlers:
2.81 +
2.82 + # If no specification exists, produce an unconditional block.
2.83 +
2.84 + if spec is None:
2.85 + nodes += self.dispatch(stmt)
2.86 +
2.87 + # Produce something like...
2.88 + # isinstance(<exc>, <spec>)
2.89 +
2.90 + else:
2.91 + new_spec = self.dispatch(spec)
2.92 + test = Conditional(body=[], else_=[], test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None))
2.93 + if assign is not None:
2.94 + test.body.append(Assign(code=[StoreTemp(expr=LoadExc()), self.dispatch(assign), ReleaseTemp()]))
2.95 + test.body += self.dispatch(stmt) + [Return()]
2.96 + nodes.append(test)
2.97 +
2.98 + # Add a raise operation to deal with unhandled exceptions.
2.99 +
2.100 + nodes.append(Raise(expr=LoadExc()))
2.101 + subprogram.code = nodes
2.102 +
2.103 + self.current_subprograms.pop()
2.104 + self.subprograms.append(subprogram)
2.105 +
2.106 + # Make an invocation of the subprogram.
2.107 +
2.108 + result = Invoke(same_frame=1, star=None, dstar=None, args=[])
2.109 + result.expr = LoadRef(ref=subprogram)
2.110 + return result
2.111 +
2.112 + def visitTryExcept(self, tryexcept):
2.113 + result = Try(tryexcept, body=[], else_=[], finally_=[])
2.114 + if tryexcept.body is not None:
2.115 + result.body = self.dispatch(tryexcept.body)
2.116 + if tryexcept.else_ is not None:
2.117 + result.else_ = self.dispatch(tryexcept.else_)
2.118 + result.handler = self._visitTryExcept(tryexcept)
2.119 + return result
2.120
2.121 comparison_methods = {
2.122 "==" : "__eq__", "!=" : "__ne__", "<" : "__lt__", "<=" : "__le__",
2.123 @@ -586,7 +658,7 @@
2.124
2.125 test = Conditional(else_=[])
2.126 test.test = Invoke(expr=LoadAttr(expr=self.dispatch(while_.test), name="__true__"),
2.127 - params=[], star=None, dstar=None)
2.128 + args=[], star=None, dstar=None)
2.129
2.130 # Inside the conditional, add a recursive invocation to the subprogram
2.131 # if the test condition was satisfied.
2.132 @@ -614,13 +686,17 @@
2.133 subprogram = Subprogram(name=hex(id(for_)), acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.134 self.current_subprograms.append(subprogram)
2.135
2.136 + if for_.else_ is not None:
2.137 + else_stmt = self.dispatch(for_.else_)
2.138 + else:
2.139 + else_stmt = []
2.140 +
2.141 # Wrap the assignment in a try...except statement.
2.142
2.143 - try_except = Try(body=[], handlers=[], else_=[], finally_=[])
2.144 - except_spec = Invoke(expr=LoadName(name="Tuple"), params=[LoadName(name="StopIteration")])
2.145 - stopiteration = Except(spec=except_spec)
2.146 - stopiteration.code = self.dispatch(for_.else_)
2.147 - try_except.handlers = [stopiteration]
2.148 + try_except = Try(body=[], else_=[], finally_=[])
2.149 + try_except.handler = Conditional(test=Invoke(expr=LoadName(name="isinstance"),
2.150 + args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None),
2.151 + body=else_stmt, else_=[Raise(expr=LoadExc())])
2.152
2.153 assign = Assign()
2.154 assign.code = [
2.155 @@ -653,27 +729,6 @@
2.156
2.157 # Exception node transformations.
2.158
2.159 - def visitTryExcept(self, tryexcept):
2.160 - result = Try(tryexcept, body=[], handlers=[], else_=[], finally_=[])
2.161 - if tryexcept.body is not None:
2.162 - result.body = self.dispatch(tryexcept.body)
2.163 - if tryexcept.else_ is not None:
2.164 - result.else_ = self.dispatch(tryexcept.else_)
2.165 - handlers = []
2.166 - for spec, assign, stmt in tryexcept.handlers:
2.167 - get_exc = Assign()
2.168 - get_exc.code = [StoreTemp(expr=LoadExc())]
2.169 - if assign is not None:
2.170 - get_exc.code.append(self.dispatch(assign))
2.171 - get_exc.code.append(ReleaseTemp())
2.172 - handler = Except()
2.173 - if spec is not None:
2.174 - handler.spec = self.dispatch(spec)
2.175 - handler.code = [get_exc] + self.dispatch(stmt)
2.176 - handlers.append(handler)
2.177 - result.handlers = handlers
2.178 - return result
2.179 -
2.180 def visitTryFinally(self, tryfinally):
2.181 result = Try(tryfinally, body=[], handlers=[], else_=[], finally_=[])
2.182 if tryfinally.body is not None: