micropython

micropython/ast.py

236:6ba10a65eddd
2009-06-02 Paul Boddie Introduced a separate globals processing phase, recording all declared global names before attempting to resolve other names. Removed the Global class and warning about globals not being declared at the module level. Added tests of globals.
     1 #!/usr/bin/env python     2      3 """     4 Translate the AST of a Python program into a more interpretable representation.     5      6 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>     7      8 This program is free software; you can redistribute it and/or modify it under     9 the terms of the GNU General Public License as published by the Free Software    10 Foundation; either version 3 of the License, or (at your option) any later    11 version.    12     13 This program is distributed in the hope that it will be useful, but WITHOUT    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    16 details.    17     18 You should have received a copy of the GNU General Public License along with    19 this program.  If not, see <http://www.gnu.org/licenses/>.    20 """    21     22 from micropython.opt import Optimiser    23 from micropython.common import *    24 from micropython.data import *    25 from micropython.rsvp import *    26 from micropython.trans import Helper    27 import compiler.ast    28 from compiler.visitor import ASTVisitor    29     30 # Program visitors.    31     32 class Translation(ASTVisitor, Helper):    33     34     "A translated module."    35     36     # Attribute access instructions, for use with the appropriate handlers.    37     38     attribute_load_instructions = (    39         LoadAddress, LoadAddressContext, LoadAddressContextCond,    40         LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond    41         )    42     attribute_store_instructions = (    43         None, None, None,    44         StoreAttr, StoreAttrIndex, None    45         )    46     47     # Name access instructions, for use with the appropriate handlers.    48     49     name_load_instructions = (LoadName, LoadAddress, None)    50     name_store_instructions = (StoreName, StoreAddress, StoreAddressContext)    51     52     def __init__(self, module, program):    53     54         """    55         Initialise the translation with an inspected 'module' and the 'program'    56         container.    57         """    58     59         ASTVisitor.__init__(self)    60         self.visitor = self    61         self.module = module    62     63         # Global program dependencies.    64     65         self.program = program    66         self.objtable = self.program.get_object_table()    67         self.paramtable = self.program.get_parameter_table()    68         self.importer = self.program.get_importer()    69         self.builtins = self.importer.modules.get("__builtins__")    70     71         # Optimisation.    72     73         self.optimiser = Optimiser(self, program.optimisations)    74     75         # The current unit being translated.    76     77         self.unit = None    78     79         # The temporary storage used by the current assignment expression.    80     81         self.expr_temp = []    82     83         # Wiring within the code.    84     85         self.labels = {}    86         self.label_number = 0    87         self.loop_blocks = []    88         self.exception_blocks = []    89         self.in_exception_handler = 0    90     91         self.reset()    92     93     def __repr__(self):    94         return "Translation(%r)" % self.module    95     96     def reset(self):    97     98         "Reset the state of the translator."    99    100         # The code itself. This is limited to the code for a particular block   101         # being processed.   102    103         self.blocks = []   104    105         # Information about temporary values.   106    107         self.temp_positions = set()   108         self.max_temp_position = -1   109    110         # Information about instructions which construct frames.   111    112         self.frame_makers = []   113    114         # Optimiser state must be reset for each unit.   115    116         self.optimiser.reset()   117    118     def get_module_code(self, final=0):   119    120         """   121         Return the top-level module code including finalising code if 'final' is   122         set to a true value.   123         """   124    125         self.unit = self.module   126         self.reset()   127    128         block = self.new_block()   129         self.set_block(block)   130    131         if self.module.module is not None:   132             self.dispatch(self.module.module)   133    134         # Finish off the translated program if appropriate.   135    136         if final:   137             self.new_op(Return())   138    139         self.unit.temp_usage = self.max_temp_position + 1   140         self.unit.blocks = self.blocks   141         return self.blocks   142    143     def get_code(self, unit):   144    145         "Return the code for the given 'unit'."   146    147         self.unit = unit   148         self.reset()   149    150         block = self.new_block()   151         self.set_block(block)   152    153         if unit.astnode is not None:   154             self.dispatch(unit.astnode)   155    156         self.unit.temp_usage = self.max_temp_position + 2 # include space for instantiators to expand backwards   157         self.unit.blocks = self.blocks   158         return self.blocks   159    160     def get_instantiator_code(self, cls):   161    162         "Return the code for the given class 'cls'."   163    164         self.unit = cls.get_instantiator()   165         self.reset()   166    167         block = self.new_block()   168         self.set_block(block)   169    170         init_method = cls.get_init_method()   171    172         # Make an object and store it in the unused first slot.   173    174         self.make_instance(cls, len(cls.instance_attributes()))   175         self.new_op(StoreTemp(0))   176    177         # Invoke the appropriate initialiser.   178    179         self.new_op(LoadFunction(init_method))   180         self.new_op(LoadCallable())   181         self.new_op(JumpInFrame())   182    183         # Store the object as the result.   184    185         self.new_op(LoadTemp(0)) # load the context from the locals   186         self.new_op(StoreResult())   187         self.new_op(Return())   188    189         self.unit.blocks = self.blocks   190         return self.blocks   191    192     # Visitor methods.   193    194     def default(self, node, *args):   195         raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__)   196    197     def dispatch(self, node, *args):   198         return ASTVisitor.dispatch(self, node, *args)   199    200     # Concrete visitor methods.   201    202     # Binary operators.   203    204     visitAdd        = Helper._visitBinary   205     visitBitand     = Helper._visitBinary   206     visitBitor      = Helper._visitBinary   207     visitBitxor     = Helper._visitBinary   208     visitDiv        = Helper._visitBinary   209     visitFloorDiv   = Helper._visitBinary   210     visitLeftShift  = Helper._visitBinary   211     visitMod        = Helper._visitBinary   212     visitMul        = Helper._visitBinary   213     visitPower      = Helper._visitBinary   214     visitRightShift = Helper._visitBinary   215     visitSub        = Helper._visitBinary   216    217     # Unary operators.   218    219     visitInvert     = Helper._visitUnary   220     visitUnaryAdd   = Helper._visitUnary   221     visitUnarySub   = Helper._visitUnary   222    223     # Logical operators.   224    225     def visitAnd(self, node):   226         end_block = self.new_block()   227         temp_pos = self.reserve_temp()   228         temp = LoadTemp(temp_pos)   229    230         for n in node.nodes[:-1]:   231             self.dispatch(n)   232             self.new_op(StoreTemp(temp_pos))   233    234             self._generateTestBoolean(n, temp)   235             self.new_op(JumpIfFalse(end_block))   236    237         self.dispatch(node.nodes[-1])   238         self.new_op(StoreTemp(temp_pos))   239    240         self.set_block(end_block)   241    242         self.new_op(temp)   243         self.discard_temp(temp)   244    245     def visitNot(self, node):   246         self.dispatch(node.expr)   247    248         temp = self.optimiser.optimise_temp_storage()   249         self._generateTestBoolean(node.expr, temp)   250         self.discard_temp(temp)   251    252         self.new_op(InvertBoolean())   253         self._generateLoadBoolean(node)   254    255     def visitOr(self, node):   256         end_block = self.new_block()   257         temp_pos = self.reserve_temp()   258         temp = LoadTemp(temp_pos)   259    260         for n in node.nodes[:-1]:   261             self.dispatch(n)   262             self.new_op(StoreTemp(temp_pos))   263    264             self._generateTestBoolean(n, temp)   265             self.new_op(JumpIfTrue(end_block))   266    267         self.dispatch(node.nodes[-1])   268         self.new_op(StoreTemp(temp_pos))   269    270         self.set_block(end_block)   271    272         self.new_op(temp)   273         self.discard_temp(temp)   274    275     # Comparisons.   276    277     def visitCompare(self, node):   278    279         """   280         _t1 = node.expr   281         _t1 op1 _t2 and _t2 op2 _t3 and ...   282         """   283    284         end_block = self.new_block()   285    286         self.dispatch(node.expr)   287         temp2 = self.optimiser.optimise_temp_storage()   288    289         # NOTE: Replicated by some code in micropython.inspect.visitCompare.   290    291         last_op = node.ops[-1]   292    293         for op in node.ops:   294             op_name, next_node = op   295             methods = comparison_methods[op_name]   296    297             # Propagate the arguments as we traverse the construct.   298    299             temp1 = temp2   300             self.dispatch(next_node)   301             temp2 = self.optimiser.optimise_temp_storage()   302    303             # Use the appropriate mechanism, setting the boolean status for the   304             # comparison.   305    306             if methods is not None:   307                 left_method, right_method = methods   308    309                 # Generate method call using evaluated argument and next node.   310    311                 temp_result = self._generateBinary(node, temp1, temp2, left_method, right_method)   312                 self.new_op(temp_result)   313                 self._generateTestBoolean(node, temp_result)   314                 self.discard_temp(temp_result)   315    316             else:   317                 # Deal with the special operators.   318    319                 if op_name.startswith("is"):   320                     self.new_op(temp1)   321                     self.record_value()   322                     self.new_op(temp2)   323                     self.new_op(TestIdentity())   324                     self.set_source()   325                     self.discard_value()   326    327                 elif op_name.endswith("in"):   328                     self.new_op(temp2)   329    330                     # Get method on temp2.   331    332                     self._generateAttr(node, "__contains__", self.attribute_load_instructions)   333                     temp_method = self.optimiser.optimise_temp_storage()   334    335                     # Add arguments.   336                     # NOTE: No support for defaults.   337    338                     self._startCallFunc()   339                     self.new_op(temp2)   340                     self.new_op(StoreFrame(0))   341                     self.new_op(temp1)   342                     self.new_op(StoreFrame(1))   343                     self._endCallFuncArgs(2)   344                     self._doCallFunc(temp_method)   345                     self._endCallFunc(temp_method)   346    347                     temp_result = self.get_temp()   348                     self._generateTestBoolean(node, temp_result)   349                     self.discard_temp(temp_result)   350    351                 if op_name.find("not") != -1:   352                     self.new_op(InvertBoolean())   353    354             # Test the result and jump to the end block if false.   355    356             if op is not last_op:   357                 self.new_op(JumpIfFalse(end_block))   358    359             # Compilation duties...   360    361             self.discard_temp(temp1)   362    363         self.discard_temp(temp2)   364    365         # With the status set above, produce a boolean result.   366    367         self.set_block(end_block)   368    369         # Yield the appropriate value.   370    371         self._generateLoadBoolean(node)   372    373     # Expressions.   374    375     def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote")   376    377     def visitCallFunc(self, node):   378    379         """   380         Evaluate positional arguments, evaluate and store keyword arguments in   381         the correct location, then invoke the function.   382         """   383    384         # Mark the frame, evaluate the target, generate the call.   385    386         self._startCallFunc()   387         self.dispatch(node.node)   388         temp_target, target, temp_context = self._generateCallFunc(node.args, node)   389         self._doCallFunc(temp_target, target)   390         self._endCallFunc(temp_target, target, temp_context)   391    392     def visitConst(self, node):   393         const = self.importer.get_constant(node.value)   394         self.new_op(LoadConst(const))   395    396     def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict")   397    398     def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis")   399    400     def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec")   401    402     def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression")   403    404     def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr")   405    406     def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor")   407    408     def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf")   409    410     def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner")   411    412     def visitGetattr(self, node):   413         self._visitAttr(node, self.attribute_load_instructions)   414    415     def visitList(self, node):   416         self._generateSequence("list", node)   417    418     def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp")   419    420     def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor")   421    422     def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf")   423    424     def visitName(self, node):   425         if self.importer.predefined_constants.has_key(node.name):   426             const = self.importer.get_predefined_constant(node.name)   427             self.new_op(LoadConst(const))   428         else:   429             self._visitName(node, self.name_load_instructions)   430    431     def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice")   432    433     def visitSubscript(self, node):   434         self.dispatch(node.expr)   435         self._startCallFunc()   436         self._generateAttr(node, "__getitem__", self.attribute_load_instructions)   437         temp_target, target, temp_context = self._generateCallFunc(node.subs, node)   438         self._doCallFunc(temp_target, target)   439         self._endCallFunc(temp_target, target, temp_context)   440    441     def visitTuple(self, node):   442         self._generateSequence("tuple", node)   443    444     # Definitions.   445    446     def visitAssign(self, node):   447    448         """   449         Evaluate the expression from the given 'node' and assign it to the   450         associated recipients.   451         """   452    453         self.dispatch(node.expr)   454    455         # Record the value and then dispatch to the assignment targets.   456    457         self.record_value(self.has_immediate_usage(node.nodes))   458    459         for n in node.nodes:   460             self.dispatch(n)   461    462         self.discard_value()   463    464     def visitAssAttr(self, node):   465    466         "Assign the assignment expression to the recipient 'node'."   467    468         self._visitAttr(node, self.attribute_store_instructions)   469         self.set_source()   470    471     def visitAssList(self, node):   472    473         """   474         Assign items from the assignment expression to each of the recipients   475         found within the given 'node'.   476         """   477    478         for i, n in enumerate(node.nodes):   479             self._startCallFunc()   480             self.new_op(self.expr_temp[-1])   481             self._generateAttr(node, "__getitem__", self.attribute_load_instructions)   482             temp_target, target, temp_context = self._generateCallFunc([compiler.ast.Const(i)], node)   483             self._doCallFunc(temp_target, target)   484             self._endCallFunc(temp_target, target, temp_context)   485    486             # Provide a different source value.   487             # NOTE: Permitting immediate usage given that neither name nor   488             # NOTE: attribute accesses should involve a function call   489             # NOTE: overwriting the above result.   490    491             self.record_value(self.is_immediate_user(n))   492             self.dispatch(n)   493             self.discard_value()   494    495     def visitAssName(self, node):   496    497         "Assign the assignment expression to the recipient 'node'."   498    499         self._visitName(node, self.name_store_instructions)   500         self.set_source()   501    502     visitAssTuple = visitAssList   503    504     def visitAugAssign(self, node):   505         use_binary_block = self.new_block()   506         end_block = self.new_block()   507    508         # Evaluate the expression.   509    510         self.dispatch(node.expr)   511         temp2 = self.optimiser.optimise_temp_storage()   512    513         # Evaluate the target.   514    515         self.dispatch(node.node)   516         temp1 = self.optimiser.optimise_temp_storage()   517    518         # Find the augmented assignment method and attempt to use it.   519    520         aug_method, (left_method, right_method) = augassign_methods[node.op]   521         temp_out = self._generateOpMethod(node, temp1, temp2, aug_method, use_binary_block, end_block)   522         self.discard_temp(temp_out) # NOTE: Will re-use the same storage.   523    524         # Where no such method exists, use the binary operator methods.   525    526         self.set_block(use_binary_block)   527         temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method)   528    529         # Assign the result to the name.   530    531         self.set_block(end_block)   532         self.new_op(temp_out)   533         self.record_value(1)   534    535         if isinstance(node.node, compiler.ast.Name):   536             self.visitAssName(node.node)   537         elif isinstance(node.node, compiler.ast.Getattr):   538             self.visitAssAttr(node.node)   539         else:   540             raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign(Slice or Subscript)")   541    542         self.discard_value()   543    544         # Compilation duties...   545    546         self.discard_temp(temp1)   547         self.discard_temp(temp2)   548    549     def visitClass(self, node):   550         if not node.unit.referenced:   551             return   552    553         # Store the name.   554    555         self.new_op(LoadConst(node.unit))   556         self.record_value()   557         self._visitName(node, self.name_store_instructions)   558         self.set_source()   559         self.discard_value()   560    561         # Visit the code.   562    563         unit = self.unit   564         self.unit = node.unit   565         self.dispatch(node.code)   566         self.unit = unit   567    568     def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators")   569    570     def visitFrom(self, node): pass   571    572     def visitFunction(self, node):   573         if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)):   574             return   575    576         # Only store the name when visiting this node from outside.   577    578         if self.unit is not node.unit:   579             self.new_op(LoadFunction(node.unit))   580             self.record_value()   581    582             self._visitName(node, self.name_store_instructions) # AssName equivalent   583             self.set_source()   584             self.discard_value()   585    586             self._generateFunctionDefaults(node.unit)   587    588         # Visiting of the code occurs when get_code is invoked on this node.   589    590         else:   591             # Check frames using the function's details.   592    593             fn = node.unit   594             nparams = len(fn.positional_names)   595             ndefaults = len(fn.defaults)   596    597             fn.body_block = self.new_block()   598    599             # Check the number of parameters and defaults.   600    601             self.new_op(CheckFrame((nparams, ndefaults, fn.has_star)))   602             if ndefaults > 0:   603                 self.new_op(LoadFunction(fn))   604                 self.new_op(FillDefaults((nparams, ndefaults)))   605    606             # Produce the body.   607    608             self.set_block(fn.body_block)   609    610             extend = ExtendFrame()   611             self.new_op(extend)   612    613             self.dispatch(node.code)   614    615             if not isinstance(self.last_op(), Return):   616                 self.dispatch(compiler.ast.Name("None"))   617                 self.new_op(StoreResult())   618                 self.new_op(Return())   619    620             # Make sure that enough frame space is reserved from the start.   621    622             self.set_frame_usage(node, extend)   623    624     def visitGlobal(self, node): pass   625    626     def visitImport(self, node): pass   627    628     def visitKeyword(self, node): pass   629    630     def visitLambda(self, node):   631    632         """   633         Lambda functions can be represented as globally defined functions   634         provided they do not define any default parameter values, since these   635         may defined in a non-global scope.   636    637         Where defaults are defined, an object must be created and its content   638         defined: the callable member of the object's structure must be set to   639         the lambda function definition; each default must be attached to the   640         object as an attribute, as is the case with normal functions and   641         methods.   642         """   643    644         # Produce the reference to this function when visiting this node from   645         # outside.   646    647         if self.unit is not node.unit:   648             fn = node.unit   649             ndefaults = len(fn.defaults)   650             temp = self._generateFunctionDefaults(fn)   651    652             if ndefaults > 0:   653                 self.new_op(LoadConst(fn))   654             else:   655                 self.new_op(LoadFunction(fn))   656    657             # Populate the new object required for the function.   658    659             if temp is not None:   660                 self.new_op(LoadCallable())   661                 self.new_op(temp)   662                 self.new_op(StoreCallable())   663    664                 self.new_op(temp)   665                 #self.discard_temp(temp)   666    667         # Visiting of the code occurs when get_code is invoked on this node.   668    669         else:   670             # Check frames using the function's details.   671    672             fn = node.unit   673             nparams = len(fn.positional_names)   674             ndefaults = len(fn.defaults)   675    676             fn.body_block = self.new_block()   677    678             # Check the number of parameters and defaults.   679    680             self.new_op(CheckFrame((nparams, ndefaults, fn.has_star)))   681             if ndefaults > 0:   682                 self.new_op(LoadTemp(0)) # context provides storage   683                 self.new_op(FillDefaults((nparams, ndefaults)))   684    685             # Produce the body.   686    687             self.set_block(fn.body_block)   688    689             extend = ExtendFrame()   690             self.new_op(extend)   691    692             self.dispatch(node.code)   693    694             self.new_op(StoreResult())   695             self.new_op(Return())   696    697             # Make sure that enough frame space is reserved from the start.   698    699             self.set_frame_usage(node, extend)   700    701     def visitModule(self, node):   702         extend = ExtendFrame()   703         self.new_op(extend)   704         self.dispatch(node.node)   705         self.set_frame_usage(node, extend)   706    707     # Statements.   708    709     def visitStmt(self, node):   710    711         "Process the collection of statements provided by 'node'."   712    713         for n in node.nodes:   714    715             # Process the statement.   716    717             self.dispatch(n)   718    719             # Discard temporary storage.   720    721             if self.temp_positions:   722                 #print "Had temp", self.temp_positions   723                 self.temp_positions = set()   724    725             # Prevent incorrect optimisation by resetting the optimiser after   726             # each statement.   727    728             self.optimiser.reset()   729    730     def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert")   731    732     def visitBreak(self, node):   733         next_block, exit_block = self.get_loop_blocks()   734         self.new_op(Jump(exit_block))   735    736     def visitContinue(self, node):   737         next_block, exit_block = self.get_loop_blocks()   738         self.new_op(Jump(next_block))   739    740     def visitDiscard(self, node):   741         self.dispatch(node.expr)   742         self.optimiser.optimise_unused_results()   743    744     def visitFor(self, node):   745         next_handler_block = self.new_block()   746         end_handler_block = self.new_block()   747         exit_block = self.new_block()   748         next_block = self.new_block()   749         else_block = self.new_block()   750    751         # Get the "list" to be iterated over, obtain its iterator.   752    753         self._startCallFunc()   754         self.dispatch(node.list)   755         self._generateAttr(node, "__iter__", self.attribute_load_instructions)   756         temp_target, target, temp_context = self._generateCallFunc([], node)   757         self._doCallFunc(temp_target, target)   758         self._endCallFunc(temp_target, target, temp_context)   759    760         temp_iterator = self.optimiser.optimise_temp_storage()   761    762         # In the loop...   763    764         self.set_block(next_block)   765    766         # Handle exceptions when calling "next"...   767    768         self.new_op(PushHandler(next_handler_block))   769    770         # Use the iterator to get the next value.   771    772         self._startCallFunc()   773         self.new_op(temp_iterator)   774         self._generateAttr(node, "next", self.attribute_load_instructions)   775         temp_target, target, temp_context = self._generateCallFunc([], node)   776         self._doCallFunc(temp_target, target)   777         self._endCallFunc(temp_target, target, temp_context)   778    779         # Record the value to be assigned.   780    781         self.record_value()   782    783         # Skip the handler where the call was successful.   784    785         self.new_op(PopHandler())   786         self.new_op(Jump(end_handler_block))   787    788         # Enter the exception handler.   789    790         self.set_block(next_handler_block)   791         self.new_op(PopHandler())   792    793         # Test for StopIteration.   794    795         self.load_builtin("StopIteration", node)   796         self.new_op(CheckException())   797         if node.else_ is not None:   798             self.new_op(JumpIfTrue(else_block))   799         else:   800             self.new_op(JumpIfTrue(exit_block))   801    802         # Re-raise the exception otherwise.   803    804         self.new_op(RaiseException())   805    806         # After the handler, clear the exception.   807    808         self.set_block(end_handler_block)   809         self.new_op(ClearException())   810    811         # Assign to the target.   812    813         self.dispatch(node.assign)   814         self.discard_value()   815    816         # Process the body with the current next and exit points.   817    818         self.add_loop_blocks(next_block, exit_block)   819         self.dispatch(node.body)   820         self.drop_loop_blocks()   821    822         # Repeat the loop.   823    824         self.new_op(Jump(next_block))   825    826         # Produce the "else" section.   827    828         if node.else_ is not None:   829             self.set_block(exit_block)   830    831             self.dispatch(node.else_)   832    833         # After the loop...   834    835         self.set_block(exit_block)   836    837         # Compilation duties...   838    839         self.discard_temp(temp_iterator)   840    841     def visitIf(self, node):   842         first = 1   843         next_block = None   844         exit_block = self.new_block()   845    846         clauses = node.tests + [(None, node.else_)]   847    848         for clause in clauses:   849             test, body = clause   850             if body is None:   851                 break   852    853             if not first:   854                 self.new_op(Jump(exit_block)) # finish last body   855                 self.set_block(next_block)    # start next test   856                 next_block = None   857    858             if test is not None:   859                 self.dispatch(test)   860    861                 temp = self.optimiser.optimise_temp_storage()   862                 self._generateTestBoolean(node, temp)   863    864                 next_block = self.new_block()   865                 self.new_op(JumpIfFalse(next_block))   866    867             self.dispatch(body)   868             first = 0   869    870         if next_block is not None:   871             self.set_block(next_block)   872    873         self.set_block(exit_block)   874    875     def visitPass(self, node): pass   876    877     def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print")   878    879     def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl")   880    881     def visitRaise(self, node):   882         # NOTE: expr1 only => instance provided   883         self.dispatch(node.expr1)   884    885         if node.expr2 is not None:   886             temp = self.optimiser.optimise_temp_storage()   887    888             self.dispatch(node.expr2)   889             temp_arg = self.optimiser.optimise_temp_storage()   890    891             self._startCallFunc()   892             self.new_op(temp_arg)   893             self.new_op(StoreFrame(0))   894             self._endCallFuncArgs(1)   895             self._doCallFunc(temp)   896             self._endCallFunc(temp)   897    898             self.discard_temp(temp_arg)   899    900         self.new_op(StoreException())   901         self.new_op(RaiseException())   902    903     def visitReturn(self, node):   904         if node.value is not None:   905             self.dispatch(node.value)   906         else:   907             self.dispatch(compiler.ast.Name("None"))   908    909         self.new_op(StoreResult())   910    911         if self.in_exception_handler:   912             self.new_op(ClearException())   913    914         self.new_op(Return())   915    916     def visitTryExcept(self, node):   917         exit_block = self.new_block()   918         else_block = self.new_block()   919         handler_block = self.new_block()   920    921         self.add_exception_blocks(handler_block, exit_block)   922    923         # Try...   924         # Produce the code, then jump to the exit.   925    926         self.new_op(PushHandler(handler_block))   927         self.dispatch(node.body)   928         self.new_op(PopHandler())   929    930         if node.else_ is not None:   931             self.new_op(Jump(else_block))   932         else:   933             self.new_op(Jump(exit_block))   934    935         # Start of handlers.   936    937         self.set_block(handler_block)   938         self.new_op(PopHandler())   939    940         for name, assignment, handler in node.handlers:   941             next_block = self.new_block()   942    943             # Test the given exception against the current exception.   944    945             if name is not None:   946                 self.dispatch(name)   947    948                 self.new_op(CheckException())   949                 self.new_op(JumpIfFalse(next_block))   950    951                 # Handle assignment to exception variable.   952    953                 if assignment is not None:   954                     self.new_op(LoadException())   955    956                     # Record the value to be assigned.   957    958                     self.record_value()   959                     self.dispatch(assignment)   960                     self.discard_value()   961    962             # Produce the handler code, then jump to the exit.   963    964             self.in_exception_handler = 1   965             self.dispatch(handler)   966             self.in_exception_handler = 0   967    968             self.new_op(Jump(exit_block))   969    970             self.set_block(next_block)   971    972         # Unhandled exceptions.   973    974         self.new_op(RaiseException())   975    976         # Optional else clause.   977    978         if node.else_ is not None:   979             self.set_block(else_block)   980             self.dispatch(node.else_)   981    982         # Clear the exception.   983    984         self.set_block(exit_block)   985         self.new_op(ClearException())   986         self.drop_exception_blocks()   987    988     def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally")   989    990     def visitWhile(self, node):   991         exit_block = self.new_block()   992         next_block = self.new_block()   993         else_block = self.new_block()   994    995         self.set_block(next_block)   996         self.dispatch(node.test)   997         if node.else_ is not None:   998             self.new_op(JumpIfFalse(else_block))   999         else:  1000             self.new_op(JumpIfFalse(exit_block))  1001   1002         self.add_loop_blocks(next_block, exit_block)  1003   1004         self.dispatch(node.body)  1005         self.new_op(Jump(next_block))  1006   1007         if node.else_ is not None:  1008             self.set_block(else_block)  1009   1010             self.dispatch(node.else_)  1011   1012         self.set_block(exit_block)  1013   1014         self.drop_loop_blocks()  1015   1016     def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With")  1017   1018     def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield")  1019   1020 # vim: tabstop=4 expandtab shiftwidth=4