1.1 --- a/simplified.py Mon Jul 31 01:01:34 2006 +0200
1.2 +++ b/simplified.py Mon Jul 31 21:20:33 2006 +0200
1.3 @@ -62,7 +62,6 @@
1.4 expr Any contributing expression.
1.5 lvalue Any target expression.
1.6 test Any test expression in a conditional instruction.
1.7 - handler Any exception handler selector expression.
1.8
1.9 Invocation and subprogram attributes:
1.10
1.11 @@ -73,6 +72,7 @@
1.12
1.13 body Any conditional code depending on the success of a test.
1.14 else_ Any conditional code depending on the failure of a test.
1.15 + handler Any exception handler code.
1.16 finally_ Any code which will be executed regardless.
1.17 code Any unconditional code.
1.18 choices Any choices which may be included in the final program.
1.19 @@ -123,14 +123,12 @@
1.20 self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name)
1.21 if hasattr(self, "test"):
1.22 self.test.pprint(indent + 2, "? ")
1.23 - for attr in "code", "body", "else_", "finally_", "choices":
1.24 + for attr in "code", "body", "else_", "handler", "finally_", "choices":
1.25 if hasattr(self, attr) and getattr(self, attr):
1.26 self._pprint(indent, "", "{ (%s)" % attr)
1.27 for node in getattr(self, attr):
1.28 node.pprint(indent + 2)
1.29 self._pprint(indent, "", "}")
1.30 - if hasattr(self, "handler"):
1.31 - self.handler.pprint(indent + 2, "! ")
1.32 if hasattr(self, "expr"):
1.33 self.expr.pprint(indent + 2, "- ")
1.34 if hasattr(self, "nodes"):
2.1 --- a/simplify.py Mon Jul 31 01:01:34 2006 +0200
2.2 +++ b/simplify.py Mon Jul 31 21:20:33 2006 +0200
2.3 @@ -186,83 +186,73 @@
2.4 def visitIf(self, if_):
2.5
2.6 """
2.7 - Convert If(tests=..., else_=...) to:
2.8 + Make conditionals for each test from an 'if_' AST node, adding the body
2.9 + and putting each subsequent test as part of the conditional's else
2.10 + section.
2.11 +
2.12 + Convert...
2.13
2.14 - Invoke -> Subprogram
2.15 - Conditional (test) -> Invoke -> Subprogram (body)
2.16 - Return
2.17 - Conditional (test) -> Invoke -> Subprogram (body)
2.18 - Return
2.19 - ...
2.20 + If (test/body)
2.21 + (test/body)
2.22 + ...
2.23 + (else/body)
2.24 +
2.25 + ...to:
2.26 +
2.27 + Conditional (test) -> (body)
2.28 + (else) -> Conditional (test) -> (body)
2.29 + (else) -> ...
2.30 """
2.31
2.32 - # Make a subprogram for the statement and record it outside the main tree.
2.33 -
2.34 - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.35 - self.current_subprograms.append(subprogram)
2.36
2.37 - # In the subprogram, make conditionals for each test plus statement,
2.38 - # adding a return onto the end of each statement block.
2.39 + results = nodes = []
2.40
2.41 - nodes = []
2.42 for compare, stmt in if_.tests:
2.43 # Produce something like...
2.44 # expr.__true__() ? body
2.45 - test = Conditional(else_=[], test=Invoke(
2.46 - expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
2.47 + test = Conditional(test=Invoke(expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
2.48 args=[], star=None, dstar=None))
2.49 -
2.50 - body_subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.51 - self.current_subprograms.append(body_subprogram)
2.52 -
2.53 - body_subprogram.code = self.dispatch(stmt) + [Return()]
2.54 -
2.55 - self.current_subprograms.pop()
2.56 - self.subprograms.append(body_subprogram)
2.57 -
2.58 - # Always return from conditional sections.
2.59 -
2.60 - test.body = [Invoke(stmt, expr=LoadRef(ref=body_subprogram), same_frame=1, star=None, dstar=None, args=[]), Return()]
2.61 + test.body = self.dispatch(stmt)
2.62 nodes.append(test)
2.63 + nodes = test.else_ = []
2.64
2.65 # Add the compound statement from any else clause to the end.
2.66
2.67 if if_.else_ is not None:
2.68 - else_subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.69 - self.current_subprograms.append(else_subprogram)
2.70 -
2.71 - else_subprogram.code = self.dispatch(if_.else_) + [Return()]
2.72 -
2.73 - self.current_subprograms.pop()
2.74 - self.subprograms.append(else_subprogram)
2.75 -
2.76 - # Always return from conditional subprograms.
2.77 + nodes += self.dispatch(if_.else_)
2.78
2.79 - nodes.append(Invoke(stmt, expr=LoadRef(ref=else_subprogram), same_frame=1, star=None, dstar=None, args=[]))
2.80 - nodes.append(Return())
2.81 -
2.82 - subprogram.code = nodes
2.83 -
2.84 - self.current_subprograms.pop()
2.85 - self.subprograms.append(subprogram)
2.86 -
2.87 - # Make an invocation of the subprogram.
2.88 -
2.89 - result = Invoke(compare, same_frame=1, star=None, dstar=None, args=[])
2.90 - result.expr = LoadRef(ref=subprogram)
2.91 + result = results[0]
2.92 return result
2.93
2.94 - def _visitTryExcept(self, tryexcept):
2.95 + def visitTryExcept(self, tryexcept):
2.96 +
2.97 + """
2.98 + Make conditionals for each handler associated with a 'tryexcept' node.
2.99 +
2.100 + Convert...
2.101
2.102 - # Make a subprogram for the statement and record it outside the main tree.
2.103 + TryExcept (body)
2.104 + (else)
2.105 + (spec/assign/stmt)
2.106 + ...
2.107 +
2.108 + ...to:
2.109
2.110 - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.111 - self.current_subprograms.append(subprogram)
2.112 + Try (body)
2.113 + (else)
2.114 + (handler) -> Conditional (test) -> (stmt)
2.115 + (else) -> Conditional (test) -> (stmt)
2.116 + (else) -> ...
2.117 + """
2.118 +
2.119 + result = Try(tryexcept, body=[], else_=[], finally_=[])
2.120
2.121 - # In the subprogram, make conditionals for each test plus statement,
2.122 - # adding a return onto the end of each statement block.
2.123 + if tryexcept.body is not None:
2.124 + result.body = self.dispatch(tryexcept.body)
2.125 + if tryexcept.else_ is not None:
2.126 + result.else_ = self.dispatch(tryexcept.else_)
2.127
2.128 - nodes = []
2.129 + results = nodes = []
2.130 for spec, assign, stmt in tryexcept.handlers:
2.131
2.132 # If no specification exists, produce an unconditional block.
2.133 @@ -275,7 +265,9 @@
2.134
2.135 else:
2.136 new_spec = self.dispatch(spec)
2.137 - test = Conditional(body=[], else_=[], test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None))
2.138 + test = Conditional(test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None))
2.139 + test.body = []
2.140 +
2.141 if assign is not None:
2.142 test.body.append(Assign(code=[StoreTemp(expr=LoadExc()), self.dispatch(assign), ReleaseTemp()]))
2.143
2.144 @@ -283,28 +275,13 @@
2.145
2.146 test.body += self.dispatch(stmt) + [Return()]
2.147 nodes.append(test)
2.148 + nodes = test.else_ = []
2.149
2.150 # Add a raise operation to deal with unhandled exceptions.
2.151
2.152 nodes.append(Raise(expr=LoadExc()))
2.153 - subprogram.code = nodes
2.154
2.155 - self.current_subprograms.pop()
2.156 - self.subprograms.append(subprogram)
2.157 -
2.158 - # Make an invocation of the subprogram.
2.159 -
2.160 - result = Invoke(same_frame=1, star=None, dstar=None, args=[])
2.161 - result.expr = LoadRef(ref=subprogram)
2.162 - return result
2.163 -
2.164 - def visitTryExcept(self, tryexcept):
2.165 - result = Try(tryexcept, body=[], else_=[], finally_=[])
2.166 - if tryexcept.body is not None:
2.167 - result.body = self.dispatch(tryexcept.body)
2.168 - if tryexcept.else_ is not None:
2.169 - result.else_ = self.dispatch(tryexcept.else_)
2.170 - result.handler = self._visitTryExcept(tryexcept)
2.171 + result.handler = results
2.172 return result
2.173
2.174 comparison_methods = {
2.175 @@ -314,7 +291,20 @@
2.176
2.177 def visitCompare(self, compare):
2.178
2.179 - # Make a subprogram for the expression and record it outside the main tree.
2.180 + """
2.181 + Make a subprogram for the 'compare' node and record its contents inside
2.182 + the subprogram. Convert...
2.183 +
2.184 + Compare (expr)
2.185 + (name/node)
2.186 + ...
2.187 +
2.188 + ...to:
2.189 +
2.190 + Subprogram -> Conditional (test) -> (body)
2.191 + (else) -> Conditional (test) -> (body)
2.192 + (else) -> ...
2.193 + """
2.194
2.195 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
2.196 self.current_subprograms.append(subprogram)
2.197 @@ -323,12 +313,16 @@
2.198 # first operand of each operand pair and, if appropriate, return with
2.199 # the value from that method.
2.200
2.201 - nodes = []
2.202 last = compare.ops[-1]
2.203 previous = self.dispatch(compare.expr)
2.204 + results = nodes = []
2.205 +
2.206 for op in compare.ops:
2.207 op_name, node = op
2.208 expr = self.dispatch(node)
2.209 +
2.210 + # Identify the operation and produce the appropriate method call.
2.211 +
2.212 method_name = self.comparison_methods[op_name]
2.213 if method_name:
2.214 invocation = Invoke(expr=LoadAttr(expr=previous, name=method_name), args=[expr], star=None, dstar=None)
2.215 @@ -340,15 +334,26 @@
2.216 raise NotImplementedError, op_name
2.217 nodes.append(StoreTemp(expr=invocation))
2.218
2.219 - # Always return from conditional sections/subprograms.
2.220 + # Return from the subprogram where the test is not satisfied.
2.221
2.222 if op is not last:
2.223 - nodes.append(Conditional(test=Not(expr=LoadTemp()), body=[Return(expr=LoadTemp())]))
2.224 - nodes.append(ReleaseTemp())
2.225 + test = Conditional(test=Not(expr=LoadTemp()), body=[Return(expr=LoadTemp())])
2.226 + nodes.append(test)
2.227 +
2.228 + # Put subsequent operations in the else section of this conditional.
2.229 +
2.230 + nodes = test.else_ = [ReleaseTemp()]
2.231 +
2.232 + # For the last operation, return the result.
2.233 +
2.234 else:
2.235 nodes.append(Return(expr=LoadTemp()))
2.236 +
2.237 previous = expr
2.238 - subprogram.code = nodes
2.239 +
2.240 + # Finish the subprogram definition.
2.241 +
2.242 + subprogram.code = results
2.243
2.244 self.current_subprograms.pop()
2.245 self.subprograms.append(subprogram)
2.246 @@ -361,7 +366,20 @@
2.247
2.248 def visitAnd(self, and_):
2.249
2.250 - # Make a subprogram for the expression and record it outside the main tree.
2.251 + """
2.252 + Make a subprogram for the 'and_' node and record its contents inside the
2.253 + subprogram. Convert...
2.254 +
2.255 + And (test)
2.256 + (test)
2.257 + ...
2.258 +
2.259 + ...to:
2.260 +
2.261 + Subprogram -> Conditional (test) -> Return ...
2.262 + (else) -> Conditional (test) -> Return ...
2.263 + (else) -> ...
2.264 + """
2.265
2.266 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
2.267 self.current_subprograms.append(subprogram)
2.268 @@ -370,21 +388,32 @@
2.269 # for each operand's truth status, and if appropriate return from the
2.270 # subprogram with the value of the operand.
2.271
2.272 - nodes = []
2.273 last = and_.nodes[-1]
2.274 + results = nodes = []
2.275 +
2.276 for node in and_.nodes:
2.277 expr = self.dispatch(node)
2.278
2.279 - # Always return from conditional sections/subprograms.
2.280 + # Return from the subprogram where the test is not satisfied.
2.281
2.282 if node is not last:
2.283 nodes.append(StoreTemp(expr=expr))
2.284 invocation = Invoke(expr=LoadAttr(expr=LoadTemp(), name="__true__"), args=[], star=None, dstar=None)
2.285 - nodes.append(Conditional(test=Not(expr=invocation), body=[Return(expr=LoadTemp())]))
2.286 - nodes.append(ReleaseTemp())
2.287 + test = Conditional(test=Not(expr=invocation), body=[Return(expr=LoadTemp())])
2.288 + nodes.append(test)
2.289 +
2.290 + # Put subsequent operations in the else section of this conditional.
2.291 +
2.292 + nodes = test.else_ = [ReleaseTemp()]
2.293 +
2.294 + # For the last operation, return the result.
2.295 +
2.296 else:
2.297 nodes.append(Return(expr=expr))
2.298 - subprogram.code = nodes
2.299 +
2.300 + # Finish the subprogram definition.
2.301 +
2.302 + subprogram.code = results
2.303
2.304 self.current_subprograms.pop()
2.305 self.subprograms.append(subprogram)
2.306 @@ -397,7 +426,20 @@
2.307
2.308 def visitOr(self, or_):
2.309
2.310 - # Make a subprogram for the expression and record it outside the main tree.
2.311 + """
2.312 + Make a subprogram for the 'or_' node and record its contents inside the
2.313 + subprogram. Convert...
2.314 +
2.315 + Or (test)
2.316 + (test)
2.317 + ...
2.318 +
2.319 + ...to:
2.320 +
2.321 + Subprogram -> Conditional (test) -> Return ...
2.322 + (else) -> Conditional (test) -> Return ...
2.323 + (else) -> ...
2.324 + """
2.325
2.326 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
2.327 self.current_subprograms.append(subprogram)
2.328 @@ -406,21 +448,32 @@
2.329 # for each operand's truth status, and if appropriate return from the
2.330 # subprogram with the value of the operand.
2.331
2.332 - nodes = []
2.333 last = or_.nodes[-1]
2.334 + results = nodes = []
2.335 +
2.336 for node in or_.nodes:
2.337 expr = self.dispatch(node)
2.338
2.339 - # Always return from conditional sections/subprograms.
2.340 + # Return from the subprogram where the test is satisfied.
2.341
2.342 if node is not last:
2.343 nodes.append(StoreTemp(expr=expr))
2.344 invocation = Invoke(expr=LoadAttr(expr=LoadTemp(), name="__true__"), args=[], star=None, dstar=None)
2.345 - nodes.append(Conditional(test=invocation, body=[Return(expr=LoadTemp())]))
2.346 - nodes.append(ReleaseTemp())
2.347 + test = Conditional(test=invocation, body=[Return(expr=LoadTemp())])
2.348 + nodes.append(test)
2.349 +
2.350 + # Put subsequent operations in the else section of this conditional.
2.351 +
2.352 + nodes = test.else_ = [ReleaseTemp()]
2.353 +
2.354 + # For the last operation, return the result.
2.355 +
2.356 else:
2.357 nodes.append(Return(expr=expr))
2.358 - subprogram.code = nodes
2.359 +
2.360 + # Finish the subprogram definition.
2.361 +
2.362 + subprogram.code = results
2.363
2.364 self.current_subprograms.pop()
2.365 self.subprograms.append(subprogram)
2.366 @@ -738,7 +791,19 @@
2.367
2.368 def visitWhile(self, while_):
2.369
2.370 - # Make a subprogram for the block and record it outside the main tree.
2.371 + """
2.372 + Make a subprogram for the 'while' node and record its contents inside the
2.373 + subprogram. Convert...
2.374 +
2.375 + While (test) -> (body)
2.376 + (else)
2.377 +
2.378 + ...to:
2.379 +
2.380 + Subprogram -> Conditional (test) -> (body) -> Invoke subprogram
2.381 + (else) -> Conditional (test) -> Return ...
2.382 + (else) -> ...
2.383 + """
2.384
2.385 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.386 self.current_subprograms.append(subprogram)
2.387 @@ -755,12 +820,18 @@
2.388 continuation = Invoke(same_frame=1, star=None, dstar=None, args=[])
2.389 continuation.expr = LoadRef(ref=subprogram)
2.390
2.391 - # Always return from conditional sections/subprograms.
2.392 + # Return within the main section of the loop.
2.393
2.394 test.body = self.dispatch(while_.body) + [continuation, Return()]
2.395 +
2.396 + # Provide the else section, if present, along with an explicit return.
2.397 +
2.398 if while_.else_ is not None:
2.399 - test.else_ = self.dispatch(while_.else_)
2.400 - subprogram.code = [test, Return()]
2.401 + test.else_ = self.dispatch(while_.else_) + [Return()]
2.402 +
2.403 + # Finish the subprogram definition.
2.404 +
2.405 + subprogram.code = test
2.406
2.407 self.current_subprograms.pop()
2.408 self.subprograms.append(subprogram)
2.409 @@ -773,7 +844,23 @@
2.410
2.411 def visitFor(self, for_):
2.412
2.413 - # Make a subprogram for the block and record it outside the main tree.
2.414 + """
2.415 + Make a subprogram for the 'for_' node and record its contents inside the
2.416 + subprogram. Convert...
2.417 +
2.418 + For (assign)
2.419 + (body)
2.420 + (else)
2.421 +
2.422 + ...to:
2.423 +
2.424 + Assign (assign #1)
2.425 + Invoke -> Subprogram -> Try (body) -> (assign #2)
2.426 + (body)
2.427 + Invoke subprogram
2.428 + (handler) -> ...
2.429 + (else) -> ...
2.430 + """
2.431
2.432 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
2.433 self.current_subprograms.append(subprogram)
2.434 @@ -788,9 +875,13 @@
2.435 # Wrap the assignment in a try...except statement.
2.436
2.437 try_except = Try(body=[], else_=[], finally_=[])
2.438 - try_except.handler = Conditional(test=Invoke(expr=LoadName(name="isinstance"),
2.439 - args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None),
2.440 - body=else_stmt, else_=[Raise(expr=LoadExc())])
2.441 + try_except.handler = Conditional(
2.442 + test=Invoke(
2.443 + expr=LoadName(name="isinstance"),
2.444 + args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None
2.445 + ),
2.446 + body=else_stmt,
2.447 + else_=[Raise(expr=LoadExc())])
2.448
2.449 assign = Assign()
2.450 assign.code = [
2.451 @@ -807,6 +898,8 @@
2.452 try_except.body = [assign] + self.dispatch(for_.body) + [continuation]
2.453 subprogram.code = [try_except, Return()]
2.454
2.455 + # Finish the subprogram definition.
2.456 +
2.457 self.subprograms.append(subprogram)
2.458 self.current_subprograms.pop()
2.459