1.1 --- a/micropython/ast.py Fri Jun 28 21:17:02 2013 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,941 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -Translate the AST of a Python program into a more interpretable representation.
1.8 -
1.9 -Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Paul Boddie <paul@boddie.org.uk>
1.10 -
1.11 -This program is free software; you can redistribute it and/or modify it under
1.12 -the terms of the GNU General Public License as published by the Free Software
1.13 -Foundation; either version 3 of the License, or (at your option) any later
1.14 -version.
1.15 -
1.16 -This program is distributed in the hope that it will be useful, but WITHOUT
1.17 -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 -details.
1.20 -
1.21 -You should have received a copy of the GNU General Public License along with
1.22 -this program. If not, see <http://www.gnu.org/licenses/>.
1.23 -"""
1.24 -
1.25 -from micropython.common import *
1.26 -from micropython.data import *
1.27 -from micropython.errors import *
1.28 -from micropython.rsvp import *
1.29 -from micropython.trans import Helper
1.30 -from micropython.code import Assembler
1.31 -import compiler.ast
1.32 -
1.33 -# Program visitors.
1.34 -
1.35 -class Translation(ASTVisitor, Assembler, Helper):
1.36 -
1.37 - "A module translator."
1.38 -
1.39 - # Attribute access instructions, for use with the appropriate handlers.
1.40 -
1.41 - attribute_load_instructions = (
1.42 - LoadAddress, LoadAddressContext, LoadAddressContextCond,
1.43 - LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond
1.44 - )
1.45 - # attribute_store_instructions are defined by the optimiser
1.46 -
1.47 - # Name access instructions, for use with the appropriate handlers.
1.48 -
1.49 - name_load_instructions = (LoadName, LoadAddress, None)
1.50 - name_store_instructions = (StoreName, StoreAddress, StoreAddressContext)
1.51 -
1.52 - def __init__(self, module, program):
1.53 -
1.54 - """
1.55 - Initialise the translation with an inspected 'module' and the 'program'
1.56 - container.
1.57 - """
1.58 -
1.59 - Assembler.__init__(self, program)
1.60 - self.visitor = self
1.61 - self.module = module
1.62 -
1.63 - # Global program dependencies.
1.64 -
1.65 - self.native = program.native
1.66 - self.objtable = self.program.get_object_table()
1.67 - self.paramtable = self.program.get_parameter_table()
1.68 - self.importer = self.program.get_importer()
1.69 - self.builtins = self.importer.modules.get("__builtins__")
1.70 -
1.71 - # Status flags.
1.72 -
1.73 - self.in_exception_handler = False
1.74 - self.in_assignment = False # for slicing and subscript
1.75 -
1.76 - # Reset the assembler.
1.77 -
1.78 - self.reset()
1.79 -
1.80 - def __repr__(self):
1.81 - return "Translation(%r)" % self.module
1.82 -
1.83 - def get_unit(self):
1.84 - return self.unit
1.85 -
1.86 - def get_module_code(self):
1.87 -
1.88 - """
1.89 - Return the top-level module code.
1.90 - """
1.91 -
1.92 - self.unit = self.module
1.93 - self.reset()
1.94 - self.add_exception_unit()
1.95 -
1.96 - block = self.new_block()
1.97 - self.set_block(block)
1.98 -
1.99 - # Handle exceptions for the program.
1.100 -
1.101 - if self.module.name == "__main__":
1.102 - handler_block = self.new_block()
1.103 - self.new_op(PushHandler(handler_block))
1.104 -
1.105 - # Generate code for the module.
1.106 -
1.107 - if self.module.astnode is not None:
1.108 - self.dispatch(self.module.astnode)
1.109 -
1.110 - # Finish off the translated program if appropriate.
1.111 -
1.112 - if self.module.name == "__main__":
1.113 - self.set_block(handler_block)
1.114 - self.new_op(PopHandler(1))
1.115 -
1.116 - # All modules return if invoked.
1.117 -
1.118 - self.new_op(Return())
1.119 -
1.120 - self.drop_exception_unit()
1.121 - self.unit.temp_usage = self.max_temp_position + 1
1.122 - self.unit.blocks = self.blocks
1.123 - return self.blocks
1.124 -
1.125 - def get_code(self, unit):
1.126 -
1.127 - "Return the code for the given 'unit'."
1.128 -
1.129 - self.unit = unit
1.130 - self.reset()
1.131 - self.add_exception_unit()
1.132 -
1.133 - block = self.new_block()
1.134 - self.set_block(block)
1.135 -
1.136 - if unit.astnode is not None:
1.137 - self.dispatch(unit.astnode)
1.138 -
1.139 - self.drop_exception_unit()
1.140 - self.unit.temp_usage = self.max_temp_position + 2 # include space for instantiators to expand backwards
1.141 - self.unit.blocks = self.blocks
1.142 - return self.blocks
1.143 -
1.144 - def get_instantiator_code(self, cls):
1.145 -
1.146 - "Return the code for the given class 'cls'."
1.147 -
1.148 - # Obtain the function object to be populated.
1.149 -
1.150 - self.unit = cls.get_instantiator()
1.151 - self.reset()
1.152 -
1.153 - block = self.new_block()
1.154 - self.set_block(block)
1.155 -
1.156 - init_method = cls.get_init_method()
1.157 -
1.158 - # Make an object and store it in the unused first slot.
1.159 -
1.160 - self.make_instance(cls, len(cls.instance_attributes()))
1.161 - self.new_op(StoreTemp(0))
1.162 -
1.163 - # Invoke the appropriate initialiser.
1.164 -
1.165 - self.new_op(LoadFunction(init_method))
1.166 - self.new_op(LoadCallable())
1.167 - self.new_op(JumpInFrame())
1.168 -
1.169 - # Store the object as the result.
1.170 -
1.171 - self.new_op(LoadTemp(0)) # load the context from the locals
1.172 - self.new_op(Return())
1.173 -
1.174 - self.unit.blocks = self.blocks
1.175 - return self.blocks
1.176 -
1.177 - # Visitor methods.
1.178 -
1.179 - def default(self, node, *args):
1.180 - raise TranslateError("Node class %r is not supported." % node.__class__)
1.181 -
1.182 - # Concrete visitor methods.
1.183 -
1.184 - # Binary operators.
1.185 -
1.186 - visitBitand = \
1.187 - visitBitor = \
1.188 - visitBitxor = Helper._visitBinaryBit
1.189 -
1.190 - visitAdd = \
1.191 - visitDiv = \
1.192 - visitFloorDiv = \
1.193 - visitLeftShift = \
1.194 - visitMod = \
1.195 - visitMul = \
1.196 - visitPower = \
1.197 - visitRightShift = \
1.198 - visitSub = Helper._visitBinary
1.199 -
1.200 - # Unary operators.
1.201 -
1.202 - visitInvert = \
1.203 - visitUnaryAdd = \
1.204 - visitUnarySub = Helper._visitUnary
1.205 -
1.206 - # Logical operators.
1.207 -
1.208 - def visitAnd(self, node):
1.209 - end_block = self.new_block()
1.210 - temp_pos = self.reserve_temp()
1.211 -
1.212 - for n in node.nodes[:-1]:
1.213 - self.dispatch(n)
1.214 - self.new_op(StoreTemp(temp_pos))
1.215 -
1.216 - self._generateTestBoolean(n, LoadTemp(temp_pos))
1.217 - self.new_op(JumpIfFalse(end_block, working="status"))
1.218 -
1.219 - self.dispatch(node.nodes[-1])
1.220 - self.new_op(StoreTemp(temp_pos))
1.221 -
1.222 - self.set_block(end_block)
1.223 -
1.224 - temp = LoadTemp(temp_pos)
1.225 - self.new_op(temp)
1.226 - self.discard_temp(temp)
1.227 -
1.228 - def visitNot(self, node):
1.229 - self.dispatch(node.expr)
1.230 -
1.231 - temp = self.optimiser.optimise_temp_storage()
1.232 - self.new_op(temp)
1.233 - self._generateTestBoolean(node.expr, temp)
1.234 - self.discard_temp(temp)
1.235 -
1.236 - self.new_op(InvertBoolean(source="status", target="status"))
1.237 - self._generateLoadBoolean(node)
1.238 -
1.239 - def visitOr(self, node):
1.240 - end_block = self.new_block()
1.241 - temp_pos = self.reserve_temp()
1.242 -
1.243 - for n in node.nodes[:-1]:
1.244 - self.dispatch(n)
1.245 - self.new_op(StoreTemp(temp_pos))
1.246 -
1.247 - self._generateTestBoolean(n, LoadTemp(temp_pos))
1.248 - self.new_op(JumpIfTrue(end_block, working="status"))
1.249 -
1.250 - self.dispatch(node.nodes[-1])
1.251 - self.new_op(StoreTemp(temp_pos))
1.252 -
1.253 - self.set_block(end_block)
1.254 -
1.255 - temp = LoadTemp(temp_pos)
1.256 - self.new_op(temp)
1.257 - self.discard_temp(temp)
1.258 -
1.259 - # Comparisons.
1.260 -
1.261 - def visitCompare(self, node):
1.262 -
1.263 - """
1.264 - _t1 = node.expr
1.265 - _t1 op1 _t2 and _t2 op2 _t3 and ...
1.266 - """
1.267 -
1.268 - end_block = self.new_block()
1.269 -
1.270 - self.dispatch(node.expr)
1.271 - temp2 = self.optimiser.optimise_temp_storage()
1.272 -
1.273 - # NOTE: Replicated by some code in micropython.inspect.visitCompare.
1.274 -
1.275 - last_op = node.ops[-1]
1.276 -
1.277 - for op in node.ops:
1.278 - op_name, next_node = op
1.279 - operator_fn = operator_functions.get(op_name)
1.280 -
1.281 - # Propagate the arguments as we traverse the construct.
1.282 -
1.283 - temp1 = temp2
1.284 - self.dispatch(next_node)
1.285 - temp2 = self.optimiser.optimise_temp_storage()
1.286 -
1.287 - # Use the appropriate mechanism, setting the boolean status for the
1.288 - # comparison.
1.289 -
1.290 - if operator_fn is not None:
1.291 -
1.292 - # Generate function call using evaluated argument and next node.
1.293 -
1.294 - temp_fn = self._generateOperatorFunction(op_name)
1.295 - self._generateInvocation(temp_fn, (temp1, temp2))
1.296 - self.discard_temp(temp_fn)
1.297 -
1.298 - temp_result = self.optimiser.optimise_temp_storage()
1.299 - self._generateTestBoolean(node, temp_result)
1.300 - self.discard_temp(temp_result)
1.301 -
1.302 - else:
1.303 - # Deal with the special operators.
1.304 -
1.305 - if op_name.startswith("is"):
1.306 - self.new_op(temp1)
1.307 - self.record_value()
1.308 - self.start_target()
1.309 - self.new_op(temp2)
1.310 - self.new_op(TestIdentity(target="status"))
1.311 - self.assign_value()
1.312 - self.discard_value()
1.313 -
1.314 - elif op_name.endswith("in"):
1.315 - self.new_op(temp2)
1.316 -
1.317 - # Get method on temp2.
1.318 -
1.319 - self._generateAttr(node, "__contains__", self.attribute_load_instructions)
1.320 - temp_method = self.optimiser.optimise_temp_storage()
1.321 -
1.322 - # Add arguments.
1.323 - # NOTE: No support for defaults.
1.324 -
1.325 - self._generateInvocation(temp_method, (temp2, temp1))
1.326 -
1.327 - temp_result = self.get_temp()
1.328 - self._generateTestBoolean(node, temp_result)
1.329 - self.discard_temp(temp_result)
1.330 -
1.331 - if op_name.find("not") != -1:
1.332 - self.new_op(InvertBoolean(source="status", target="status"))
1.333 -
1.334 - # Test the result and jump to the end block if false.
1.335 -
1.336 - if op is not last_op:
1.337 - self.new_op(JumpIfFalse(end_block, working="status"))
1.338 -
1.339 - # Compilation duties...
1.340 -
1.341 - self.discard_temp(temp1)
1.342 -
1.343 - self.discard_temp(temp2)
1.344 -
1.345 - # With the status set above, produce a boolean result.
1.346 -
1.347 - self.set_block(end_block)
1.348 -
1.349 - # Yield the appropriate value.
1.350 -
1.351 - self._generateLoadBoolean(node)
1.352 -
1.353 - # Expressions.
1.354 -
1.355 - def visitBackquote(self, node): raise TranslationNotImplementedError("Backquote")
1.356 -
1.357 - def visitCallFunc(self, node):
1.358 -
1.359 - """
1.360 - Evaluate positional arguments, evaluate and store keyword arguments in
1.361 - the correct location, then invoke the function.
1.362 - """
1.363 -
1.364 - # Mark the frame, evaluate the target, generate the call.
1.365 -
1.366 - self._startCallFunc()
1.367 - self.dispatch(node.node)
1.368 - temp_target, target, temp_context = self._generateCallFunc(node.args, node)
1.369 - self._doCallFunc(temp_target, target)
1.370 - self._endCallFunc(temp_target, temp_context)
1.371 -
1.372 - def visitConst(self, node):
1.373 - const = self.importer.get_constant(node.value)
1.374 - self.new_op(LoadConst(const))
1.375 -
1.376 - def visitDict(self, node): raise TranslationNotImplementedError("Dict")
1.377 -
1.378 - def visitEllipsis(self, node): raise TranslationNotImplementedError("Ellipsis")
1.379 -
1.380 - def visitExec(self, node): raise TranslationNotImplementedError("Exec")
1.381 -
1.382 - def visitExpression(self, node): raise TranslationNotImplementedError("Expression")
1.383 -
1.384 - def visitGenExpr(self, node): raise TranslationNotImplementedError("GenExpr")
1.385 -
1.386 - def visitGenExprFor(self, node): raise TranslationNotImplementedError("GenExprFor")
1.387 -
1.388 - def visitGenExprIf(self, node): raise TranslationNotImplementedError("GenExprIf")
1.389 -
1.390 - def visitGenExprInner(self, node): raise TranslationNotImplementedError("GenExprInner")
1.391 -
1.392 - def visitGetattr(self, node):
1.393 - self._visitAttr(node, self.attribute_load_instructions)
1.394 -
1.395 - def visitList(self, node):
1.396 - self._generateList(node, node.nodes)
1.397 -
1.398 - def visitListComp(self, node):
1.399 - self._generateList(node)
1.400 - temp_list = self.optimiser.optimise_temp_storage()
1.401 -
1.402 - # Get the list's append method.
1.403 -
1.404 - self._generateAttr(node, "append", self.attribute_load_instructions)
1.405 - temp_method = self.optimiser.optimise_temp_storage()
1.406 -
1.407 - self.visitListCompFor(node.quals[0], node.quals[1:], node.expr, temp_list, temp_method)
1.408 -
1.409 - # Generate a reference to the list.
1.410 -
1.411 - self.new_op(temp_list)
1.412 -
1.413 - self.discard_temp(temp_method)
1.414 - self.discard_temp(temp_list)
1.415 -
1.416 - def visitListCompFor(self, node, following_quals, expr, temp_list, temp_method):
1.417 - temp_iterator, next_block, exit_block, else_block = self._startFor(node)
1.418 -
1.419 - # Explicit dispatch to tests, following loops, expression.
1.420 -
1.421 - if node.ifs:
1.422 - self.visitListCompIf(node.ifs[0], node.ifs[1:], following_quals, expr, temp_list, temp_method)
1.423 -
1.424 - # Explicit dispatch to following loops, expression.
1.425 -
1.426 - elif following_quals:
1.427 - self.visitListCompFor(following_quals[0], following_quals[1:], expr, temp_list, temp_method)
1.428 -
1.429 - # Explicit dispatch to the expression.
1.430 -
1.431 - else:
1.432 - self.dispatch(expr)
1.433 -
1.434 - # Append the value to the list.
1.435 -
1.436 - temp_value = self.optimiser.optimise_temp_storage()
1.437 - self._generateInvocation(temp_method, (temp_list, temp_value,))
1.438 -
1.439 - self._endFor(node, temp_iterator, next_block, exit_block, else_block)
1.440 -
1.441 - def visitListCompIf(self, node, following_tests, following_quals, expr, temp_list, temp_method):
1.442 - exit_block = self.new_block()
1.443 -
1.444 - # Evaluate the test and jump beyond the body if it is not satisfied.
1.445 -
1.446 - self.dispatch(node.test)
1.447 -
1.448 - temp = self.optimiser.optimise_temp_storage()
1.449 - self.new_op(temp)
1.450 - self._generateTestBoolean(node, temp)
1.451 - self.new_op(JumpIfFalse(exit_block, working="status"))
1.452 -
1.453 - # Explicit dispatch to tests, following loops, expression.
1.454 -
1.455 - if following_tests:
1.456 - self.visitListCompIf(following_tests[0], following_tests[1:], following_quals, expr, temp_list, temp_method)
1.457 -
1.458 - # Explicit dispatch to following loops, expression.
1.459 -
1.460 - elif following_quals:
1.461 - self.visitListCompFor(following_quals[0], following_quals[1:], expr, temp_list, temp_method)
1.462 -
1.463 - # Explicit dispatch to the expression.
1.464 -
1.465 - else:
1.466 - self.dispatch(expr)
1.467 -
1.468 - # Append the value to the list.
1.469 -
1.470 - temp_value = self.optimiser.optimise_temp_storage()
1.471 - self._generateInvocation(temp_method, (temp_list, temp_value,))
1.472 -
1.473 - self.set_block(exit_block)
1.474 -
1.475 - def visitName(self, node):
1.476 - self._visitName(node, self.name_load_instructions)
1.477 -
1.478 - def visitSlice(self, node):
1.479 - args = [node.expr]
1.480 -
1.481 - if node.lower is None:
1.482 - args.append(compiler.ast.Name("None"))
1.483 - if node.upper is None:
1.484 - args.append(compiler.ast.Name("None"))
1.485 - else:
1.486 - args.append(node.upper)
1.487 - else:
1.488 - args.append(node.lower)
1.489 - if node.upper is None:
1.490 - args.append(compiler.ast.Name("None"))
1.491 - else:
1.492 - args.append(node.upper)
1.493 -
1.494 - temp_fn = self._getOperatorFunction(node, self.in_assignment and "AssSlice" or "Slice")
1.495 - self._visitCall(node, temp_fn, args)
1.496 - self.discard_temp(temp_fn)
1.497 -
1.498 - def visitSubscript(self, node):
1.499 - temp_fn = self._getOperatorFunction(node, self.in_assignment and "AssSubscript" or "Subscript")
1.500 - self._visitCall(node, temp_fn, [node.expr] + node.subs)
1.501 - self.discard_temp(temp_fn)
1.502 -
1.503 - def visitTuple(self, node):
1.504 - self._generateTuple(node)
1.505 -
1.506 - # Definitions.
1.507 -
1.508 - def visitAssign(self, node):
1.509 -
1.510 - """
1.511 - Evaluate the expression from the given 'node' and assign it to the
1.512 - associated recipients.
1.513 - """
1.514 -
1.515 - self.dispatch(node.expr)
1.516 -
1.517 - # Record the value and then dispatch to the assignment targets.
1.518 -
1.519 - self.record_value(self.has_immediate_usage(node.nodes))
1.520 -
1.521 - self.in_assignment = True
1.522 -
1.523 - for n in node.nodes:
1.524 - self.dispatch(n)
1.525 -
1.526 - self.in_assignment = False
1.527 - self.discard_value()
1.528 -
1.529 - def visitAssAttr(self, node):
1.530 -
1.531 - "Assign the assignment expression to the recipient 'node'."
1.532 -
1.533 - self.start_target()
1.534 - self._visitAttr(node, self.optimiser.get_attribute_store_instructions())
1.535 - self.assign_value()
1.536 -
1.537 - def visitAssList(self, node):
1.538 -
1.539 - """
1.540 - Assign items from the assignment expression to each of the recipients
1.541 - found within the given 'node'.
1.542 - """
1.543 -
1.544 - self.new_op(self.expr_temp[-1])
1.545 - self._generateAttr(node, "__getitem__", self.attribute_load_instructions)
1.546 - temp_getitem = self.optimiser.optimise_temp_storage()
1.547 -
1.548 - for i, n in enumerate(node.nodes):
1.549 - self._startCallFunc()
1.550 - self.new_op(temp_getitem)
1.551 - temp_target, target, temp_context = self._generateCallFunc([compiler.ast.Const(i)], node)
1.552 - self._doCallFunc(temp_target, target)
1.553 - self._endCallFunc(temp_context=temp_context)
1.554 -
1.555 - # Provide a different source value.
1.556 - # NOTE: Permitting immediate usage given that neither name nor
1.557 - # NOTE: attribute accesses should involve a function call
1.558 - # NOTE: overwriting the above result.
1.559 -
1.560 - self.record_value(self.is_immediate_user(n))
1.561 - self.dispatch(n)
1.562 - self.discard_value()
1.563 -
1.564 - self.discard_temp(temp_getitem)
1.565 -
1.566 - def visitAssName(self, node):
1.567 -
1.568 - "Assign the assignment expression to the recipient 'node'."
1.569 -
1.570 - if node.flags == "OP_DELETE":
1.571 - raise TranslationNotImplementedError("AssName(OP_DELETE)")
1.572 - self._visitAssName(node)
1.573 -
1.574 - def _visitAssName(self, node):
1.575 - self.start_target()
1.576 - self._visitName(node, self.name_store_instructions)
1.577 - self.assign_value()
1.578 -
1.579 - # Add any attribute usage guards.
1.580 -
1.581 - self._generateGuards(node)
1.582 -
1.583 - visitAssTuple = visitAssList
1.584 -
1.585 - def visitAugAssign(self, node):
1.586 -
1.587 - # Find the augmented assignment function and attempt to use it.
1.588 -
1.589 - temp_fn = self._getOperatorAugAssignFunction(node)
1.590 - self._visitCall(node, temp_fn, (node.node, node.expr))
1.591 - self.discard_temp(temp_fn)
1.592 -
1.593 - # Assign the result to the name.
1.594 -
1.595 - self.record_value(1)
1.596 -
1.597 - if isinstance(node.node, compiler.ast.Name):
1.598 - self._visitAssName(node.node)
1.599 - elif isinstance(node.node, compiler.ast.Getattr):
1.600 - self.visitAssAttr(node.node)
1.601 - else:
1.602 - raise TranslationNotImplementedError("AugAssign(Slice or Subscript)")
1.603 -
1.604 - self.discard_value()
1.605 -
1.606 - def visitClass(self, node):
1.607 - if not used_by_unit(node):
1.608 - return
1.609 -
1.610 - # Store the name.
1.611 -
1.612 - self.new_op(LoadClass(node.unit))
1.613 - self._storeName(node)
1.614 -
1.615 - # Visit the code.
1.616 -
1.617 - unit = self.unit
1.618 - self.unit = node.unit
1.619 - self.dispatch(node.code)
1.620 - self.unit = unit
1.621 -
1.622 - def visitDecorators(self, node): raise TranslationNotImplementedError("Decorators")
1.623 -
1.624 - def visitFrom(self, node):
1.625 - self._visitImport(node)
1.626 -
1.627 - # Store each imported name if its reference is not set as a constant
1.628 - # module global.
1.629 -
1.630 - module = self.importer.get_module(node.modname)
1.631 -
1.632 - for name, alias in node.names:
1.633 - if name != "*":
1.634 - self._importName(module, name, alias, node)
1.635 - else:
1.636 - for attrname in module.module_attributes().keys():
1.637 - self._importName(module, attrname, None, node)
1.638 -
1.639 - def visitFunction(self, node):
1.640 - if not used_by_unit(node):
1.641 - return
1.642 -
1.643 - # Only store the name when visiting this node from outside.
1.644 -
1.645 - if self.unit is not node.unit:
1.646 - self._visitFunctionDeclaration(node)
1.647 -
1.648 - # Record the declared function.
1.649 -
1.650 - self._storeName(node)
1.651 -
1.652 - # Visiting of the code occurs when get_code is invoked on this node.
1.653 -
1.654 - else:
1.655 - self._visitFunctionDefinition(node)
1.656 -
1.657 - def visitGlobal(self, node): pass
1.658 -
1.659 - def visitImport(self, node):
1.660 - self._visitImport(node)
1.661 -
1.662 - for name, alias in node.names:
1.663 - module = self.importer.get_module(name)
1.664 - self.new_op(LoadConst(module))
1.665 - self._storeName(node, alias or name)
1.666 -
1.667 - def visitKeyword(self, node): pass
1.668 -
1.669 - def visitLambda(self, node):
1.670 -
1.671 - """
1.672 - Lambda functions can be represented as globally defined functions
1.673 - provided they do not define any default parameter values, since these
1.674 - may defined in a non-global scope.
1.675 -
1.676 - Where defaults are defined, an object must be created and its content
1.677 - defined: the callable member of the object's structure must be set to
1.678 - the lambda function definition; each default must be attached to the
1.679 - object as an attribute, as is the case with normal functions and
1.680 - methods.
1.681 - """
1.682 -
1.683 - # Produce the reference to this function when visiting this node from
1.684 - # outside.
1.685 -
1.686 - if self.unit is not node.unit:
1.687 -
1.688 - # Provide the declared function.
1.689 -
1.690 - self._visitFunctionDeclaration(node)
1.691 -
1.692 - # Visiting of the code occurs when get_code is invoked on this node.
1.693 -
1.694 - else:
1.695 - self._visitFunctionDefinition(node)
1.696 -
1.697 - def visitModule(self, node):
1.698 - extend = ExtendFrame()
1.699 - self.new_op(extend)
1.700 - self.dispatch(node.node)
1.701 - self.set_frame_usage(node, extend)
1.702 -
1.703 - # Statements.
1.704 -
1.705 - def visitStmt(self, node):
1.706 -
1.707 - "Process the collection of statements provided by 'node'."
1.708 -
1.709 - for n in node.nodes:
1.710 -
1.711 - # Process the statement.
1.712 -
1.713 - self.dispatch(n)
1.714 -
1.715 - # Prevent incorrect optimisation by resetting the optimiser after
1.716 - # each statement.
1.717 -
1.718 - self.optimiser.reset()
1.719 -
1.720 - def visitAssert(self, node): raise TranslationNotImplementedError("Assert")
1.721 -
1.722 - def visitBreak(self, node):
1.723 - next_block, exit_block = self.get_loop_blocks()
1.724 - self.new_op(Jump(exit_block))
1.725 -
1.726 - def visitContinue(self, node):
1.727 - next_block, exit_block = self.get_loop_blocks()
1.728 - self.new_op(Jump(next_block))
1.729 -
1.730 - def visitDiscard(self, node):
1.731 - self.dispatch(node.expr)
1.732 - self.optimiser.optimise_unused_results()
1.733 -
1.734 - def visitFor(self, node):
1.735 - temp_iterator, next_block, exit_block, else_block = self._startFor(node, node.else_)
1.736 - self.dispatch(node.body)
1.737 - self._endFor(node, temp_iterator, next_block, exit_block, else_block, node.else_)
1.738 -
1.739 - def visitIf(self, node):
1.740 - first = True
1.741 - next_block = None
1.742 - exit_block = self.new_block()
1.743 -
1.744 - clauses = node.tests + [(None, node.else_)]
1.745 -
1.746 - for clause in clauses:
1.747 - test, body = clause
1.748 - if body is None:
1.749 - break
1.750 -
1.751 - if not first:
1.752 - self.new_op(Jump(exit_block)) # finish last body
1.753 - self.set_block(next_block) # start next test
1.754 - next_block = None
1.755 -
1.756 - if test is not None:
1.757 - self.dispatch(test)
1.758 -
1.759 - temp = self.optimiser.optimise_temp_storage()
1.760 - self.new_op(temp)
1.761 - self._generateTestBoolean(node, temp)
1.762 -
1.763 - next_block = self.new_block()
1.764 - self.new_op(JumpIfFalse(next_block, working="status"))
1.765 -
1.766 - self.dispatch(body)
1.767 - first = False
1.768 -
1.769 - if next_block is not None:
1.770 - self.set_block(next_block)
1.771 -
1.772 - self.set_block(exit_block)
1.773 -
1.774 - def visitIfExp(self, node): raise TranslationNotImplementedError("IfExp")
1.775 -
1.776 - def visitPass(self, node): pass
1.777 -
1.778 - def visitPrint(self, node):
1.779 - self._visitPrint(node, "_print")
1.780 -
1.781 - def visitPrintnl(self, node):
1.782 - self._visitPrint(node, "_printnl")
1.783 -
1.784 - def visitRaise(self, node):
1.785 -
1.786 - if node.expr1 is not None:
1.787 -
1.788 - # NOTE: expr1 only => instance provided
1.789 -
1.790 - self.dispatch(node.expr1)
1.791 -
1.792 - if node.expr2 is not None:
1.793 - temp = self.optimiser.optimise_temp_storage()
1.794 -
1.795 - self.dispatch(node.expr2)
1.796 - temp_arg = self.optimiser.optimise_temp_storage()
1.797 -
1.798 - self._generateInvocation(temp, (temp_arg,))
1.799 -
1.800 - self.discard_temp(temp_arg)
1.801 -
1.802 - self.new_op(Transfer(source="working", target="exception"))
1.803 -
1.804 - self.new_op(RaiseException())
1.805 -
1.806 - def visitReturn(self, node):
1.807 - if node.value is not None:
1.808 - self.dispatch(node.value)
1.809 - else:
1.810 - self.dispatch(compiler.ast.Name("None"))
1.811 -
1.812 - if self.in_exception_handler:
1.813 - self.new_op(ClearException(target="exception"))
1.814 -
1.815 - # NOTE: Support finally blocks here.
1.816 -
1.817 - if self.exception_blocks[-1]:
1.818 - self.new_op(PopHandler(len(self.exception_blocks[-1])))
1.819 -
1.820 - self.new_op(Return())
1.821 -
1.822 - def visitTryExcept(self, node):
1.823 - exit_block = self.new_block()
1.824 - else_block = self.new_block()
1.825 - handler_block = self.new_block()
1.826 -
1.827 - self.add_exception_blocks(handler_block, exit_block)
1.828 -
1.829 - # Try...
1.830 - # Produce the code, then jump to the exit.
1.831 -
1.832 - self.new_op(PushHandler(handler_block))
1.833 - self.dispatch(node.body)
1.834 - self.new_op(PopHandler(1))
1.835 -
1.836 - if node.else_ is not None:
1.837 - self.new_op(Jump(else_block))
1.838 - else:
1.839 - self.new_op(Jump(exit_block))
1.840 -
1.841 - # Start of handlers.
1.842 -
1.843 - self.set_block(handler_block)
1.844 - self.new_op(PopHandler(1))
1.845 -
1.846 - # Disable the handlers.
1.847 -
1.848 - self.drop_exception_blocks()
1.849 -
1.850 - for name, assignment, handler in node.handlers:
1.851 - next_block = self.new_block()
1.852 -
1.853 - # Test the given exception against the current exception.
1.854 -
1.855 - if name is not None:
1.856 - self.dispatch(name)
1.857 -
1.858 - self.new_op(CheckException(target="status"))
1.859 - self.new_op(JumpIfFalse(next_block, working="status"))
1.860 -
1.861 - # Handle assignment to exception variable.
1.862 -
1.863 - if assignment is not None:
1.864 - self.new_op(Transfer(source="working", target="exception"))
1.865 -
1.866 - # Record the value to be assigned.
1.867 -
1.868 - self.record_value()
1.869 - self.dispatch(assignment)
1.870 - self.discard_value()
1.871 -
1.872 - # Produce the handler code, then jump to the exit.
1.873 -
1.874 - self.in_exception_handler = True
1.875 - self.dispatch(handler)
1.876 - self.in_exception_handler = False
1.877 -
1.878 - self.new_op(Jump(exit_block))
1.879 -
1.880 - self.set_block(next_block)
1.881 -
1.882 - # Unhandled exceptions.
1.883 -
1.884 - self.new_op(RaiseException())
1.885 -
1.886 - # Optional else clause.
1.887 -
1.888 - if node.else_ is not None:
1.889 - self.set_block(else_block)
1.890 - self.dispatch(node.else_)
1.891 -
1.892 - # Clear the exception.
1.893 -
1.894 - self.set_block(exit_block)
1.895 - self.new_op(ClearException(target="exception"))
1.896 -
1.897 - def visitTryFinally(self, node):
1.898 -
1.899 - """
1.900 - Add finally handler, potentially as an exception handler.
1.901 - Generate body, potentially changing return statements so that they do
1.902 - not return immediately.
1.903 - Generate handler, removing the handler from the active handler list,
1.904 - adding instructions which raise active exceptions.
1.905 - """
1.906 -
1.907 - raise TranslationNotImplementedError("TryFinally")
1.908 -
1.909 - def visitWhile(self, node):
1.910 - exit_block = self.new_block()
1.911 - next_block = self.new_block()
1.912 - else_block = self.new_block()
1.913 -
1.914 - self.set_block(next_block)
1.915 - self.dispatch(node.test)
1.916 -
1.917 - temp = self.optimiser.optimise_temp_storage()
1.918 - self.new_op(temp)
1.919 - self._generateTestBoolean(node, temp)
1.920 -
1.921 - if node.else_ is not None:
1.922 - self.new_op(JumpIfFalse(else_block, working="status"))
1.923 - else:
1.924 - self.new_op(JumpIfFalse(exit_block, working="status"))
1.925 -
1.926 - self.add_loop_blocks(next_block, exit_block)
1.927 -
1.928 - self.dispatch(node.body)
1.929 - self.new_op(Jump(next_block))
1.930 -
1.931 - if node.else_ is not None:
1.932 - self.set_block(else_block)
1.933 -
1.934 - self.dispatch(node.else_)
1.935 -
1.936 - self.set_block(exit_block)
1.937 -
1.938 - self.drop_loop_blocks()
1.939 -
1.940 - def visitWith(self, node): raise TranslationNotImplementedError("With")
1.941 -
1.942 - def visitYield(self, node): raise TranslationNotImplementedError("Yield")
1.943 -
1.944 -# vim: tabstop=4 expandtab shiftwidth=4