1.1 --- a/simplify.py Fri Dec 01 00:32:06 2006 +0100
1.2 +++ b/simplify.py Sat Dec 02 00:14:33 2006 +0100
1.3 @@ -94,17 +94,6 @@
1.4 else:
1.5 return LoadName(node, name="None")
1.6
1.7 - # Placeholder or deletion transformations.
1.8 -
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 visitStmt(self, stmt):
1.16 - return self.dispatches(stmt.nodes)
1.17 -
1.18 # Top-level transformation.
1.19
1.20 def visitModule(self, module, name=None):
1.21 @@ -139,380 +128,10 @@
1.22 result.code = init_code + module_code
1.23 return result
1.24
1.25 - # Relatively trivial transformations.
1.26 -
1.27 - def _visitBuiltin(self, builtin, name):
1.28 - result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes), star=None, dstar=None)
1.29 - return result
1.30 -
1.31 - def visitBreak(self, break_):
1.32 - result = ReturnFromBlock(break_, 1)
1.33 - return result
1.34 -
1.35 - def visitConst(self, const):
1.36 - if not self.constants.has_key(const.value):
1.37 - self.constants[const.value] = Constant(name=repr(const.value), value=const.value)
1.38 - result = LoadRef(const, 1, ref=self.constants[const.value])
1.39 - return result
1.40 -
1.41 - def visitContinue(self, continue_):
1.42 - result = InvokeBlock(continue_, 1,
1.43 - expr=LoadRef(ref=self.current_subprograms[-1])
1.44 - )
1.45 - return result
1.46 -
1.47 - def visitDict(self, dict):
1.48 - result = InvokeFunction(dict, 1, expr=LoadName(name="dict"), star=None, dstar=None)
1.49 - args = []
1.50 - for key, value in dict.items:
1.51 - tuple = InvokeFunction(expr=LoadName(name="tuple"), star=None, dstar=None)
1.52 - tuple.set_args([self.dispatch(key), self.dispatch(value)])
1.53 - args.append(tuple)
1.54 - result.set_args(args)
1.55 - return result
1.56 -
1.57 - def visitFrom(self, from_):
1.58 - result = Assign(from_, 1)
1.59 - code = []
1.60 - code.append(StoreTemp(expr=Import(name=from_.modname)))
1.61 - for name, alias in from_.names:
1.62 - code.append(
1.63 - StoreName(
1.64 - expr=LoadAttr(
1.65 - expr=LoadTemp(),
1.66 - name=name),
1.67 - name=(alias or name)
1.68 - )
1.69 - )
1.70 - code.append(ReleaseTemp())
1.71 - result.code = code
1.72 - return result
1.73 -
1.74 - def visitGetattr(self, getattr):
1.75 - result = LoadAttr(getattr, 1,
1.76 - name=getattr.attrname,
1.77 - expr=self.dispatch(getattr.expr)
1.78 - )
1.79 - return result
1.80 -
1.81 - def visitGlobal(self, global_):
1.82 - result = Global(global_, 1,
1.83 - names=global_.names
1.84 - )
1.85 - return result
1.86 -
1.87 - def visitImport(self, import_):
1.88 - result = Assign(import_, 1)
1.89 - code = []
1.90 - for path, alias in import_.names:
1.91 - importer = Import(name=path)
1.92 - top = alias or path.split(".")[0]
1.93 - code.append(StoreName(expr=importer, name=top))
1.94 - result.code = code
1.95 - return result
1.96 -
1.97 - def visitKeyword(self, keyword):
1.98 - result = Keyword(keyword, 1,
1.99 - name=keyword.name,
1.100 - expr=self.dispatch(keyword.expr)
1.101 - )
1.102 - return result
1.103 -
1.104 - def visitList(self, list):
1.105 - return self._visitBuiltin(list, "list")
1.106 -
1.107 - def visitName(self, name):
1.108 - result = LoadName(name, 1, name=name.name)
1.109 - return result
1.110 -
1.111 - def visitRaise(self, raise_):
1.112 - result = Raise(raise_, 1)
1.113 - if raise_.expr2 is None:
1.114 - result.expr = self.dispatch(raise_.expr1)
1.115 - else:
1.116 - result.expr = InvokeFunction(
1.117 - expr=self.dispatch(raise_.expr1),
1.118 - args=[self.dispatch(raise_.expr2)],
1.119 - star=None,
1.120 - dstar=None
1.121 - )
1.122 - if raise_.expr3 is not None:
1.123 - result.traceback = self.dispatch(raise_.expr3)
1.124 - else:
1.125 - result.traceback = None
1.126 - return result
1.127 -
1.128 - def visitReturn(self, return_):
1.129 - result = ReturnFromFunction(return_, 1,
1.130 - expr=self.dispatch(return_.value)
1.131 - )
1.132 - return result
1.133 -
1.134 - def visitTuple(self, tuple):
1.135 - return self._visitBuiltin(tuple, "tuple")
1.136 -
1.137 - # Logical and comparison operations plus chained statements.
1.138 -
1.139 - def visitIf(self, if_):
1.140 -
1.141 - """
1.142 - Make conditionals for each test from an 'if_' AST node, adding the body
1.143 - and putting each subsequent test as part of the conditional's else
1.144 - section.
1.145 -
1.146 - Convert...
1.147 -
1.148 - If (test/body)
1.149 - (test/body)
1.150 - ...
1.151 - (else/body)
1.152 -
1.153 - ...to:
1.154 -
1.155 - Conditional (test) -> (body)
1.156 - (else) -> Conditional (test) -> (body)
1.157 - (else) -> ...
1.158 - """
1.159 -
1.160 -
1.161 - results = nodes = []
1.162 -
1.163 - # Produce something like...
1.164 - # expr.__bool__() ? body
1.165 -
1.166 - first = 1
1.167 - for compare, stmt in if_.tests:
1.168 -
1.169 - # Set the first as the defining node.
1.170 -
1.171 - test = Conditional(if_, first,
1.172 - test=InvokeFunction(
1.173 - expr=LoadAttr(
1.174 - expr=self.dispatch(compare),
1.175 - name="__bool__"
1.176 - ),
1.177 - args=[],
1.178 - star=None,
1.179 - dstar=None)
1.180 - )
1.181 - test.body = self.dispatch(stmt)
1.182 - nodes.append(test)
1.183 - nodes = test.else_ = []
1.184 - first = 0
1.185 -
1.186 - # Add the compound statement from any else clause to the end.
1.187 -
1.188 - if if_.else_ is not None:
1.189 - nodes += self.dispatch(if_.else_)
1.190 -
1.191 - result = results[0]
1.192 - return result
1.193 -
1.194 - def visitTryExcept(self, tryexcept):
1.195 -
1.196 - """
1.197 - Make conditionals for each handler associated with a 'tryexcept' node.
1.198 -
1.199 - Convert...
1.200 -
1.201 - TryExcept (body)
1.202 - (else)
1.203 - (spec/assign/stmt)
1.204 - ...
1.205 -
1.206 - ...to:
1.207 + # Node transformations.
1.208
1.209 - Try (body)
1.210 - (else)
1.211 - (handler) -> Conditional (test) -> (stmt)
1.212 - (body) -> ...
1.213 - (else) -> Conditional (test) -> (stmt)
1.214 - (body) -> ...
1.215 - (else) -> ...
1.216 - """
1.217 -
1.218 - result = Try(tryexcept, 1, body=[], else_=[], finally_=[])
1.219 -
1.220 - if tryexcept.body is not None:
1.221 - result.body = self.dispatch(tryexcept.body)
1.222 - if tryexcept.else_ is not None:
1.223 - result.else_ = self.dispatch(tryexcept.else_)
1.224 -
1.225 - results = nodes = []
1.226 - catch_all = 0
1.227 -
1.228 - for spec, assign, stmt in tryexcept.handlers:
1.229 -
1.230 - # If no specification exists, produce an unconditional block.
1.231 -
1.232 - if spec is None:
1.233 - nodes += self.dispatch(stmt)
1.234 - catch_all = 1
1.235 -
1.236 - # Produce an exception value check.
1.237 -
1.238 - else:
1.239 - test = Conditional(
1.240 - isolate_test=1,
1.241 - test=CheckExc(expr=LoadExc(), choices=self._visitTryExcept(spec))
1.242 - )
1.243 - test.body = []
1.244 -
1.245 - if assign is not None:
1.246 - test.body.append(
1.247 - Assign(
1.248 - code=[
1.249 - StoreTemp(expr=LoadExc()),
1.250 - self.dispatch(assign),
1.251 - ReleaseTemp()
1.252 - ]
1.253 - )
1.254 - )
1.255 -
1.256 - # Always return from conditional sections.
1.257 -
1.258 - test.body += self.dispatch(stmt) + [ReturnFromBlock()]
1.259 - nodes.append(test)
1.260 - nodes = test.else_ = []
1.261 -
1.262 - # Add a raise operation to deal with unhandled exceptions.
1.263 -
1.264 - if not catch_all:
1.265 - nodes.append(
1.266 - Raise(
1.267 - expr=LoadExc())
1.268 - )
1.269 -
1.270 - result.handler = results
1.271 - return result
1.272 -
1.273 - def _visitTryExcept(self, spec):
1.274 -
1.275 - "Return a list of nodes for the given exception type 'spec'."
1.276 -
1.277 - if isinstance(spec, compiler.ast.Tuple):
1.278 - nodes = []
1.279 - for node in spec.nodes:
1.280 - nodes += self._visitTryExcept(node)
1.281 - else:
1.282 - nodes = [self.dispatch(spec)]
1.283 - return nodes
1.284 -
1.285 - comparison_methods = {
1.286 - "==" : "__eq__", "!=" : "__ne__", "<" : "__lt__", "<=" : "__le__",
1.287 - ">=" : "__ge__", ">" : "__gt__", "is" : None, "is not" : None
1.288 - }
1.289 -
1.290 - def visitCompare(self, compare):
1.291 -
1.292 - """
1.293 - Make a subprogram for the 'compare' node and record its contents inside
1.294 - the subprogram. Convert...
1.295 -
1.296 - Compare (expr)
1.297 - (name/node)
1.298 - ...
1.299 -
1.300 - ...to:
1.301 -
1.302 - InvokeBlock -> Subprogram -> Conditional (test) -> (body)
1.303 - (else) -> Conditional (test) -> (body)
1.304 - (else) -> ...
1.305 - """
1.306 -
1.307 - subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.308 - self.current_subprograms.append(subprogram)
1.309 -
1.310 - # In the subprogram, make instructions which invoke a method on the
1.311 - # first operand of each operand pair and, if appropriate, return with
1.312 - # the value from that method.
1.313 -
1.314 - last = compare.ops[-1]
1.315 - previous = self.dispatch(compare.expr)
1.316 - results = nodes = []
1.317 -
1.318 - # For viewing purposes, record invocations on the AST node.
1.319 -
1.320 - compare._ops = []
1.321 -
1.322 - for op in compare.ops:
1.323 - op_name, node = op
1.324 - expr = self.dispatch(node)
1.325 -
1.326 - # Identify the operation and produce the appropriate method call.
1.327 -
1.328 - method_name = self.comparison_methods[op_name]
1.329 - if method_name:
1.330 - invocation = InvokeFunction(
1.331 - expr=LoadAttr(
1.332 - expr=previous,
1.333 - name=method_name),
1.334 - args=[expr],
1.335 - star=None,
1.336 - dstar=None)
1.337 -
1.338 - elif op_name == "is":
1.339 - invocation = InvokeFunction(
1.340 - expr=LoadName(name="__is__"),
1.341 - args=[previous, expr],
1.342 - star=None,
1.343 - dstar=None)
1.344 -
1.345 - elif op_name == "is not":
1.346 - invocation = Not(
1.347 - expr=InvokeFunction(
1.348 - expr=LoadName(name="__is__"),
1.349 - args=[previous, expr],
1.350 - star=None,
1.351 - dstar=None)
1.352 - )
1.353 - else:
1.354 - raise NotImplementedError, op_name
1.355 -
1.356 - nodes.append(StoreTemp(expr=invocation))
1.357 - compare._ops.append(invocation)
1.358 -
1.359 - # Return from the subprogram where the test is not satisfied.
1.360 -
1.361 - if op is not last:
1.362 - nodes.append(
1.363 - Conditional(
1.364 - test=self._visitNot(LoadTemp()),
1.365 - body=[
1.366 - ReturnFromBlock(expr=LoadTemp())
1.367 - ],
1.368 - else_=[
1.369 - ReleaseTemp()
1.370 - # Subsequent operations go here!
1.371 - ]
1.372 - )
1.373 - )
1.374 -
1.375 - # Put subsequent operations in the else section of this conditional.
1.376 -
1.377 - nodes = nodes[-1].else_
1.378 -
1.379 - # For the last operation, return the result.
1.380 -
1.381 - else:
1.382 - nodes.append(
1.383 - ReturnFromBlock(expr=LoadTemp(release=1))
1.384 - )
1.385 -
1.386 - previous = expr
1.387 -
1.388 - # Finish the subprogram definition.
1.389 -
1.390 - subprogram.code = results
1.391 -
1.392 - self.current_subprograms.pop()
1.393 - self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.394 -
1.395 - # Make an invocation of the subprogram.
1.396 -
1.397 - result = InvokeBlock(compare, 1, produces_result=1)
1.398 - result.expr = LoadRef(ref=subprogram)
1.399 - return result
1.400 + def visitAdd(self, add):
1.401 + return self._visitBinary(add, "__add__", "__radd__")
1.402
1.403 def visitAnd(self, and_):
1.404
1.405 @@ -585,187 +204,44 @@
1.406 result.expr = LoadRef(ref=subprogram)
1.407 return result
1.408
1.409 - def visitOr(self, or_):
1.410 -
1.411 - """
1.412 - Make a subprogram for the 'or_' node and record its contents inside the
1.413 - subprogram. Convert...
1.414 -
1.415 - Or (test)
1.416 - (test)
1.417 - ...
1.418 -
1.419 - ...to:
1.420 -
1.421 - Subprogram -> Conditional (test) -> ReturnFromBlock ...
1.422 - (else) -> Conditional (test) -> ReturnFromBlock ...
1.423 - (else) -> ...
1.424 - """
1.425 -
1.426 - subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.427 - self.current_subprograms.append(subprogram)
1.428 -
1.429 - # In the subprogram, make instructions which store each operand, test
1.430 - # for each operand's truth status, and if appropriate return from the
1.431 - # subprogram with the value of the operand.
1.432 -
1.433 - last = or_.nodes[-1]
1.434 - results = nodes = []
1.435 -
1.436 - for node in or_.nodes:
1.437 - expr = self.dispatch(node)
1.438 + # Assignments.
1.439
1.440 - # Return from the subprogram where the test is satisfied.
1.441 -
1.442 - if node is not last:
1.443 - nodes.append(StoreTemp(expr=expr))
1.444 - invocation = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="__bool__"), args=[], star=None, dstar=None)
1.445 - test = Conditional(test=invocation, body=[ReturnFromBlock(expr=LoadTemp())])
1.446 - nodes.append(test)
1.447 -
1.448 - # Put subsequent operations in the else section of this conditional.
1.449 -
1.450 - nodes = test.else_ = [ReleaseTemp()]
1.451 -
1.452 - # For the last operation, return the result.
1.453 -
1.454 - else:
1.455 - nodes.append(
1.456 - ReturnFromBlock(expr=expr)
1.457 - )
1.458 -
1.459 - # Finish the subprogram definition.
1.460 -
1.461 - subprogram.code = results
1.462 -
1.463 - self.current_subprograms.pop()
1.464 - self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.465 -
1.466 - # Make an invocation of the subprogram.
1.467 -
1.468 - result = InvokeBlock(or_, 1, produces_result=1)
1.469 - result.expr = LoadRef(ref=subprogram)
1.470 + def visitAssAttr(self, assattr, in_sequence=0):
1.471 + expr = self._visitAssNameOrAttr(assattr, in_sequence)
1.472 + lvalue = self.dispatch(assattr.expr)
1.473 + result = StoreAttr(assattr, 1, name=assattr.attrname, lvalue=lvalue, expr=expr)
1.474 return result
1.475
1.476 - def _visitNot(self, expr, not_=None):
1.477 - invocation = InvokeFunction(
1.478 - expr=LoadAttr(
1.479 - expr=expr,
1.480 - name="__bool__"
1.481 - ),
1.482 - args=[],
1.483 - star=None,
1.484 - dstar=None
1.485 - )
1.486 - if not_ is not None:
1.487 - result = Not(not_, 1, expr=invocation)
1.488 - else:
1.489 - result = Not(expr=invocation)
1.490 + def visitAssign(self, assign):
1.491 + result = Assign(assign, 1)
1.492 + store = StoreTemp(expr=self.dispatch(assign.expr))
1.493 + release = ReleaseTemp()
1.494 + result.code = [store] + self.dispatches(assign.nodes, 0) + [release]
1.495 return result
1.496
1.497 - def visitNot(self, not_):
1.498 - return self._visitNot(self.dispatch(not_.expr), not_)
1.499 -
1.500 - # Operators.
1.501 -
1.502 - def _visitBinary(self, binary, left_name, right_name):
1.503 -
1.504 - """
1.505 - Emulate the current mechanisms by producing nodes as follows:
1.506 -
1.507 - InvokeBlock -> Subprogram -> Try (body) -> ReturnFromBlock (expr) -> x.__add__(y)
1.508 - (else)
1.509 - (handler) -> Conditional (test) -> CheckExc (expr) -> LoadExc
1.510 - (choices) -> LoadName TypeError
1.511 - (body) -> ReturnFromBlock (expr) -> y.__radd__(x)
1.512 - (else)
1.513 - """
1.514 -
1.515 - subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.516 - self.current_subprograms.append(subprogram)
1.517 -
1.518 - subprogram.code = [
1.519 - Try(binary, 1,
1.520 - body=[
1.521 - ReturnFromBlock(
1.522 - expr=InvokeFunction(
1.523 - expr=LoadAttr(expr=self.dispatch(binary.left), name=left_name),
1.524 - args=[self.dispatch(binary.right)],
1.525 - star=None,
1.526 - dstar=None)
1.527 - )
1.528 - ],
1.529 - else_=[],
1.530 - finally_=[],
1.531 - handler=[
1.532 - Conditional(
1.533 - test=CheckExc(expr=LoadExc(), choices=[LoadName(name="TypeError")]),
1.534 - body=[
1.535 - ReturnFromBlock(
1.536 - expr=InvokeFunction(
1.537 - expr=LoadAttr(expr=self.dispatch(binary.right), name=right_name),
1.538 - args=[self.dispatch(binary.left)],
1.539 - star=None,
1.540 - dstar=None)
1.541 - )
1.542 - ],
1.543 - else_=[]
1.544 - )
1.545 - ]
1.546 - )
1.547 - ]
1.548 -
1.549 - self.current_subprograms.pop()
1.550 - self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.551 -
1.552 - result = InvokeBlock(produces_result=1)
1.553 - result.expr = LoadRef(ref=subprogram)
1.554 + def visitAssList(self, asslist, in_sequence=0):
1.555 + if not in_sequence:
1.556 + expr = LoadTemp()
1.557 + else:
1.558 + expr = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), star=None, dstar=None, args=[])
1.559 + result = Assign(asslist, 1)
1.560 + store = StoreTemp(expr=InvokeFunction(expr=LoadAttr(name="__iter__", expr=expr), star=None, dstar=None, args=[]))
1.561 + release = ReleaseTemp()
1.562 + result.code = [store] + self.dispatches(asslist.nodes, 1) + [release]
1.563 return result
1.564
1.565 - def visitAdd(self, add):
1.566 - return self._visitBinary(add, "__add__", "__radd__")
1.567 -
1.568 - def visitDiv(self, div):
1.569 - return self._visitBinary(div, "__div__", "__rdiv__")
1.570 -
1.571 - def visitFloorDiv(self, floordiv):
1.572 - return self._visitBinary(floordiv, "__floordiv__", "__rfloordiv__")
1.573 -
1.574 - def visitMul(self, mul):
1.575 - return self._visitBinary(mul, "__mul__", "__rmul__")
1.576 -
1.577 - def visitSub(self, sub):
1.578 - return self._visitBinary(sub, "__sub__", "__rsub__")
1.579 + visitAssTuple = visitAssList
1.580
1.581 - def visitInvert(self, invert):
1.582 - return InvokeFunction(invert, 1,
1.583 - expr=LoadAttr(
1.584 - expr=self.dispatch(invert.expr),
1.585 - name="__invert__"
1.586 - ),
1.587 - args=[],
1.588 - star=None,
1.589 - dstar=None
1.590 - )
1.591 + def _visitAssNameOrAttr(self, node, in_sequence):
1.592 + if not in_sequence:
1.593 + return LoadTemp()
1.594 + else:
1.595 + return InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), star=None, dstar=None, args=[])
1.596
1.597 - def _visitUnary(self, unary, name):
1.598 - return InvokeFunction(unary, 1,
1.599 - expr=LoadAttr(
1.600 - expr=self.dispatch(unary.expr),
1.601 - name=name
1.602 - ),
1.603 - args=[],
1.604 - star=None,
1.605 - dstar=None
1.606 - )
1.607 -
1.608 - def visitUnaryAdd(self, unaryadd):
1.609 - return self._visitUnary(unaryadd, "__pos__")
1.610 -
1.611 - def visitUnarySub(self, unarysub):
1.612 - return self._visitUnary(unarysub, "__neg__")
1.613 -
1.614 - # Assignments.
1.615 + def visitAssName(self, assname, in_sequence=0):
1.616 + expr = self._visitAssNameOrAttr(assname, in_sequence)
1.617 + result = StoreName(assname, 1, name=assname.name, expr=expr)
1.618 + return result
1.619
1.620 augassign_methods = {
1.621 "+=" : "__iadd__", "-=" : "__isub__", "*=" : "__imul__", "/=" : "__idiv__",
1.622 @@ -934,142 +410,19 @@
1.623
1.624 return result
1.625
1.626 - def visitAssign(self, assign):
1.627 - result = Assign(assign, 1)
1.628 - store = StoreTemp(expr=self.dispatch(assign.expr))
1.629 - release = ReleaseTemp()
1.630 - result.code = [store] + self.dispatches(assign.nodes, 0) + [release]
1.631 - return result
1.632 -
1.633 - def visitAssList(self, asslist, in_sequence=0):
1.634 - if not in_sequence:
1.635 - expr = LoadTemp()
1.636 - else:
1.637 - expr = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), star=None, dstar=None, args=[])
1.638 - result = Assign(asslist, 1)
1.639 - store = StoreTemp(expr=InvokeFunction(expr=LoadAttr(name="__iter__", expr=expr), star=None, dstar=None, args=[]))
1.640 - release = ReleaseTemp()
1.641 - result.code = [store] + self.dispatches(asslist.nodes, 1) + [release]
1.642 - return result
1.643 -
1.644 - visitAssTuple = visitAssList
1.645 -
1.646 - def _visitAssNameOrAttr(self, node, in_sequence):
1.647 - if not in_sequence:
1.648 - return LoadTemp()
1.649 - else:
1.650 - return InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="next"), star=None, dstar=None, args=[])
1.651 -
1.652 - def visitAssName(self, assname, in_sequence=0):
1.653 - expr = self._visitAssNameOrAttr(assname, in_sequence)
1.654 - result = StoreName(assname, 1, name=assname.name, expr=expr)
1.655 - return result
1.656 -
1.657 - def visitAssAttr(self, assattr, in_sequence=0):
1.658 - expr = self._visitAssNameOrAttr(assattr, in_sequence)
1.659 - lvalue = self.dispatch(assattr.expr)
1.660 - result = StoreAttr(assattr, 1, name=assattr.attrname, lvalue=lvalue, expr=expr)
1.661 + def visitBreak(self, break_):
1.662 + result = ReturnFromBlock(break_, 1)
1.663 return result
1.664
1.665 - def _visitSlice(self, slice, expr, lower, upper, flags, value=None):
1.666 - if flags == "OP_ASSIGN":
1.667 - result = InvokeFunction(slice, 1,
1.668 - expr=LoadAttr(
1.669 - expr=expr,
1.670 - name="__setslice__"
1.671 - ),
1.672 - star=None,
1.673 - dstar=None,
1.674 - args=[lower, upper, value]
1.675 - )
1.676 - elif flags == "OP_APPLY":
1.677 - args = []
1.678 - result = InvokeFunction(slice, 1,
1.679 - expr=LoadAttr(
1.680 - expr=expr,
1.681 - name="__getslice__"
1.682 - ),
1.683 - star=None,
1.684 - dstar=None,
1.685 - args=[lower, upper]
1.686 - )
1.687 - elif flags == "OP_DELETE":
1.688 - args = []
1.689 - result = InvokeFunction(slice, 1,
1.690 - expr=LoadAttr(
1.691 - expr=expr,
1.692 - name="__delslice__"
1.693 - ),
1.694 - star=None,
1.695 - dstar=None,
1.696 - args=[lower, upper]
1.697 - )
1.698 - else:
1.699 - raise NotImplementedError, flags
1.700 -
1.701 + def visitCallFunc(self, callfunc):
1.702 + result = InvokeFunction(callfunc, 1, star=None, dstar=None, args=self.dispatches(callfunc.args))
1.703 + if callfunc.star_args is not None:
1.704 + result.star = self.dispatch(callfunc.star_args)
1.705 + if callfunc.dstar_args is not None:
1.706 + result.dstar = self.dispatch(callfunc.dstar_args)
1.707 + result.expr = self.dispatch(callfunc.node)
1.708 return result
1.709
1.710 - def visitSlice(self, slice, in_sequence=0):
1.711 - return self._visitSlice(slice, self.dispatch(slice.expr), self.dispatch_or_none(slice.lower),
1.712 - self.dispatch_or_none(slice.upper), slice.flags, self._visitAssNameOrAttr(slice, in_sequence))
1.713 -
1.714 - def _visitSubscript(self, subscript, expr, subs, flags, value=None):
1.715 - if flags == "OP_ASSIGN":
1.716 - result = InvokeFunction(subscript, 1,
1.717 - expr=LoadAttr(
1.718 - expr=expr,
1.719 - name="__setitem__"
1.720 - ),
1.721 - star=None,
1.722 - dstar=None,
1.723 - args=[subs, value]
1.724 - )
1.725 - elif flags == "OP_APPLY":
1.726 - args = []
1.727 - result = InvokeFunction(subscript, 1,
1.728 - expr=LoadAttr(
1.729 - expr=expr,
1.730 - name="__getitem__"
1.731 - ),
1.732 - star=None,
1.733 - dstar=None,
1.734 - args=[subs]
1.735 - )
1.736 - elif flags == "OP_DELETE":
1.737 - args = []
1.738 - result = InvokeFunction(subscript, 1,
1.739 - expr=LoadAttr(
1.740 - expr=expr,
1.741 - name="__delitem__"
1.742 - ),
1.743 - star=None,
1.744 - dstar=None,
1.745 - args=[subs]
1.746 - )
1.747 - else:
1.748 - raise NotImplementedError, flags
1.749 -
1.750 - return result
1.751 -
1.752 - def _visitSubscriptSubs(self, node, subs):
1.753 - if len(subs) == 1:
1.754 - return self.dispatch(subs[0])
1.755 - else:
1.756 - return InvokeFunction(node, 1,
1.757 - expr=LoadName(name="tuple"),
1.758 - args=self.dispatches(subs),
1.759 - star=None,
1.760 - dstar=None
1.761 - )
1.762 -
1.763 - def visitSubscript(self, subscript, in_sequence=0):
1.764 - return self._visitSubscript(
1.765 - subscript, self.dispatch(subscript.expr), self._visitSubscriptSubs(subscript, subscript.subs), subscript.flags,
1.766 - self._visitAssNameOrAttr(subscript, in_sequence)
1.767 - )
1.768 -
1.769 - # Invocation and subprogram transformations.
1.770 -
1.771 def visitClass(self, class_):
1.772
1.773 # Add "object" if the class is not "object" and has an empty bases list.
1.774 @@ -1112,165 +465,153 @@
1.775 )
1.776 return result
1.777
1.778 - def _visitFunction(self, function, subprogram):
1.779 + comparison_methods = {
1.780 + "==" : "__eq__", "!=" : "__ne__", "<" : "__lt__", "<=" : "__le__",
1.781 + ">=" : "__ge__", ">" : "__gt__", "is" : None, "is not" : None
1.782 + }
1.783 +
1.784 + def visitCompare(self, compare):
1.785
1.786 """
1.787 - A common function generator which transforms the given 'function' node
1.788 - and initialises the given 'subprogram' appropriately.
1.789 - """
1.790 -
1.791 - # Discover star and dstar parameters.
1.792 -
1.793 - if function.flags & 4 != 0:
1.794 - has_star = 1
1.795 - else:
1.796 - has_star = 0
1.797 - if function.flags & 8 != 0:
1.798 - has_dstar = 1
1.799 - else:
1.800 - has_dstar = 0
1.801 -
1.802 - # Discover the number of defaults and positional parameters.
1.803 -
1.804 - ndefaults = len(function.defaults)
1.805 - npositional = len(function.argnames) - has_star - has_dstar
1.806 -
1.807 - # Produce star and dstar parameters with appropriate defaults.
1.808 -
1.809 - if has_star:
1.810 - star = (
1.811 - function.argnames[npositional],
1.812 - InvokeFunction(expr=LoadName(name="list"), args=[], star=None, dstar=None)
1.813 - )
1.814 - else:
1.815 - star = None
1.816 - if has_dstar:
1.817 - dstar = (
1.818 - function.argnames[npositional + has_star],
1.819 - InvokeFunction(expr=LoadName(name="dict"), args=[], star=None, dstar=None)
1.820 - )
1.821 - else:
1.822 - dstar = None
1.823 -
1.824 - params = []
1.825 - for i in range(0, npositional - ndefaults):
1.826 - params.append((function.argnames[i], None))
1.827 -
1.828 - # Process defaults.
1.829 -
1.830 - for i in range(0, ndefaults):
1.831 - default = function.defaults[i]
1.832 - if default is not None:
1.833 - params.append((function.argnames[npositional - ndefaults + i], self.dispatch(default)))
1.834 - else:
1.835 - params.append((function.argnames[npositional - ndefaults + i], None))
1.836 -
1.837 - subprogram.params = params
1.838 - subprogram.star = star
1.839 - subprogram.dstar = dstar
1.840 - self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.841 + Make a subprogram for the 'compare' node and record its contents inside
1.842 + the subprogram. Convert...
1.843
1.844 - def visitFunction(self, function):
1.845 -
1.846 - """
1.847 - Make a subprogram for the 'function' and record it outside the main
1.848 - tree. Produce something like the following:
1.849 -
1.850 - StoreName (name)
1.851 - (expr) -> Subprogram (params)
1.852 - (star)
1.853 - (dstar)
1.854 - """
1.855 -
1.856 - subprogram = Subprogram(name=function.name, module=self.module, structures=self.current_structures[:],
1.857 - internal=0, returns_value=1, star=None, dstar=None)
1.858 -
1.859 - self.current_subprograms.append(subprogram)
1.860 - subprogram.code = self.dispatch(function.code) + [ReturnFromFunction()]
1.861 - self.current_subprograms.pop()
1.862 - self._visitFunction(function, subprogram)
1.863 -
1.864 - # Make a definition of the function associating it with a name.
1.865 -
1.866 - result = StoreName(function, 1, name=function.name, expr=LoadRef(ref=subprogram))
1.867 - return result
1.868 -
1.869 - def visitLambda(self, lambda_):
1.870 -
1.871 - # Make a subprogram for the function and record it outside the main
1.872 - # tree.
1.873 -
1.874 - subprogram = Subprogram(name=None, module=self.module, internal=0, returns_value=1, star=None, dstar=None)
1.875 - self.current_subprograms.append(subprogram)
1.876 - subprogram.code = [ReturnFromFunction(expr=self.dispatch(lambda_.code))]
1.877 - self.current_subprograms.pop()
1.878 - self._visitFunction(lambda_, subprogram)
1.879 -
1.880 - # Get the subprogram reference to the lambda.
1.881 -
1.882 - return LoadRef(lambda_, 1, ref=subprogram)
1.883 -
1.884 - def visitCallFunc(self, callfunc):
1.885 - result = InvokeFunction(callfunc, 1, star=None, dstar=None, args=self.dispatches(callfunc.args))
1.886 - if callfunc.star_args is not None:
1.887 - result.star = self.dispatch(callfunc.star_args)
1.888 - if callfunc.dstar_args is not None:
1.889 - result.dstar = self.dispatch(callfunc.dstar_args)
1.890 - result.expr = self.dispatch(callfunc.node)
1.891 - return result
1.892 -
1.893 - def visitWhile(self, while_):
1.894 -
1.895 - """
1.896 - Make a subprogram for the 'while' node and record its contents inside the
1.897 - subprogram. Convert...
1.898 -
1.899 - While (test) -> (body)
1.900 - (else)
1.901 + Compare (expr)
1.902 + (name/node)
1.903 + ...
1.904
1.905 ...to:
1.906
1.907 - Subprogram -> Conditional (test) -> (body) -> Invoke subprogram
1.908 - (else) -> Conditional (test) -> ReturnFromBlock ...
1.909 - (else) -> ...
1.910 + InvokeBlock -> Subprogram -> Conditional (test) -> (body)
1.911 + (else) -> Conditional (test) -> (body)
1.912 + (else) -> ...
1.913 """
1.914
1.915 - subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=0, params=[], star=None, dstar=None)
1.916 + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.917 self.current_subprograms.append(subprogram)
1.918
1.919 - # Include a conditional statement in the subprogram.
1.920 + # In the subprogram, make instructions which invoke a method on the
1.921 + # first operand of each operand pair and, if appropriate, return with
1.922 + # the value from that method.
1.923 +
1.924 + last = compare.ops[-1]
1.925 + previous = self.dispatch(compare.expr)
1.926 + results = nodes = []
1.927 +
1.928 + # For viewing purposes, record invocations on the AST node.
1.929 +
1.930 + compare._ops = []
1.931 +
1.932 + for op in compare.ops:
1.933 + op_name, node = op
1.934 + expr = self.dispatch(node)
1.935
1.936 - test = Conditional(else_=[])
1.937 - test.test = InvokeFunction(expr=LoadAttr(expr=self.dispatch(while_.test), name="__bool__"), args=[], star=None, dstar=None)
1.938 + # Identify the operation and produce the appropriate method call.
1.939
1.940 - # Inside the conditional, add a recursive invocation to the subprogram
1.941 - # if the test condition was satisfied.
1.942 + method_name = self.comparison_methods[op_name]
1.943 + if method_name:
1.944 + invocation = InvokeFunction(
1.945 + expr=LoadAttr(
1.946 + expr=previous,
1.947 + name=method_name),
1.948 + args=[expr],
1.949 + star=None,
1.950 + dstar=None)
1.951 +
1.952 + elif op_name == "is":
1.953 + invocation = InvokeFunction(
1.954 + expr=LoadName(name="__is__"),
1.955 + args=[previous, expr],
1.956 + star=None,
1.957 + dstar=None)
1.958
1.959 - continuation = InvokeBlock()
1.960 - continuation.expr = LoadRef(ref=subprogram)
1.961 + elif op_name == "is not":
1.962 + invocation = Not(
1.963 + expr=InvokeFunction(
1.964 + expr=LoadName(name="__is__"),
1.965 + args=[previous, expr],
1.966 + star=None,
1.967 + dstar=None)
1.968 + )
1.969 + else:
1.970 + raise NotImplementedError, op_name
1.971
1.972 - # Return within the main section of the loop.
1.973 + nodes.append(StoreTemp(expr=invocation))
1.974 + compare._ops.append(invocation)
1.975 +
1.976 + # Return from the subprogram where the test is not satisfied.
1.977
1.978 - test.body = self.dispatch(while_.body) + [continuation, ReturnFromBlock()]
1.979 + if op is not last:
1.980 + nodes.append(
1.981 + Conditional(
1.982 + test=self._visitNot(LoadTemp()),
1.983 + body=[
1.984 + ReturnFromBlock(expr=LoadTemp())
1.985 + ],
1.986 + else_=[
1.987 + ReleaseTemp()
1.988 + # Subsequent operations go here!
1.989 + ]
1.990 + )
1.991 + )
1.992
1.993 - # Provide the else section, if present, along with an explicit return.
1.994 + # Put subsequent operations in the else section of this conditional.
1.995 +
1.996 + nodes = nodes[-1].else_
1.997 +
1.998 + # For the last operation, return the result.
1.999
1.1000 - if while_.else_ is not None:
1.1001 - test.else_ = self.dispatch(while_.else_) + [ReturnFromBlock()]
1.1002 + else:
1.1003 + nodes.append(
1.1004 + ReturnFromBlock(expr=LoadTemp(release=1))
1.1005 + )
1.1006 +
1.1007 + previous = expr
1.1008
1.1009 # Finish the subprogram definition.
1.1010
1.1011 - subprogram.code = [test]
1.1012 + subprogram.code = results
1.1013
1.1014 self.current_subprograms.pop()
1.1015 self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.1016
1.1017 # Make an invocation of the subprogram.
1.1018
1.1019 - result = InvokeBlock(while_, 1)
1.1020 + result = InvokeBlock(compare, 1, produces_result=1)
1.1021 result.expr = LoadRef(ref=subprogram)
1.1022 return result
1.1023
1.1024 + def visitConst(self, const):
1.1025 + if not self.constants.has_key(const.value):
1.1026 + self.constants[const.value] = Constant(name=repr(const.value), value=const.value)
1.1027 + result = LoadRef(const, 1, ref=self.constants[const.value])
1.1028 + return result
1.1029 +
1.1030 + def visitContinue(self, continue_):
1.1031 + result = InvokeBlock(continue_, 1,
1.1032 + expr=LoadRef(ref=self.current_subprograms[-1])
1.1033 + )
1.1034 + return result
1.1035 +
1.1036 + def visitDict(self, dict):
1.1037 + result = InvokeFunction(dict, 1, expr=LoadName(name="dict"), star=None, dstar=None)
1.1038 + args = []
1.1039 + for key, value in dict.items:
1.1040 + tuple = InvokeFunction(expr=LoadName(name="tuple"), star=None, dstar=None)
1.1041 + tuple.set_args([self.dispatch(key), self.dispatch(value)])
1.1042 + args.append(tuple)
1.1043 + result.set_args(args)
1.1044 + return result
1.1045 +
1.1046 + def visitDiscard(self, discard):
1.1047 + return self.dispatch(discard.expr)
1.1048 +
1.1049 + def visitDiv(self, div):
1.1050 + return self._visitBinary(div, "__div__", "__rdiv__")
1.1051 +
1.1052 + def visitFloorDiv(self, floordiv):
1.1053 + return self._visitBinary(floordiv, "__floordiv__", "__rfloordiv__")
1.1054 +
1.1055 def visitFor(self, for_):
1.1056
1.1057 """
1.1058 @@ -1361,7 +702,518 @@
1.1059 ]
1.1060 return result
1.1061
1.1062 - # Exception node transformations.
1.1063 + def visitFrom(self, from_):
1.1064 + result = Assign(from_, 1)
1.1065 + code = []
1.1066 + code.append(StoreTemp(expr=Import(name=from_.modname)))
1.1067 + for name, alias in from_.names:
1.1068 + code.append(
1.1069 + StoreName(
1.1070 + expr=LoadAttr(
1.1071 + expr=LoadTemp(),
1.1072 + name=name),
1.1073 + name=(alias or name)
1.1074 + )
1.1075 + )
1.1076 + code.append(ReleaseTemp())
1.1077 + result.code = code
1.1078 + return result
1.1079 +
1.1080 + def _visitFunction(self, function, subprogram):
1.1081 +
1.1082 + """
1.1083 + A common function generator which transforms the given 'function' node
1.1084 + and initialises the given 'subprogram' appropriately.
1.1085 + """
1.1086 +
1.1087 + # Discover star and dstar parameters.
1.1088 +
1.1089 + if function.flags & 4 != 0:
1.1090 + has_star = 1
1.1091 + else:
1.1092 + has_star = 0
1.1093 + if function.flags & 8 != 0:
1.1094 + has_dstar = 1
1.1095 + else:
1.1096 + has_dstar = 0
1.1097 +
1.1098 + # Discover the number of defaults and positional parameters.
1.1099 +
1.1100 + ndefaults = len(function.defaults)
1.1101 + npositional = len(function.argnames) - has_star - has_dstar
1.1102 +
1.1103 + # Produce star and dstar parameters with appropriate defaults.
1.1104 +
1.1105 + if has_star:
1.1106 + star = (
1.1107 + function.argnames[npositional],
1.1108 + InvokeFunction(expr=LoadName(name="list"), args=[], star=None, dstar=None)
1.1109 + )
1.1110 + else:
1.1111 + star = None
1.1112 + if has_dstar:
1.1113 + dstar = (
1.1114 + function.argnames[npositional + has_star],
1.1115 + InvokeFunction(expr=LoadName(name="dict"), args=[], star=None, dstar=None)
1.1116 + )
1.1117 + else:
1.1118 + dstar = None
1.1119 +
1.1120 + params = []
1.1121 + for i in range(0, npositional - ndefaults):
1.1122 + params.append((function.argnames[i], None))
1.1123 +
1.1124 + # Process defaults.
1.1125 +
1.1126 + for i in range(0, ndefaults):
1.1127 + default = function.defaults[i]
1.1128 + if default is not None:
1.1129 + params.append((function.argnames[npositional - ndefaults + i], self.dispatch(default)))
1.1130 + else:
1.1131 + params.append((function.argnames[npositional - ndefaults + i], None))
1.1132 +
1.1133 + subprogram.params = params
1.1134 + subprogram.star = star
1.1135 + subprogram.dstar = dstar
1.1136 + self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.1137 +
1.1138 + def visitFunction(self, function):
1.1139 +
1.1140 + """
1.1141 + Make a subprogram for the 'function' and record it outside the main
1.1142 + tree. Produce something like the following:
1.1143 +
1.1144 + StoreName (name)
1.1145 + (expr) -> Subprogram (params)
1.1146 + (star)
1.1147 + (dstar)
1.1148 + """
1.1149 +
1.1150 + subprogram = Subprogram(name=function.name, module=self.module, structures=self.current_structures[:],
1.1151 + internal=0, returns_value=1, star=None, dstar=None)
1.1152 +
1.1153 + self.current_subprograms.append(subprogram)
1.1154 + subprogram.code = self.dispatch(function.code) + [ReturnFromFunction()]
1.1155 + self.current_subprograms.pop()
1.1156 + self._visitFunction(function, subprogram)
1.1157 +
1.1158 + # Make a definition of the function associating it with a name.
1.1159 +
1.1160 + result = StoreName(function, 1, name=function.name, expr=LoadRef(ref=subprogram))
1.1161 + return result
1.1162 +
1.1163 + def visitGetattr(self, getattr):
1.1164 + result = LoadAttr(getattr, 1,
1.1165 + name=getattr.attrname,
1.1166 + expr=self.dispatch(getattr.expr)
1.1167 + )
1.1168 + return result
1.1169 +
1.1170 + def visitGlobal(self, global_):
1.1171 + result = Global(global_, 1,
1.1172 + names=global_.names
1.1173 + )
1.1174 + return result
1.1175 +
1.1176 + def visitIf(self, if_):
1.1177 +
1.1178 + """
1.1179 + Make conditionals for each test from an 'if_' AST node, adding the body
1.1180 + and putting each subsequent test as part of the conditional's else
1.1181 + section.
1.1182 +
1.1183 + Convert...
1.1184 +
1.1185 + If (test/body)
1.1186 + (test/body)
1.1187 + ...
1.1188 + (else/body)
1.1189 +
1.1190 + ...to:
1.1191 +
1.1192 + Conditional (test) -> (body)
1.1193 + (else) -> Conditional (test) -> (body)
1.1194 + (else) -> ...
1.1195 + """
1.1196 +
1.1197 +
1.1198 + results = nodes = []
1.1199 +
1.1200 + # Produce something like...
1.1201 + # expr.__bool__() ? body
1.1202 +
1.1203 + first = 1
1.1204 + for compare, stmt in if_.tests:
1.1205 +
1.1206 + # Set the first as the defining node.
1.1207 +
1.1208 + test = Conditional(if_, first,
1.1209 + test=InvokeFunction(
1.1210 + expr=LoadAttr(
1.1211 + expr=self.dispatch(compare),
1.1212 + name="__bool__"
1.1213 + ),
1.1214 + args=[],
1.1215 + star=None,
1.1216 + dstar=None)
1.1217 + )
1.1218 + test.body = self.dispatch(stmt)
1.1219 + nodes.append(test)
1.1220 + nodes = test.else_ = []
1.1221 + first = 0
1.1222 +
1.1223 + # Add the compound statement from any else clause to the end.
1.1224 +
1.1225 + if if_.else_ is not None:
1.1226 + nodes += self.dispatch(if_.else_)
1.1227 +
1.1228 + result = results[0]
1.1229 + return result
1.1230 +
1.1231 + def visitImport(self, import_):
1.1232 + result = Assign(import_, 1)
1.1233 + code = []
1.1234 + for path, alias in import_.names:
1.1235 + importer = Import(name=path)
1.1236 + top = alias or path.split(".")[0]
1.1237 + code.append(StoreName(expr=importer, name=top))
1.1238 + result.code = code
1.1239 + return result
1.1240 +
1.1241 + def visitInvert(self, invert):
1.1242 + return self._visitUnary(invert, "__invert__")
1.1243 +
1.1244 + def visitKeyword(self, keyword):
1.1245 + result = Keyword(keyword, 1,
1.1246 + name=keyword.name,
1.1247 + expr=self.dispatch(keyword.expr)
1.1248 + )
1.1249 + return result
1.1250 +
1.1251 + def visitLambda(self, lambda_):
1.1252 +
1.1253 + # Make a subprogram for the function and record it outside the main
1.1254 + # tree.
1.1255 +
1.1256 + subprogram = Subprogram(name=None, module=self.module, internal=0, returns_value=1, star=None, dstar=None)
1.1257 + self.current_subprograms.append(subprogram)
1.1258 + subprogram.code = [ReturnFromFunction(expr=self.dispatch(lambda_.code))]
1.1259 + self.current_subprograms.pop()
1.1260 + self._visitFunction(lambda_, subprogram)
1.1261 +
1.1262 + # Get the subprogram reference to the lambda.
1.1263 +
1.1264 + return LoadRef(lambda_, 1, ref=subprogram)
1.1265 +
1.1266 + def visitList(self, list):
1.1267 + return self._visitBuiltin(list, "list")
1.1268 +
1.1269 + def visitMul(self, mul):
1.1270 + return self._visitBinary(mul, "__mul__", "__rmul__")
1.1271 +
1.1272 + def visitName(self, name):
1.1273 + result = LoadName(name, 1, name=name.name)
1.1274 + return result
1.1275 +
1.1276 + def _visitNot(self, expr, not_=None):
1.1277 + invocation = InvokeFunction(
1.1278 + expr=LoadAttr(
1.1279 + expr=expr,
1.1280 + name="__bool__"
1.1281 + ),
1.1282 + args=[],
1.1283 + star=None,
1.1284 + dstar=None
1.1285 + )
1.1286 + if not_ is not None:
1.1287 + result = Not(not_, 1, expr=invocation)
1.1288 + else:
1.1289 + result = Not(expr=invocation)
1.1290 + return result
1.1291 +
1.1292 + def visitNot(self, not_):
1.1293 + return self._visitNot(self.dispatch(not_.expr), not_)
1.1294 +
1.1295 + def visitOr(self, or_):
1.1296 +
1.1297 + """
1.1298 + Make a subprogram for the 'or_' node and record its contents inside the
1.1299 + subprogram. Convert...
1.1300 +
1.1301 + Or (test)
1.1302 + (test)
1.1303 + ...
1.1304 +
1.1305 + ...to:
1.1306 +
1.1307 + Subprogram -> Conditional (test) -> ReturnFromBlock ...
1.1308 + (else) -> Conditional (test) -> ReturnFromBlock ...
1.1309 + (else) -> ...
1.1310 + """
1.1311 +
1.1312 + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.1313 + self.current_subprograms.append(subprogram)
1.1314 +
1.1315 + # In the subprogram, make instructions which store each operand, test
1.1316 + # for each operand's truth status, and if appropriate return from the
1.1317 + # subprogram with the value of the operand.
1.1318 +
1.1319 + last = or_.nodes[-1]
1.1320 + results = nodes = []
1.1321 +
1.1322 + for node in or_.nodes:
1.1323 + expr = self.dispatch(node)
1.1324 +
1.1325 + # Return from the subprogram where the test is satisfied.
1.1326 +
1.1327 + if node is not last:
1.1328 + nodes.append(StoreTemp(expr=expr))
1.1329 + invocation = InvokeFunction(expr=LoadAttr(expr=LoadTemp(), name="__bool__"), args=[], star=None, dstar=None)
1.1330 + test = Conditional(test=invocation, body=[ReturnFromBlock(expr=LoadTemp())])
1.1331 + nodes.append(test)
1.1332 +
1.1333 + # Put subsequent operations in the else section of this conditional.
1.1334 +
1.1335 + nodes = test.else_ = [ReleaseTemp()]
1.1336 +
1.1337 + # For the last operation, return the result.
1.1338 +
1.1339 + else:
1.1340 + nodes.append(
1.1341 + ReturnFromBlock(expr=expr)
1.1342 + )
1.1343 +
1.1344 + # Finish the subprogram definition.
1.1345 +
1.1346 + subprogram.code = results
1.1347 +
1.1348 + self.current_subprograms.pop()
1.1349 + self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.1350 +
1.1351 + # Make an invocation of the subprogram.
1.1352 +
1.1353 + result = InvokeBlock(or_, 1, produces_result=1)
1.1354 + result.expr = LoadRef(ref=subprogram)
1.1355 + return result
1.1356 +
1.1357 + def visitPass(self, pass_):
1.1358 + return Pass(pass_, 1)
1.1359 +
1.1360 + def visitRaise(self, raise_):
1.1361 + result = Raise(raise_, 1)
1.1362 + if raise_.expr2 is None:
1.1363 + result.expr = self.dispatch(raise_.expr1)
1.1364 + else:
1.1365 + result.expr = InvokeFunction(
1.1366 + expr=self.dispatch(raise_.expr1),
1.1367 + args=[self.dispatch(raise_.expr2)],
1.1368 + star=None,
1.1369 + dstar=None
1.1370 + )
1.1371 + if raise_.expr3 is not None:
1.1372 + result.traceback = self.dispatch(raise_.expr3)
1.1373 + else:
1.1374 + result.traceback = None
1.1375 + return result
1.1376 +
1.1377 + def visitReturn(self, return_):
1.1378 + result = ReturnFromFunction(return_, 1,
1.1379 + expr=self.dispatch(return_.value)
1.1380 + )
1.1381 + return result
1.1382 +
1.1383 + def _visitSlice(self, slice, expr, lower, upper, flags, value=None):
1.1384 + if flags == "OP_ASSIGN":
1.1385 + result = InvokeFunction(slice, 1,
1.1386 + expr=LoadAttr(
1.1387 + expr=expr,
1.1388 + name="__setslice__"
1.1389 + ),
1.1390 + star=None,
1.1391 + dstar=None,
1.1392 + args=[lower, upper, value]
1.1393 + )
1.1394 + elif flags == "OP_APPLY":
1.1395 + args = []
1.1396 + result = InvokeFunction(slice, 1,
1.1397 + expr=LoadAttr(
1.1398 + expr=expr,
1.1399 + name="__getslice__"
1.1400 + ),
1.1401 + star=None,
1.1402 + dstar=None,
1.1403 + args=[lower, upper]
1.1404 + )
1.1405 + elif flags == "OP_DELETE":
1.1406 + args = []
1.1407 + result = InvokeFunction(slice, 1,
1.1408 + expr=LoadAttr(
1.1409 + expr=expr,
1.1410 + name="__delslice__"
1.1411 + ),
1.1412 + star=None,
1.1413 + dstar=None,
1.1414 + args=[lower, upper]
1.1415 + )
1.1416 + else:
1.1417 + raise NotImplementedError, flags
1.1418 +
1.1419 + return result
1.1420 +
1.1421 + def visitSlice(self, slice, in_sequence=0):
1.1422 + return self._visitSlice(slice, self.dispatch(slice.expr), self.dispatch_or_none(slice.lower),
1.1423 + self.dispatch_or_none(slice.upper), slice.flags, self._visitAssNameOrAttr(slice, in_sequence))
1.1424 +
1.1425 + def visitStmt(self, stmt):
1.1426 + return self.dispatches(stmt.nodes)
1.1427 +
1.1428 + def visitSub(self, sub):
1.1429 + return self._visitBinary(sub, "__sub__", "__rsub__")
1.1430 +
1.1431 + def _visitSubscript(self, subscript, expr, subs, flags, value=None):
1.1432 + if flags == "OP_ASSIGN":
1.1433 + result = InvokeFunction(subscript, 1,
1.1434 + expr=LoadAttr(
1.1435 + expr=expr,
1.1436 + name="__setitem__"
1.1437 + ),
1.1438 + star=None,
1.1439 + dstar=None,
1.1440 + args=[subs, value]
1.1441 + )
1.1442 + elif flags == "OP_APPLY":
1.1443 + args = []
1.1444 + result = InvokeFunction(subscript, 1,
1.1445 + expr=LoadAttr(
1.1446 + expr=expr,
1.1447 + name="__getitem__"
1.1448 + ),
1.1449 + star=None,
1.1450 + dstar=None,
1.1451 + args=[subs]
1.1452 + )
1.1453 + elif flags == "OP_DELETE":
1.1454 + args = []
1.1455 + result = InvokeFunction(subscript, 1,
1.1456 + expr=LoadAttr(
1.1457 + expr=expr,
1.1458 + name="__delitem__"
1.1459 + ),
1.1460 + star=None,
1.1461 + dstar=None,
1.1462 + args=[subs]
1.1463 + )
1.1464 + else:
1.1465 + raise NotImplementedError, flags
1.1466 +
1.1467 + return result
1.1468 +
1.1469 + def _visitSubscriptSubs(self, node, subs):
1.1470 + if len(subs) == 1:
1.1471 + return self.dispatch(subs[0])
1.1472 + else:
1.1473 + return InvokeFunction(node, 1,
1.1474 + expr=LoadName(name="tuple"),
1.1475 + args=self.dispatches(subs),
1.1476 + star=None,
1.1477 + dstar=None
1.1478 + )
1.1479 +
1.1480 + def visitSubscript(self, subscript, in_sequence=0):
1.1481 + return self._visitSubscript(
1.1482 + subscript, self.dispatch(subscript.expr), self._visitSubscriptSubs(subscript, subscript.subs), subscript.flags,
1.1483 + self._visitAssNameOrAttr(subscript, in_sequence)
1.1484 + )
1.1485 +
1.1486 + def visitTryExcept(self, tryexcept):
1.1487 +
1.1488 + """
1.1489 + Make conditionals for each handler associated with a 'tryexcept' node.
1.1490 +
1.1491 + Convert...
1.1492 +
1.1493 + TryExcept (body)
1.1494 + (else)
1.1495 + (spec/assign/stmt)
1.1496 + ...
1.1497 +
1.1498 + ...to:
1.1499 +
1.1500 + Try (body)
1.1501 + (else)
1.1502 + (handler) -> Conditional (test) -> (stmt)
1.1503 + (body) -> ...
1.1504 + (else) -> Conditional (test) -> (stmt)
1.1505 + (body) -> ...
1.1506 + (else) -> ...
1.1507 + """
1.1508 +
1.1509 + result = Try(tryexcept, 1, body=[], else_=[], finally_=[])
1.1510 +
1.1511 + if tryexcept.body is not None:
1.1512 + result.body = self.dispatch(tryexcept.body)
1.1513 + if tryexcept.else_ is not None:
1.1514 + result.else_ = self.dispatch(tryexcept.else_)
1.1515 +
1.1516 + results = nodes = []
1.1517 + catch_all = 0
1.1518 +
1.1519 + for spec, assign, stmt in tryexcept.handlers:
1.1520 +
1.1521 + # If no specification exists, produce an unconditional block.
1.1522 +
1.1523 + if spec is None:
1.1524 + nodes += self.dispatch(stmt)
1.1525 + catch_all = 1
1.1526 +
1.1527 + # Produce an exception value check.
1.1528 +
1.1529 + else:
1.1530 + test = Conditional(
1.1531 + isolate_test=1,
1.1532 + test=CheckExc(expr=LoadExc(), choices=self._visitTryExcept(spec))
1.1533 + )
1.1534 + test.body = []
1.1535 +
1.1536 + if assign is not None:
1.1537 + test.body.append(
1.1538 + Assign(
1.1539 + code=[
1.1540 + StoreTemp(expr=LoadExc()),
1.1541 + self.dispatch(assign),
1.1542 + ReleaseTemp()
1.1543 + ]
1.1544 + )
1.1545 + )
1.1546 +
1.1547 + # Always return from conditional sections.
1.1548 +
1.1549 + test.body += self.dispatch(stmt) + [ReturnFromBlock()]
1.1550 + nodes.append(test)
1.1551 + nodes = test.else_ = []
1.1552 +
1.1553 + # Add a raise operation to deal with unhandled exceptions.
1.1554 +
1.1555 + if not catch_all:
1.1556 + nodes.append(
1.1557 + Raise(
1.1558 + expr=LoadExc())
1.1559 + )
1.1560 +
1.1561 + result.handler = results
1.1562 + return result
1.1563 +
1.1564 + def _visitTryExcept(self, spec):
1.1565 +
1.1566 + "Return a list of nodes for the given exception type 'spec'."
1.1567 +
1.1568 + if isinstance(spec, compiler.ast.Tuple):
1.1569 + nodes = []
1.1570 + for node in spec.nodes:
1.1571 + nodes += self._visitTryExcept(node)
1.1572 + else:
1.1573 + nodes = [self.dispatch(spec)]
1.1574 + return nodes
1.1575
1.1576 def visitTryFinally(self, tryfinally):
1.1577 result = Try(tryfinally, 1, body=[], else_=[], finally_=[])
1.1578 @@ -1371,6 +1223,138 @@
1.1579 result.finally_ = self.dispatch(tryfinally.final)
1.1580 return result
1.1581
1.1582 + def visitTuple(self, tuple):
1.1583 + return self._visitBuiltin(tuple, "tuple")
1.1584 +
1.1585 + def visitUnaryAdd(self, unaryadd):
1.1586 + return self._visitUnary(unaryadd, "__pos__")
1.1587 +
1.1588 + def visitUnarySub(self, unarysub):
1.1589 + return self._visitUnary(unarysub, "__neg__")
1.1590 +
1.1591 + def visitWhile(self, while_):
1.1592 +
1.1593 + """
1.1594 + Make a subprogram for the 'while' node and record its contents inside the
1.1595 + subprogram. Convert...
1.1596 +
1.1597 + While (test) -> (body)
1.1598 + (else)
1.1599 +
1.1600 + ...to:
1.1601 +
1.1602 + Subprogram -> Conditional (test) -> (body) -> Invoke subprogram
1.1603 + (else) -> Conditional (test) -> ReturnFromBlock ...
1.1604 + (else) -> ...
1.1605 + """
1.1606 +
1.1607 + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=0, params=[], star=None, dstar=None)
1.1608 + self.current_subprograms.append(subprogram)
1.1609 +
1.1610 + # Include a conditional statement in the subprogram.
1.1611 +
1.1612 + test = Conditional(else_=[])
1.1613 + test.test = InvokeFunction(expr=LoadAttr(expr=self.dispatch(while_.test), name="__bool__"), args=[], star=None, dstar=None)
1.1614 +
1.1615 + # Inside the conditional, add a recursive invocation to the subprogram
1.1616 + # if the test condition was satisfied.
1.1617 +
1.1618 + continuation = InvokeBlock()
1.1619 + continuation.expr = LoadRef(ref=subprogram)
1.1620 +
1.1621 + # Return within the main section of the loop.
1.1622 +
1.1623 + test.body = self.dispatch(while_.body) + [continuation, ReturnFromBlock()]
1.1624 +
1.1625 + # Provide the else section, if present, along with an explicit return.
1.1626 +
1.1627 + if while_.else_ is not None:
1.1628 + test.else_ = self.dispatch(while_.else_) + [ReturnFromBlock()]
1.1629 +
1.1630 + # Finish the subprogram definition.
1.1631 +
1.1632 + subprogram.code = [test]
1.1633 +
1.1634 + self.current_subprograms.pop()
1.1635 + self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.1636 +
1.1637 + # Make an invocation of the subprogram.
1.1638 +
1.1639 + result = InvokeBlock(while_, 1)
1.1640 + result.expr = LoadRef(ref=subprogram)
1.1641 + return result
1.1642 +
1.1643 + # Convenience methods.
1.1644 +
1.1645 + def _visitBinary(self, binary, left_name, right_name):
1.1646 +
1.1647 + """
1.1648 + Emulate the current mechanisms by producing nodes as follows:
1.1649 +
1.1650 + InvokeBlock -> Subprogram -> Try (body) -> ReturnFromBlock (expr) -> x.__add__(y)
1.1651 + (else)
1.1652 + (handler) -> Conditional (test) -> CheckExc (expr) -> LoadExc
1.1653 + (choices) -> LoadName TypeError
1.1654 + (body) -> ReturnFromBlock (expr) -> y.__radd__(x)
1.1655 + (else)
1.1656 + """
1.1657 +
1.1658 + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=1, params=[], star=None, dstar=None)
1.1659 + self.current_subprograms.append(subprogram)
1.1660 +
1.1661 + subprogram.code = [
1.1662 + Try(binary, 1,
1.1663 + body=[
1.1664 + ReturnFromBlock(
1.1665 + expr=InvokeFunction(
1.1666 + expr=LoadAttr(expr=self.dispatch(binary.left), name=left_name),
1.1667 + args=[self.dispatch(binary.right)],
1.1668 + star=None,
1.1669 + dstar=None)
1.1670 + )
1.1671 + ],
1.1672 + else_=[],
1.1673 + finally_=[],
1.1674 + handler=[
1.1675 + Conditional(
1.1676 + test=CheckExc(expr=LoadExc(), choices=[LoadName(name="TypeError")]),
1.1677 + body=[
1.1678 + ReturnFromBlock(
1.1679 + expr=InvokeFunction(
1.1680 + expr=LoadAttr(expr=self.dispatch(binary.right), name=right_name),
1.1681 + args=[self.dispatch(binary.left)],
1.1682 + star=None,
1.1683 + dstar=None)
1.1684 + )
1.1685 + ],
1.1686 + else_=[]
1.1687 + )
1.1688 + ]
1.1689 + )
1.1690 + ]
1.1691 +
1.1692 + self.current_subprograms.pop()
1.1693 + self.subprograms.append(subprogram); self.subnames[subprogram.full_name()] = subprogram
1.1694 +
1.1695 + result = InvokeBlock(produces_result=1)
1.1696 + result.expr = LoadRef(ref=subprogram)
1.1697 + return result
1.1698 +
1.1699 + def _visitBuiltin(self, builtin, name):
1.1700 + result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes), star=None, dstar=None)
1.1701 + return result
1.1702 +
1.1703 + def _visitUnary(self, unary, name):
1.1704 + return InvokeFunction(unary, 1,
1.1705 + expr=LoadAttr(
1.1706 + expr=self.dispatch(unary.expr),
1.1707 + name=name
1.1708 + ),
1.1709 + args=[],
1.1710 + star=None,
1.1711 + dstar=None
1.1712 + )
1.1713 +
1.1714 # Convenience functions.
1.1715
1.1716 def simplify(filename, builtins=0):