1.1 --- a/simplify.py Mon Jul 31 01:01:34 2006 +0200
1.2 +++ b/simplify.py Mon Jul 31 21:20:33 2006 +0200
1.3 @@ -186,83 +186,73 @@
1.4 def visitIf(self, if_):
1.5
1.6 """
1.7 - Convert If(tests=..., else_=...) to:
1.8 + Make conditionals for each test from an 'if_' AST node, adding the body
1.9 + and putting each subsequent test as part of the conditional's else
1.10 + section.
1.11 +
1.12 + Convert...
1.13
1.14 - Invoke -> Subprogram
1.15 - Conditional (test) -> Invoke -> Subprogram (body)
1.16 - Return
1.17 - Conditional (test) -> Invoke -> Subprogram (body)
1.18 - Return
1.19 - ...
1.20 + If (test/body)
1.21 + (test/body)
1.22 + ...
1.23 + (else/body)
1.24 +
1.25 + ...to:
1.26 +
1.27 + Conditional (test) -> (body)
1.28 + (else) -> Conditional (test) -> (body)
1.29 + (else) -> ...
1.30 """
1.31
1.32 - # Make a subprogram for the statement and record it outside the main tree.
1.33 -
1.34 - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.35 - self.current_subprograms.append(subprogram)
1.36
1.37 - # In the subprogram, make conditionals for each test plus statement,
1.38 - # adding a return onto the end of each statement block.
1.39 + results = nodes = []
1.40
1.41 - nodes = []
1.42 for compare, stmt in if_.tests:
1.43 # Produce something like...
1.44 # expr.__true__() ? body
1.45 - test = Conditional(else_=[], test=Invoke(
1.46 - expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
1.47 + test = Conditional(test=Invoke(expr=LoadAttr(expr=self.dispatch(compare), name="__true__"),
1.48 args=[], star=None, dstar=None))
1.49 -
1.50 - body_subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.51 - self.current_subprograms.append(body_subprogram)
1.52 -
1.53 - body_subprogram.code = self.dispatch(stmt) + [Return()]
1.54 -
1.55 - self.current_subprograms.pop()
1.56 - self.subprograms.append(body_subprogram)
1.57 -
1.58 - # Always return from conditional sections.
1.59 -
1.60 - test.body = [Invoke(stmt, expr=LoadRef(ref=body_subprogram), same_frame=1, star=None, dstar=None, args=[]), Return()]
1.61 + test.body = self.dispatch(stmt)
1.62 nodes.append(test)
1.63 + nodes = test.else_ = []
1.64
1.65 # Add the compound statement from any else clause to the end.
1.66
1.67 if if_.else_ is not None:
1.68 - else_subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.69 - self.current_subprograms.append(else_subprogram)
1.70 -
1.71 - else_subprogram.code = self.dispatch(if_.else_) + [Return()]
1.72 -
1.73 - self.current_subprograms.pop()
1.74 - self.subprograms.append(else_subprogram)
1.75 -
1.76 - # Always return from conditional subprograms.
1.77 + nodes += self.dispatch(if_.else_)
1.78
1.79 - nodes.append(Invoke(stmt, expr=LoadRef(ref=else_subprogram), same_frame=1, star=None, dstar=None, args=[]))
1.80 - nodes.append(Return())
1.81 -
1.82 - subprogram.code = nodes
1.83 -
1.84 - self.current_subprograms.pop()
1.85 - self.subprograms.append(subprogram)
1.86 -
1.87 - # Make an invocation of the subprogram.
1.88 -
1.89 - result = Invoke(compare, same_frame=1, star=None, dstar=None, args=[])
1.90 - result.expr = LoadRef(ref=subprogram)
1.91 + result = results[0]
1.92 return result
1.93
1.94 - def _visitTryExcept(self, tryexcept):
1.95 + def visitTryExcept(self, tryexcept):
1.96 +
1.97 + """
1.98 + Make conditionals for each handler associated with a 'tryexcept' node.
1.99 +
1.100 + Convert...
1.101
1.102 - # Make a subprogram for the statement and record it outside the main tree.
1.103 + TryExcept (body)
1.104 + (else)
1.105 + (spec/assign/stmt)
1.106 + ...
1.107 +
1.108 + ...to:
1.109
1.110 - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.111 - self.current_subprograms.append(subprogram)
1.112 + Try (body)
1.113 + (else)
1.114 + (handler) -> Conditional (test) -> (stmt)
1.115 + (else) -> Conditional (test) -> (stmt)
1.116 + (else) -> ...
1.117 + """
1.118 +
1.119 + result = Try(tryexcept, body=[], else_=[], finally_=[])
1.120
1.121 - # In the subprogram, make conditionals for each test plus statement,
1.122 - # adding a return onto the end of each statement block.
1.123 + if tryexcept.body is not None:
1.124 + result.body = self.dispatch(tryexcept.body)
1.125 + if tryexcept.else_ is not None:
1.126 + result.else_ = self.dispatch(tryexcept.else_)
1.127
1.128 - nodes = []
1.129 + results = nodes = []
1.130 for spec, assign, stmt in tryexcept.handlers:
1.131
1.132 # If no specification exists, produce an unconditional block.
1.133 @@ -275,7 +265,9 @@
1.134
1.135 else:
1.136 new_spec = self.dispatch(spec)
1.137 - test = Conditional(body=[], else_=[], test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None))
1.138 + test = Conditional(test=Invoke(expr=LoadName(name="isinstance"), args=[LoadExc(), new_spec], star=None, dstar=None))
1.139 + test.body = []
1.140 +
1.141 if assign is not None:
1.142 test.body.append(Assign(code=[StoreTemp(expr=LoadExc()), self.dispatch(assign), ReleaseTemp()]))
1.143
1.144 @@ -283,28 +275,13 @@
1.145
1.146 test.body += self.dispatch(stmt) + [Return()]
1.147 nodes.append(test)
1.148 + nodes = test.else_ = []
1.149
1.150 # Add a raise operation to deal with unhandled exceptions.
1.151
1.152 nodes.append(Raise(expr=LoadExc()))
1.153 - subprogram.code = nodes
1.154
1.155 - self.current_subprograms.pop()
1.156 - self.subprograms.append(subprogram)
1.157 -
1.158 - # Make an invocation of the subprogram.
1.159 -
1.160 - result = Invoke(same_frame=1, star=None, dstar=None, args=[])
1.161 - result.expr = LoadRef(ref=subprogram)
1.162 - return result
1.163 -
1.164 - def visitTryExcept(self, tryexcept):
1.165 - result = Try(tryexcept, body=[], else_=[], finally_=[])
1.166 - if tryexcept.body is not None:
1.167 - result.body = self.dispatch(tryexcept.body)
1.168 - if tryexcept.else_ is not None:
1.169 - result.else_ = self.dispatch(tryexcept.else_)
1.170 - result.handler = self._visitTryExcept(tryexcept)
1.171 + result.handler = results
1.172 return result
1.173
1.174 comparison_methods = {
1.175 @@ -314,7 +291,20 @@
1.176
1.177 def visitCompare(self, compare):
1.178
1.179 - # Make a subprogram for the expression and record it outside the main tree.
1.180 + """
1.181 + Make a subprogram for the 'compare' node and record its contents inside
1.182 + the subprogram. Convert...
1.183 +
1.184 + Compare (expr)
1.185 + (name/node)
1.186 + ...
1.187 +
1.188 + ...to:
1.189 +
1.190 + Subprogram -> Conditional (test) -> (body)
1.191 + (else) -> Conditional (test) -> (body)
1.192 + (else) -> ...
1.193 + """
1.194
1.195 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
1.196 self.current_subprograms.append(subprogram)
1.197 @@ -323,12 +313,16 @@
1.198 # first operand of each operand pair and, if appropriate, return with
1.199 # the value from that method.
1.200
1.201 - nodes = []
1.202 last = compare.ops[-1]
1.203 previous = self.dispatch(compare.expr)
1.204 + results = nodes = []
1.205 +
1.206 for op in compare.ops:
1.207 op_name, node = op
1.208 expr = self.dispatch(node)
1.209 +
1.210 + # Identify the operation and produce the appropriate method call.
1.211 +
1.212 method_name = self.comparison_methods[op_name]
1.213 if method_name:
1.214 invocation = Invoke(expr=LoadAttr(expr=previous, name=method_name), args=[expr], star=None, dstar=None)
1.215 @@ -340,15 +334,26 @@
1.216 raise NotImplementedError, op_name
1.217 nodes.append(StoreTemp(expr=invocation))
1.218
1.219 - # Always return from conditional sections/subprograms.
1.220 + # Return from the subprogram where the test is not satisfied.
1.221
1.222 if op is not last:
1.223 - nodes.append(Conditional(test=Not(expr=LoadTemp()), body=[Return(expr=LoadTemp())]))
1.224 - nodes.append(ReleaseTemp())
1.225 + test = Conditional(test=Not(expr=LoadTemp()), body=[Return(expr=LoadTemp())])
1.226 + nodes.append(test)
1.227 +
1.228 + # Put subsequent operations in the else section of this conditional.
1.229 +
1.230 + nodes = test.else_ = [ReleaseTemp()]
1.231 +
1.232 + # For the last operation, return the result.
1.233 +
1.234 else:
1.235 nodes.append(Return(expr=LoadTemp()))
1.236 +
1.237 previous = expr
1.238 - subprogram.code = nodes
1.239 +
1.240 + # Finish the subprogram definition.
1.241 +
1.242 + subprogram.code = results
1.243
1.244 self.current_subprograms.pop()
1.245 self.subprograms.append(subprogram)
1.246 @@ -361,7 +366,20 @@
1.247
1.248 def visitAnd(self, and_):
1.249
1.250 - # Make a subprogram for the expression and record it outside the main tree.
1.251 + """
1.252 + Make a subprogram for the 'and_' node and record its contents inside the
1.253 + subprogram. Convert...
1.254 +
1.255 + And (test)
1.256 + (test)
1.257 + ...
1.258 +
1.259 + ...to:
1.260 +
1.261 + Subprogram -> Conditional (test) -> Return ...
1.262 + (else) -> Conditional (test) -> Return ...
1.263 + (else) -> ...
1.264 + """
1.265
1.266 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
1.267 self.current_subprograms.append(subprogram)
1.268 @@ -370,21 +388,32 @@
1.269 # for each operand's truth status, and if appropriate return from the
1.270 # subprogram with the value of the operand.
1.271
1.272 - nodes = []
1.273 last = and_.nodes[-1]
1.274 + results = nodes = []
1.275 +
1.276 for node in and_.nodes:
1.277 expr = self.dispatch(node)
1.278
1.279 - # Always return from conditional sections/subprograms.
1.280 + # Return from the subprogram where the test is not satisfied.
1.281
1.282 if node is not last:
1.283 nodes.append(StoreTemp(expr=expr))
1.284 invocation = Invoke(expr=LoadAttr(expr=LoadTemp(), name="__true__"), args=[], star=None, dstar=None)
1.285 - nodes.append(Conditional(test=Not(expr=invocation), body=[Return(expr=LoadTemp())]))
1.286 - nodes.append(ReleaseTemp())
1.287 + test = Conditional(test=Not(expr=invocation), body=[Return(expr=LoadTemp())])
1.288 + nodes.append(test)
1.289 +
1.290 + # Put subsequent operations in the else section of this conditional.
1.291 +
1.292 + nodes = test.else_ = [ReleaseTemp()]
1.293 +
1.294 + # For the last operation, return the result.
1.295 +
1.296 else:
1.297 nodes.append(Return(expr=expr))
1.298 - subprogram.code = nodes
1.299 +
1.300 + # Finish the subprogram definition.
1.301 +
1.302 + subprogram.code = results
1.303
1.304 self.current_subprograms.pop()
1.305 self.subprograms.append(subprogram)
1.306 @@ -397,7 +426,20 @@
1.307
1.308 def visitOr(self, or_):
1.309
1.310 - # Make a subprogram for the expression and record it outside the main tree.
1.311 + """
1.312 + Make a subprogram for the 'or_' node and record its contents inside the
1.313 + subprogram. Convert...
1.314 +
1.315 + Or (test)
1.316 + (test)
1.317 + ...
1.318 +
1.319 + ...to:
1.320 +
1.321 + Subprogram -> Conditional (test) -> Return ...
1.322 + (else) -> Conditional (test) -> Return ...
1.323 + (else) -> ...
1.324 + """
1.325
1.326 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None)
1.327 self.current_subprograms.append(subprogram)
1.328 @@ -406,21 +448,32 @@
1.329 # for each operand's truth status, and if appropriate return from the
1.330 # subprogram with the value of the operand.
1.331
1.332 - nodes = []
1.333 last = or_.nodes[-1]
1.334 + results = nodes = []
1.335 +
1.336 for node in or_.nodes:
1.337 expr = self.dispatch(node)
1.338
1.339 - # Always return from conditional sections/subprograms.
1.340 + # Return from the subprogram where the test is satisfied.
1.341
1.342 if node is not last:
1.343 nodes.append(StoreTemp(expr=expr))
1.344 invocation = Invoke(expr=LoadAttr(expr=LoadTemp(), name="__true__"), args=[], star=None, dstar=None)
1.345 - nodes.append(Conditional(test=invocation, body=[Return(expr=LoadTemp())]))
1.346 - nodes.append(ReleaseTemp())
1.347 + test = Conditional(test=invocation, body=[Return(expr=LoadTemp())])
1.348 + nodes.append(test)
1.349 +
1.350 + # Put subsequent operations in the else section of this conditional.
1.351 +
1.352 + nodes = test.else_ = [ReleaseTemp()]
1.353 +
1.354 + # For the last operation, return the result.
1.355 +
1.356 else:
1.357 nodes.append(Return(expr=expr))
1.358 - subprogram.code = nodes
1.359 +
1.360 + # Finish the subprogram definition.
1.361 +
1.362 + subprogram.code = results
1.363
1.364 self.current_subprograms.pop()
1.365 self.subprograms.append(subprogram)
1.366 @@ -738,7 +791,19 @@
1.367
1.368 def visitWhile(self, while_):
1.369
1.370 - # Make a subprogram for the block and record it outside the main tree.
1.371 + """
1.372 + Make a subprogram for the 'while' node and record its contents inside the
1.373 + subprogram. Convert...
1.374 +
1.375 + While (test) -> (body)
1.376 + (else)
1.377 +
1.378 + ...to:
1.379 +
1.380 + Subprogram -> Conditional (test) -> (body) -> Invoke subprogram
1.381 + (else) -> Conditional (test) -> Return ...
1.382 + (else) -> ...
1.383 + """
1.384
1.385 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.386 self.current_subprograms.append(subprogram)
1.387 @@ -755,12 +820,18 @@
1.388 continuation = Invoke(same_frame=1, star=None, dstar=None, args=[])
1.389 continuation.expr = LoadRef(ref=subprogram)
1.390
1.391 - # Always return from conditional sections/subprograms.
1.392 + # Return within the main section of the loop.
1.393
1.394 test.body = self.dispatch(while_.body) + [continuation, Return()]
1.395 +
1.396 + # Provide the else section, if present, along with an explicit return.
1.397 +
1.398 if while_.else_ is not None:
1.399 - test.else_ = self.dispatch(while_.else_)
1.400 - subprogram.code = [test, Return()]
1.401 + test.else_ = self.dispatch(while_.else_) + [Return()]
1.402 +
1.403 + # Finish the subprogram definition.
1.404 +
1.405 + subprogram.code = test
1.406
1.407 self.current_subprograms.pop()
1.408 self.subprograms.append(subprogram)
1.409 @@ -773,7 +844,23 @@
1.410
1.411 def visitFor(self, for_):
1.412
1.413 - # Make a subprogram for the block and record it outside the main tree.
1.414 + """
1.415 + Make a subprogram for the 'for_' node and record its contents inside the
1.416 + subprogram. Convert...
1.417 +
1.418 + For (assign)
1.419 + (body)
1.420 + (else)
1.421 +
1.422 + ...to:
1.423 +
1.424 + Assign (assign #1)
1.425 + Invoke -> Subprogram -> Try (body) -> (assign #2)
1.426 + (body)
1.427 + Invoke subprogram
1.428 + (handler) -> ...
1.429 + (else) -> ...
1.430 + """
1.431
1.432 subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None)
1.433 self.current_subprograms.append(subprogram)
1.434 @@ -788,9 +875,13 @@
1.435 # Wrap the assignment in a try...except statement.
1.436
1.437 try_except = Try(body=[], else_=[], finally_=[])
1.438 - try_except.handler = Conditional(test=Invoke(expr=LoadName(name="isinstance"),
1.439 - args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None),
1.440 - body=else_stmt, else_=[Raise(expr=LoadExc())])
1.441 + try_except.handler = Conditional(
1.442 + test=Invoke(
1.443 + expr=LoadName(name="isinstance"),
1.444 + args=[LoadExc(), LoadName(name="StopIteration")], star=None, dstar=None
1.445 + ),
1.446 + body=else_stmt,
1.447 + else_=[Raise(expr=LoadExc())])
1.448
1.449 assign = Assign()
1.450 assign.code = [
1.451 @@ -807,6 +898,8 @@
1.452 try_except.body = [assign] + self.dispatch(for_.body) + [continuation]
1.453 subprogram.code = [try_except, Return()]
1.454
1.455 + # Finish the subprogram definition.
1.456 +
1.457 self.subprograms.append(subprogram)
1.458 self.current_subprograms.pop()
1.459