1.1 --- a/simplify.py Mon Nov 27 01:06:38 2006 +0100
1.2 +++ b/simplify.py Tue Nov 28 00:37:12 2006 +0100
1.3 @@ -97,16 +97,16 @@
1.4
1.5 # Placeholder or deletion transformations.
1.6
1.7 - def visitStmt(self, stmt):
1.8 - return self.dispatches(stmt.nodes)
1.9 + def visitDiscard(self, discard):
1.10 + return self.dispatch(discard.expr)
1.11
1.12 def visitPass(self, pass_):
1.13 return Pass(pass_, 1)
1.14
1.15 - def visitDiscard(self, discard):
1.16 - return self.dispatch(discard.expr)
1.17 + def visitStmt(self, stmt):
1.18 + return self.dispatches(stmt.nodes)
1.19
1.20 - # Relatively trivial transformations.
1.21 + # Top-level transformation.
1.22
1.23 def visitModule(self, module, name=None):
1.24
1.25 @@ -140,34 +140,36 @@
1.26 result.code = init_code + module_code
1.27 return result
1.28
1.29 - def visitGetattr(self, getattr):
1.30 - result = LoadAttr(getattr, 1,
1.31 - name=getattr.attrname,
1.32 - expr=self.dispatch(getattr.expr)
1.33 - )
1.34 + # Relatively trivial transformations.
1.35 +
1.36 + def _visitBuiltin(self, builtin, name):
1.37 + result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes), star=None, dstar=None)
1.38 + return result
1.39 +
1.40 + def visitBreak(self, break_):
1.41 + result = ReturnFromBlock(break_, 1)
1.42 return result
1.43
1.44 - def visitKeyword(self, keyword):
1.45 - result = Keyword(keyword, 1,
1.46 - name=keyword.name,
1.47 - expr=self.dispatch(keyword.expr)
1.48 + def visitConst(self, const):
1.49 + if not self.constants.has_key(const.value):
1.50 + self.constants[const.value] = Constant(name=repr(const.value), value=const.value)
1.51 + result = LoadRef(const, 1, ref=self.constants[const.value])
1.52 + return result
1.53 +
1.54 + def visitContinue(self, continue_):
1.55 + result = InvokeBlock(continue_, 1,
1.56 + expr=LoadRef(ref=self.current_subprograms[-1])
1.57 )
1.58 return result
1.59
1.60 - def visitGlobal(self, global_):
1.61 - result = Global(global_, 1,
1.62 - names=global_.names
1.63 - )
1.64 - return result
1.65 -
1.66 - def visitImport(self, import_):
1.67 - result = Assign(import_, 1)
1.68 - code = []
1.69 - for path, alias in import_.names:
1.70 - importer = Import(name=path)
1.71 - top = alias or path.split(".")[0]
1.72 - code.append(StoreName(expr=importer, name=top))
1.73 - result.code = code
1.74 + def visitDict(self, dict):
1.75 + result = InvokeFunction(dict, 1, expr=LoadName(name="dict"), star=None, dstar=None)
1.76 + args = []
1.77 + for key, value in dict.items:
1.78 + tuple = InvokeFunction(expr=LoadName(name="tuple"), star=None, dstar=None)
1.79 + tuple.set_args([self.dispatch(key), self.dispatch(value)])
1.80 + args.append(tuple)
1.81 + result.set_args(args)
1.82 return result
1.83
1.84 def visitFrom(self, from_):
1.85 @@ -187,32 +189,43 @@
1.86 result.code = code
1.87 return result
1.88
1.89 - def visitName(self, name):
1.90 - result = LoadName(name, 1, name=name.name)
1.91 + def visitGetattr(self, getattr):
1.92 + result = LoadAttr(getattr, 1,
1.93 + name=getattr.attrname,
1.94 + expr=self.dispatch(getattr.expr)
1.95 + )
1.96 return result
1.97
1.98 - def visitConst(self, const):
1.99 - if not self.constants.has_key(const.value):
1.100 - self.constants[const.value] = Constant(name=repr(const.value), value=const.value)
1.101 - result = LoadRef(const, 1, ref=self.constants[const.value])
1.102 - return result
1.103 -
1.104 - def visitReturn(self, return_):
1.105 - result = Return(return_, 1,
1.106 - expr=self.dispatch(return_.value)
1.107 + def visitGlobal(self, global_):
1.108 + result = Global(global_, 1,
1.109 + names=global_.names
1.110 )
1.111 return result
1.112
1.113 - def visitBreak(self, break_):
1.114 - result = Return(break_, 1)
1.115 + def visitImport(self, import_):
1.116 + result = Assign(import_, 1)
1.117 + code = []
1.118 + for path, alias in import_.names:
1.119 + importer = Import(name=path)
1.120 + top = alias or path.split(".")[0]
1.121 + code.append(StoreName(expr=importer, name=top))
1.122 + result.code = code
1.123 return result
1.124
1.125 - def visitContinue(self, continue_):
1.126 - result = InvokeBlock(continue_, 1,
1.127 - expr=LoadRef(ref=self.current_subprograms[-1])
1.128 + def visitKeyword(self, keyword):
1.129 + result = Keyword(keyword, 1,
1.130 + name=keyword.name,
1.131 + expr=self.dispatch(keyword.expr)
1.132 )
1.133 return result
1.134
1.135 + def visitList(self, list):
1.136 + return self._visitBuiltin(list, "list")
1.137 +
1.138 + def visitName(self, name):
1.139 + result = LoadName(name, 1, name=name.name)
1.140 + return result
1.141 +
1.142 def visitRaise(self, raise_):
1.143 result = Raise(raise_, 1)
1.144 if raise_.expr2 is None:
1.145 @@ -230,26 +243,15 @@
1.146 result.traceback = None
1.147 return result
1.148
1.149 - def _visitBuiltin(self, builtin, name):
1.150 - result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes), star=None, dstar=None)
1.151 + def visitReturn(self, return_):
1.152 + result = ReturnFromFunction(return_, 1,
1.153 + expr=self.dispatch(return_.value)
1.154 + )
1.155 return result
1.156
1.157 def visitTuple(self, tuple):
1.158 return self._visitBuiltin(tuple, "tuple")
1.159
1.160 - def visitList(self, list):
1.161 - return self._visitBuiltin(list, "list")
1.162 -
1.163 - def visitDict(self, dict):
1.164 - result = InvokeFunction(dict, 1, expr=LoadName(name="dict"), star=None, dstar=None)
1.165 - args = []
1.166 - for key, value in dict.items:
1.167 - tuple = InvokeFunction(expr=LoadName(name="tuple"), star=None, dstar=None)
1.168 - tuple.set_args([self.dispatch(key), self.dispatch(value)])
1.169 - args.append(tuple)
1.170 - result.set_args(args)
1.171 - return result
1.172 -
1.173 # Logical and comparison operations plus chained statements.
1.174
1.175 def visitIf(self, if_):
1.176 @@ -370,7 +372,7 @@
1.177
1.178 # Always return from conditional sections.
1.179
1.180 - test.body += self.dispatch(stmt) + [Return()]
1.181 + test.body += self.dispatch(stmt) + [ReturnFromBlock()]
1.182 nodes.append(test)
1.183 nodes = test.else_ = []
1.184
1.185 @@ -458,8 +460,8 @@
1.186 dstar=None)
1.187
1.188 elif op_name == "is not":
1.189 - invocation = self._visitNot(
1.190 - InvokeFunction(
1.191 + invocation = Not(
1.192 + expr=InvokeFunction(
1.193 expr=LoadName(name="__is__"),
1.194 args=[previous, expr],
1.195 star=None,
1.196 @@ -477,19 +479,25 @@
1.197 nodes.append(
1.198 Conditional(
1.199 test=self._visitNot(LoadTemp()),
1.200 - body=[Return(expr=LoadTemp())])
1.201 + body=[
1.202 + ReturnFromBlock(expr=LoadTemp())
1.203 + ],
1.204 + else_=[
1.205 + ReleaseTemp()
1.206 + # Subsequent operations go here!
1.207 + ]
1.208 + )
1.209 )
1.210
1.211 # Put subsequent operations in the else section of this conditional.
1.212
1.213 - nodes[-1].else_ = [ReleaseTemp()]
1.214 nodes = nodes[-1].else_
1.215
1.216 # For the last operation, return the result.
1.217
1.218 else:
1.219 nodes.append(
1.220 - Return(expr=LoadTemp(release=1))
1.221 + ReturnFromBlock(expr=LoadTemp(release=1))
1.222 )
1.223
1.224 previous = expr
1.225 @@ -519,8 +527,8 @@
1.226
1.227 ...to:
1.228
1.229 - Subprogram -> Conditional (test) -> Return ...
1.230 - (else) -> Conditional (test) -> Return ...
1.231 + Subprogram -> Conditional (test) -> ReturnFromBlock ...
1.232 + (else) -> Conditional (test) -> ReturnFromBlock ...
1.233 (else) -> ...
1.234 """
1.235
1.236 @@ -540,19 +548,30 @@
1.237 # Return from the subprogram where the test is not satisfied.
1.238
1.239 if node is not last:
1.240 - nodes.append(StoreTemp(expr=expr))
1.241 - #invocation = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="__bool__"), args=[], star=None, dstar=None)
1.242 - test = Conditional(test=self._visitNot(LoadTemp()), body=[Return(expr=LoadTemp())])
1.243 - nodes.append(test)
1.244 + nodes += [
1.245 + StoreTemp(expr=expr),
1.246 + Conditional(
1.247 + test=self._visitNot(LoadTemp()),
1.248 + body=[
1.249 + ReturnFromBlock(
1.250 + expr=LoadTemp()
1.251 + )
1.252 + ],
1.253 + else_=[
1.254 + ReleaseTemp()
1.255 + # Subsequent operations go here!
1.256 + ]
1.257 + )
1.258 + ]
1.259
1.260 # Put subsequent operations in the else section of this conditional.
1.261
1.262 - nodes = test.else_ = [ReleaseTemp()]
1.263 + nodes = nodes[-1].else_
1.264
1.265 # For the last operation, return the result.
1.266
1.267 else:
1.268 - nodes.append(Return(expr=expr))
1.269 + nodes.append(ReturnFromBlock(expr=expr))
1.270
1.271 # Finish the subprogram definition.
1.272
1.273 @@ -579,8 +598,8 @@
1.274
1.275 ...to:
1.276
1.277 - Subprogram -> Conditional (test) -> Return ...
1.278 - (else) -> Conditional (test) -> Return ...
1.279 + Subprogram -> Conditional (test) -> ReturnFromBlock ...
1.280 + (else) -> Conditional (test) -> ReturnFromBlock ...
1.281 (else) -> ...
1.282 """
1.283
1.284 @@ -602,7 +621,7 @@
1.285 if node is not last:
1.286 nodes.append(StoreTemp(expr=expr))
1.287 invocation = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="__bool__"), args=[], star=None, dstar=None)
1.288 - test = Conditional(test=invocation, body=[Return(expr=LoadTemp())])
1.289 + test = Conditional(test=invocation, body=[ReturnFromBlock(expr=LoadTemp())])
1.290 nodes.append(test)
1.291
1.292 # Put subsequent operations in the else section of this conditional.
1.293 @@ -613,7 +632,7 @@
1.294
1.295 else:
1.296 nodes.append(
1.297 - Return(expr=expr)
1.298 + ReturnFromBlock(expr=expr)
1.299 )
1.300
1.301 # Finish the subprogram definition.
1.302 @@ -650,49 +669,16 @@
1.303
1.304 # Operators.
1.305
1.306 - def visitUnaryAdd(self, unaryadd):
1.307 - return InvokeFunction(unaryadd, 1,
1.308 - expr=LoadAttr(
1.309 - expr=self.dispatch(unaryadd.expr),
1.310 - name="__pos__"
1.311 - ),
1.312 - args=[],
1.313 - star=None,
1.314 - dstar=None
1.315 - )
1.316 -
1.317 - def visitUnarySub(self, unarysub):
1.318 - return InvokeFunction(unarysub, 1,
1.319 - expr=LoadAttr(
1.320 - expr=self.dispatch(unarysub.expr),
1.321 - name="__neg__"
1.322 - ),
1.323 - args=[],
1.324 - star=None,
1.325 - dstar=None
1.326 - )
1.327 -
1.328 - def visitInvert(self, invert):
1.329 - return InvokeFunction(invert, 1,
1.330 - expr=LoadAttr(
1.331 - expr=self.dispatch(invert.expr),
1.332 - name="__invert__"
1.333 - ),
1.334 - args=[],
1.335 - star=None,
1.336 - dstar=None
1.337 - )
1.338 -
1.339 - def visitAdd(self, add):
1.340 + def _visitBinary(self, binary, left_name, right_name):
1.341
1.342 """
1.343 Emulate the current mechanisms by producing nodes as follows:
1.344
1.345 - InvokeBlock -> Subprogram -> Try (body) -> Return (expr) -> x.__add__(y)
1.346 + InvokeBlock -> Subprogram -> Try (body) -> ReturnFromBlock (expr) -> x.__add__(y)
1.347 (else)
1.348 (handler) -> Conditional (test) -> CheckExc (expr) -> LoadExc
1.349 (choices) -> LoadName TypeError
1.350 - (body) -> Return (expr) -> y.__radd__(x)
1.351 + (body) -> ReturnFromBlock (expr) -> y.__radd__(x)
1.352 (else)
1.353 """
1.354
1.355 @@ -700,12 +686,12 @@
1.356 self.current_subprograms.append(subprogram)
1.357
1.358 subprogram.code = [
1.359 - Try(add, 1,
1.360 + Try(binary, 1,
1.361 body=[
1.362 - Return(
1.363 + ReturnFromBlock(
1.364 expr=InvokeFunction(
1.365 - expr=LoadAttr(expr=self.dispatch(add.left), name="__add__"),
1.366 - args=[self.dispatch(add.right)],
1.367 + expr=LoadAttr(expr=self.dispatch(binary.left), name=left_name),
1.368 + args=[self.dispatch(binary.right)],
1.369 star=None,
1.370 dstar=None)
1.371 )
1.372 @@ -716,10 +702,10 @@
1.373 Conditional(
1.374 test=CheckExc(expr=LoadExc(), choices=[LoadName(name="TypeError")]),
1.375 body=[
1.376 - Return(
1.377 + ReturnFromBlock(
1.378 expr=InvokeFunction(
1.379 - expr=LoadAttr(expr=self.dispatch(add.right), name="__radd__"),
1.380 - args=[self.dispatch(add.left)],
1.381 + expr=LoadAttr(expr=self.dispatch(binary.right), name=right_name),
1.382 + args=[self.dispatch(binary.left)],
1.383 star=None,
1.384 dstar=None)
1.385 )
1.386 @@ -734,6 +720,46 @@
1.387 result.expr = LoadRef(ref=subprogram)
1.388 return result
1.389
1.390 + def visitAdd(self, add):
1.391 + return self._visitBinary(add, "__add__", "__radd__")
1.392 +
1.393 + def visitDiv(self, div):
1.394 + return self._visitBinary(div, "__div__", "__rdiv__")
1.395 +
1.396 + def visitMul(self, mul):
1.397 + return self._visitBinary(mul, "__mul__", "__rmul__")
1.398 +
1.399 + def visitSub(self, sub):
1.400 + return self._visitBinary(sub, "__sub__", "__rsub__")
1.401 +
1.402 + def visitInvert(self, invert):
1.403 + return InvokeFunction(invert, 1,
1.404 + expr=LoadAttr(
1.405 + expr=self.dispatch(invert.expr),
1.406 + name="__invert__"
1.407 + ),
1.408 + args=[],
1.409 + star=None,
1.410 + dstar=None
1.411 + )
1.412 +
1.413 + def _visitUnary(self, unary, name):
1.414 + return InvokeFunction(unary, 1,
1.415 + expr=LoadAttr(
1.416 + expr=self.dispatch(unary.expr),
1.417 + name=name
1.418 + ),
1.419 + args=[],
1.420 + star=None,
1.421 + dstar=None
1.422 + )
1.423 +
1.424 + def visitUnaryAdd(self, unaryadd):
1.425 + return self._visitUnary(unaryadd, "__pos__")
1.426 +
1.427 + def visitUnarySub(self, unarysub):
1.428 + return self._visitUnary(unarysub, "__neg__")
1.429 +
1.430 # Assignments.
1.431
1.432 augassign_methods = {
1.433 @@ -1059,7 +1085,7 @@
1.434
1.435 # The class is initialised using the code found inside.
1.436
1.437 - subprogram.code = self.dispatch(class_.code) + [Return()]
1.438 + subprogram.code = self.dispatch(class_.code) + [ReturnFromBlock()]
1.439
1.440 self.current_structures.pop()
1.441 self.current_subprograms.pop()
1.442 @@ -1155,7 +1181,7 @@
1.443 internal=0, returns_value=1, star=None, dstar=None)
1.444
1.445 self.current_subprograms.append(subprogram)
1.446 - subprogram.code = self.dispatch(function.code) + [Return()]
1.447 + subprogram.code = self.dispatch(function.code) + [ReturnFromFunction()]
1.448 self.current_subprograms.pop()
1.449 self._visitFunction(function, subprogram)
1.450
1.451 @@ -1171,7 +1197,7 @@
1.452
1.453 subprogram = Subprogram(name=None, module=self.module, internal=0, returns_value=1, star=None, dstar=None)
1.454 self.current_subprograms.append(subprogram)
1.455 - subprogram.code = [Return(expr=self.dispatch(lambda_.code))]
1.456 + subprogram.code = [ReturnFromFunction(expr=self.dispatch(lambda_.code))]
1.457 self.current_subprograms.pop()
1.458 self._visitFunction(lambda_, subprogram)
1.459
1.460 @@ -1200,7 +1226,7 @@
1.461 ...to:
1.462
1.463 Subprogram -> Conditional (test) -> (body) -> Invoke subprogram
1.464 - (else) -> Conditional (test) -> Return ...
1.465 + (else) -> Conditional (test) -> ReturnFromBlock ...
1.466 (else) -> ...
1.467 """
1.468
1.469 @@ -1220,12 +1246,12 @@
1.470
1.471 # Return within the main section of the loop.
1.472
1.473 - test.body = self.dispatch(while_.body) + [continuation, Return()]
1.474 + test.body = self.dispatch(while_.body) + [continuation, ReturnFromBlock()]
1.475
1.476 # Provide the else section, if present, along with an explicit return.
1.477
1.478 if while_.else_ is not None:
1.479 - test.else_ = self.dispatch(while_.else_) + [Return()]
1.480 + test.else_ = self.dispatch(while_.else_) + [ReturnFromBlock()]
1.481
1.482 # Finish the subprogram definition.
1.483
1.484 @@ -1266,38 +1292,43 @@
1.485 # Always return from conditional sections/subprograms.
1.486
1.487 if for_.else_ is not None:
1.488 - else_stmt = self.dispatch(for_.else_) + [Return()]
1.489 + else_stmt = self.dispatch(for_.else_) + [ReturnFromBlock()]
1.490 else:
1.491 - else_stmt = [Return()]
1.492 + else_stmt = [ReturnFromBlock()]
1.493
1.494 # Wrap the assignment in a try...except statement.
1.495 -
1.496 - try_except = Try(body=[], else_=[], finally_=[])
1.497 - test = Conditional(
1.498 - test=InvokeFunction(
1.499 - expr=LoadName(name="isinstance"),
1.500 - args=[LoadExc(), LoadName(name="StopIteration")],
1.501 - star=None,
1.502 - dstar=None),
1.503 - body=else_stmt,
1.504 - else_=[Raise(expr=LoadExc())])
1.505 - try_except.handler = [test]
1.506 + # Inside the body, add a recursive invocation to the subprogram.
1.507
1.508 - assign = Assign(
1.509 - code=[
1.510 - StoreTemp(expr=InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), args=[], star=None, dstar=None)),
1.511 - self.dispatch(for_.assign),
1.512 - ReleaseTemp()
1.513 - ])
1.514 -
1.515 - # Inside the conditional, add a recursive invocation to the subprogram
1.516 - # if the test condition was satisfied.
1.517 -
1.518 - continuation = InvokeBlock(
1.519 - expr=LoadRef(ref=subprogram)
1.520 - )
1.521 - try_except.body = [assign] + self.dispatch(for_.body) + [continuation]
1.522 - subprogram.code = [try_except, Return()]
1.523 + subprogram.code = [
1.524 + Try(
1.525 + body=[
1.526 + Assign(
1.527 + code=[
1.528 + StoreTemp(expr=InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), args=[], star=None, dstar=None)),
1.529 + self.dispatch(for_.assign),
1.530 + ReleaseTemp()
1.531 + ])
1.532 + ] + self.dispatch(for_.body) + [
1.533 + InvokeBlock(
1.534 + expr=LoadRef(ref=subprogram)
1.535 + )
1.536 + ],
1.537 + handler=[
1.538 + Conditional(
1.539 + test=InvokeFunction(
1.540 + expr=LoadName(name="isinstance"),
1.541 + args=[LoadExc(), LoadName(name="StopIteration")],
1.542 + star=None,
1.543 + dstar=None),
1.544 + body=else_stmt,
1.545 + else_=[Raise(expr=LoadExc())]
1.546 + )
1.547 + ],
1.548 + else_=[],
1.549 + finally_=[]
1.550 + ),
1.551 + ReturnFromBlock()
1.552 + ]
1.553
1.554 # Finish the subprogram definition.
1.555