micropython

micropython/ast.py

138:4c95794770e6
2008-09-04 Paul Boddie Made object construction through MakeObject use details of a supplied class, reserving an extra location for type information. Changed some LoadAddress usage to LoadConst in order to feed instructions which require a value, not the type information of an object (which is what LoadAddress acting on a reference to an object, as opposed to an attribute, would provide). Added parameter default details to raw class and function information, although further default details are required. Added convenience methods to the RSVPMachine class for inspecting and stepping through execution of a program. Changed various RSVP implementations, fixing stack manipulation and returning from subroutines. Made the test of lists wider in scope.
     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 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.common import *    23 from micropython.data import *    24 from micropython.rsvp import *    25 import compiler.ast    26 from compiler.visitor import ASTVisitor    27     28 # Program visitors.    29     30 class Translation(ASTVisitor):    31     32     "A translated module."    33     34     supported_optimisations = [    35         "constant_storage", "source_storage", "known_target", "self_access",    36         "temp_storage", "load_operations", "no_operations", "unused_results"    37         ]    38     39     # Attribute access instructions, for use with the appropriate handlers.    40     41     attribute_load_instructions = (LoadAddress, LoadAddressContext, LoadAttr, LoadAttrIndex)    42     attribute_store_instructions = (None, None, StoreAttr, StoreAttrIndex)    43     44     # Name access instructions, for use with the appropriate handlers.    45     46     name_load_instructions = (LoadName, LoadAddress)    47     name_store_instructions = (StoreName, StoreAddress)    48     49     # Instructions which affect the current value.    50     51     current_value_instructions = (LoadConst, LoadName, LoadTemp, LoadAddress, LoadAddressContext, LoadAttr, LoadAttrIndex,    52         LoadCallable, LoadContext, LoadResult, LoadException, MakeObject)    53     54     def __init__(self, module, importer, optimisations=None):    55     56         """    57         Initialise the translation with an inspected 'module', the 'importer'    58         and optional 'optimisations'. See the 'supported_optimisations'    59         attribute of this class for permitted values.    60         """    61     62         ASTVisitor.__init__(self)    63         self.visitor = self    64         self.module = module    65     66         # Global program dependencies.    67     68         self.importer = importer    69         self.objtable = self.importer.get_object_table()    70         self.paramtable = self.importer.get_parameter_table()    71         self.builtins = self.importer.modules.get("__builtins__")    72     73         # Desired optimisations.    74     75         self.optimisations = set(optimisations or [])    76     77         # The current unit being translated.    78     79         self.unit = None    80     81         # The current "active" instruction.    82         # As a rule, this will become the last instruction, but some    83         # control-flow operations will flush the "active" instruction.    84     85         self.active = None    86         self.active_value = None    87     88         # The temporary storage used by the current assignment expression.    89     90         self.expr_temp = None    91     92         # Wiring within the code.    93     94         self.labels = {}    95         self.label_number = 0    96         self.loop_labels = []    97         self.exception_labels = []    98     99         # The code itself. This is limited to the code for a particular block   100         # being processed. Also retained is information about temporary values   101         # and instructions which construct frames.   102    103         self.code = None   104         self.temp_positions = set()   105         self.max_temp_position = -1   106         self.frame_makers = []   107    108     def __repr__(self):   109         return "Translation(%r)" % self.module   110    111     def get_module_code(self):   112    113         "Return the top-level module code."   114    115         self.unit = self.module   116         self.code = []   117         self.temp_positions = set()   118         self.max_temp_position = -1   119    120         if self.module.module is not None:   121             self.dispatch(self.module.module)   122    123         self.unit.temp_usage = self.max_temp_position + 1   124         return self.code   125    126     def get_code(self, unit):   127    128         "Return the code for the given 'unit'."   129    130         self.unit = unit   131         self.code = []   132         self.temp_positions = set()   133         self.max_temp_position = -1   134    135         if unit.astnode is not None:   136             self.dispatch(unit.astnode)   137    138         self.unit.temp_usage = self.max_temp_position + 1   139         return self.code   140    141     def get_instantiator_code(self, cls):   142    143         "Return the code for the given class 'cls'."   144    145         self.unit = cls.get_instantiator()   146         self.code = []   147         self.temp_positions = set()   148         self.max_temp_position = -1   149    150         init_method = cls.get_init_method()   151    152         # Convert this frame back to being an invocation frame.   153    154         self.new_op(RecoverFrame())   155    156         # Fix the current frame to include a new storage slot at the beginning.   157    158         self.new_op(AdjustFrame(-1))   159    160         # Make an object.   161    162         self.make_object(cls, len(cls.instance_attributes()))   163         self.new_op(StoreFrame(0))   164    165         # Invoke the appropriate initialiser.   166    167         self.new_op(LoadConst(init_method))   168         self.new_op(LoadCallable())   169         self.new_op(JumpWithFrame())   170    171         # Store the object as the result.   172    173         self.new_op(LoadName(init_method.all_locals()["self"])) # load the context in the invocation frame   174         self.new_op(StoreResult())   175         self.new_op(Return())   176    177         return self.code   178    179     # Allocation-related methods.   180    181     def make_object(self, cls, n):   182    183         """   184         Request a new object with the given class 'cls' and with 'n' attributes.   185         """   186    187         # NOTE: Object headers are one location.   188    189         self.new_op(LoadConst(cls))   190         self.new_op(MakeObject(n + 1))   191    192     # Name-related methods.   193    194     def get_scope(self, name):   195    196         "Return the scope for the given 'name'."   197    198         if self.unit.has_key(name):   199             return "local"   200         elif self.module.has_key(name):   201             return "global"   202         else:   203             return "builtins"   204    205     def load_builtin(self, name, node):   206    207         "Generate an instruction loading 'name' for the given 'node'."   208    209         self.new_op(LoadAddress(self.get_builtin(name, node)))   210    211     def get_builtin_class(self, name, node):   212         return self.get_builtin(name, node).value   213    214     def get_builtin(self, name, node):   215    216         """   217         Return the built-in module definition for the given 'name', used by the   218         given 'node'.   219         """   220    221         if self.builtins is not None:   222             try:   223                 return self.builtins[name]   224             except KeyError:   225                 raise TranslateError(self.module.full_name(), node, "No __builtins__ definition is available for name %r." % name)   226         else:   227             raise TranslateError(self.module.full_name(), node, "No __builtins__ module is available for name %r." % name)   228    229     # Code feature methods.   230    231     def new_label(self):   232    233         "Return a new label object for use with set_label."   234    235         number = self.label_number   236         label = Label(number)   237         self.labels[label] = label   238         self.label_number += 1   239         return label   240    241     def set_label(self, label):   242    243         """   244         Set the location of 'label' to that within the entire image: the   245         location within the code combined with location of the code unit.   246         """   247    248         label.location = len(self.code) + self.unit.code_location   249    250     def get_loop_labels(self):   251         return self.loop_labels[-1]   252    253     def add_loop_labels(self, next_label, exit_label):   254         self.loop_labels.append((next_label, exit_label))   255    256     def drop_loop_labels(self):   257         self.loop_labels.pop()   258    259     def get_exception_labels(self):   260         return self.exception_labels[-1]   261    262     def add_exception_labels(self, handler_label, exit_label):   263         self.exception_labels.append((handler_label, exit_label))   264    265     def drop_exception_labels(self):   266         self.exception_labels.pop()   267    268     # Assignment expression values.   269    270     def record_value(self):   271         self.expr_temp = self._optimise_temp_storage()   272         self.active_source = self.active   273    274     def discard_value(self):   275         self.discard_temp(self.expr_temp)   276         self.expr_temp = None   277         self.active_source = None   278    279     def set_source(self):   280         if self.active is not None:   281             self.active.source = self.expr_temp   282    283         # Optimise away constant storage if appropriate.   284    285         self._optimise_constant_storage()   286    287     # Temporary storage administration.   288    289     def get_temp(self):   290    291         """   292         Add a temporary storage instruction for the current value and return a   293         sequence of access instructions.   294         """   295    296         position_in_frame = self.reserve_temp()   297         self.new_op(StoreTemp(position_in_frame))   298         return LoadTemp(position_in_frame)   299    300     def reserve_temp(self):   301         if not self.temp_positions:   302             temp_position = 0   303         else:   304             temp_position = max(self.temp_positions)   305         self.temp_positions.add(temp_position)   306         self.max_temp_position = max(self.max_temp_position, temp_position)   307         return self.unit.all_local_usage + temp_position # position in frame   308    309     def discard_temp(self, instruction=None):   310         if isinstance(instruction, LoadTemp):   311             temp_position = instruction.attr - self.unit.all_local_usage   312             self.free_temp(temp_position)   313    314     def free_temp(self, temp_position):   315         if temp_position in self.temp_positions:   316             self.temp_positions.remove(temp_position)   317    318     def set_frame_usage(self, node, extend):   319         extend.attr = self.max_temp_position + node.unit.local_usage # NOTE: See get_code for similar code.   320    321     # Code writing methods.   322    323     def new_op(self, op):   324    325         "Add 'op' to the generated code."   326    327         # Optimise load operations employed by this instruction.   328    329         self._optimise_load_operations(op)   330         if self._optimise_away_no_operations(op):   331             return   332    333         self.code.append(op)   334         self.active = op   335    336         # Record specific types of instructions for optimisation.   337    338         if isinstance(op, self.current_value_instructions):   339             self.active_value = op   340    341     def remove_op(self):   342    343         "Remove the last instruction."   344    345         op = self.code.pop()   346         self.active = None   347    348     def remove_active_value(self):   349    350         "Remove the value-providing active instruction if appropriate."   351    352         if self.active_value is self.active:   353             self.remove_op()   354    355     def replace_op(self, op):   356    357         "Replace the last added instruction with 'op'."   358    359         self.remove_op()   360         self.new_op(op)   361    362     def replace_active_value(self, op):   363    364         """   365         Replace the value-providing active instruction with 'op' if appropriate.   366         """   367    368         self.remove_active_value()   369         self.new_op(op)   370    371     def last_op(self):   372    373         "Return the last added instruction."   374    375         try:   376             return self.code[-1]   377         except IndexError:   378             return None   379    380     def clear_active(self):   381    382         "Prevent incorrect optimisation."   383    384         self.active = None   385         self.active_value = None   386         self.active_source = None   387    388     # Optimisation tests.   389    390     def _should_optimise_constant_storage(self):   391         return "constant_storage" in self.optimisations   392    393     def _should_optimise_source_storage(self):   394         return "source_storage" in self.optimisations   395    396     def _should_optimise_known_target(self):   397         return "known_target" in self.optimisations   398    399     def _should_optimise_self_access(self):   400         return "self_access" in self.optimisations   401    402     def _should_optimise_temp_storage(self):   403         return "temp_storage" in self.optimisations   404    405     def _should_optimise_load_operations(self):   406         return "load_operations" in self.optimisations   407    408     def _should_optimise_away_no_operations(self):   409         return "no_operations" in self.optimisations   410    411     def _should_optimise_unused_results(self):   412         return "unused_results" in self.optimisations   413    414     # Simple tests.   415    416     def _is_constant_input(self, instruction):   417    418         "Return whether 'instruction' provides a constant input."   419    420         return isinstance(instruction, LoadAddress) and instruction.attr.assignments == 1 or \   421             isinstance(instruction, LoadConst)   422    423     def _is_constant_target(self, instruction):   424    425         "Return whether 'instruction' provides a constant target."   426    427         return isinstance(instruction, (StoreName, StoreAddress)) and \   428             instruction.attr.assignments == 1   429    430     def _is_simple_input(self, instruction):   431    432         """   433         Return whether 'instruction' provides a simple input (typically a load   434         instruction).   435         """   436    437         return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult, LoadAddress))   438    439     def _is_simple_input_user(self, instruction):   440    441         "Return whether 'instruction' can use simple input from the current value."   442    443         return isinstance(instruction, (   444             StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored   445             LoadAddressContext, LoadAttr, LoadAttrIndex,        # as the object being referenced   446             StoreAttr, StoreAttrIndex, StoreCallable,           # as the object being referenced   447             LoadCallable,   448             TestIdentity, TestIdentityAddress, CheckSelf,       # as one of the operands   449             CheckFrame, MakeObject,   450             LoadContext                                         # as the object providing the result   451             ))   452    453     def _is_resultant_no_operation(self, instruction):   454    455         """   456         Return whether 'instruction' merely stores its input where the input   457         originally came from.   458         """   459    460         return (   461             isinstance(instruction.input, LoadTemp) and isinstance(instruction, StoreTemp) and   462                 instruction.input.attr == instruction.attr) or (   463             isinstance(instruction.input, LoadResult) and isinstance(instruction, StoreResult)   464             )   465    466     def _is_input(self, instruction):   467    468         "Return whether 'instruction' provides an input."   469    470         return isinstance(instruction, self.current_value_instructions)   471    472     # Convenience tests on outputs.   473    474     def _have_constant_target(self):   475    476         "Return whether the active instruction provides a constant target."   477    478         return self._is_constant_target(self.active)   479    480     def _have_constant_source(self):   481    482         "Return whether the active instruction has a constant source."   483    484         return self._is_constant_input(self.active.source)   485    486     # Convenience tests on inputs.   487    488     def _have_constant_input(self):   489    490         "Return whether the active instruction provides a constant input."   491    492         return self._is_constant_input(self.active_value)   493    494     _have_known_target = _have_constant_input   495    496     def _have_simple_input(self):   497    498         "Return whether the active instruction provides a simple input."   499    500         return self._is_simple_input(self.active_value)   501    502     def _have_input(self):   503    504         "Return whether the active instruction provides an input."   505    506         return self._is_input(self.active_value)   507    508     def _have_self_input(self):   509    510         "Return whether the active instruction is a reference to self."   511    512         return isinstance(self.unit, Function) and \   513             self.unit.is_method() and isinstance(self.active_value, LoadName) and \   514             self.active_value.attr.name == "self"   515    516     def _have_temp_compatible_access(self):   517    518         """   519         Indicate whether the active instruction can be used in place of access   520         to a temporary variable retaining the result of the last instruction.   521         """   522    523         # LoadResult cannot be relied upon in general since the result register   524         # could be updated since first being referenced.   525    526         return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst)) or \   527             isinstance(self.active_value, LoadResult) and self.active_value is self.active   528    529     def _have_correct_self_for_target(self, context):   530    531         "Return whether the 'context' is compatible with the current value."   532    533         if context is not None and self._have_self_input():   534    535             parent = self.unit.parent   536             if parent is context or parent.has_subclass(context) or context.has_subclass(parent):   537                 return 1   538    539         return 0   540    541     # Optimisation methods. See the supported_optimisations class attribute.   542    543     def _optimise_constant_storage(self):   544    545         """   546         Where the last operation stores a constant into a target which is also   547         constant, optimise away both operations.   548         """   549    550         if self._should_optimise_constant_storage() and \   551             self._have_constant_target() and \   552             self._have_constant_source():   553    554             self.remove_op()   555             return 1   556         else:   557             return 0   558    559     def _optimise_source_storage(self):   560    561         """   562         Where the source value in an assignment can be inserted into the   563         eventual target without intermediate storage, optimise away the storage   564         instruction.   565         """   566    567         if self._should_optimise_source_storage() and \   568             self.active_source is not None and \   569             self.active_source.source is None and \   570             self.active_source.input is None and \   571             self.active_source is self.active:   572    573             self.remove_op()   574             return 1   575         else:   576             return 0   577    578     def _optimise_known_target(self):   579    580         """   581         Where the target of an invocation is known, provide information about it   582         and its context. If a class is being invoked and the conditions are   583         appropriate, get information about the specific initialiser.   584         """   585    586         if self._should_optimise_known_target() and self._have_known_target():   587             last = self.active_value   588             target = last.attr.value   589             context = last.attr.context   590    591             return target, context   592         else:   593             return None   594    595     def _optimise_self_access(self, attrname, classes, node):   596    597         """   598         Where the provided 'attrname' accesses an attribute which occupies the   599         same position in all possible objects which can be accessed, generate an   600         instruction using one of the given 'classes', accessing the attribute   601         directly.   602         """   603    604         AddressInstruction, AddressContextInstruction, AttrInstruction = classes   605    606         if self._should_optimise_self_access() and self._have_self_input() and \   607             not self.unit.is_relocated(attrname):   608    609             # Either generate an instruction operating on an instance attribute.   610    611             try:   612                 attr = self.unit.parent.instance_attributes()[attrname]   613                 self.new_op(AttrInstruction(attr))   614    615             # Or generate an instruction operating on a class attribute.   616    617             except KeyError:   618                 attr = self.unit.parent.all_attributes()[attrname]   619    620                 # Switch the context if the class attribute is compatible with   621                 # the instance.   622    623                 if attr.defined_within_hierarchy():   624    625                     # Only permit loading (not storing) of class attributes via self.   626    627                     if AddressContextInstruction is not None:   628                         self.new_op(AddressContextInstruction(attr))   629                     else:   630                         raise TranslateError(self.module.full_name(), node,   631                             "Storing of class attribute %r via self not permitted." % attrname)   632    633                 # Preserve the context if the class attribute comes from an   634                 # incompatible class.   635    636                 else:   637                     if AddressInstruction is not None:   638                         self.new_op(AddressInstruction(attr))   639                     else:   640                         raise TranslateError(self.module.full_name(), node,   641                             "Storing of class attribute %r via self not permitted." % attrname)   642    643             return 1   644         else:   645             return 0   646    647     def _optimise_temp_storage(self):   648    649         """   650         Where the next operation would involve storing a value into temporary   651         storage at 'temp_position', record and remove any simple instruction   652         which produced the value to be stored such that instead of subsequently   653         accessing the temporary storage, that instruction is substituted.   654    655         If no optimisation can be achieved, a StoreTemp instruction is produced   656         and the appropriate LoadTemp instruction is returned.   657    658         Restriction: for use only in situations where the source of the   659         temporary data will not be disturbed between its first access and its   660         subsequent use.   661         """   662    663         if self._should_optimise_temp_storage() and \   664             self._have_temp_compatible_access():   665    666             removed = self.active   667             self.remove_active_value()   668             return removed   669         else:   670             return self.get_temp()   671    672     def _optimise_load_operations(self, instruction):   673    674         """   675         Incorporate previous load operations into other operations.   676         """   677    678         if self._should_optimise_load_operations() and \   679             self._have_simple_input() and \   680             self._is_simple_input_user(instruction):   681    682             self.remove_active_value()   683             instruction.input = self.active_value   684    685     def _optimise_away_no_operations(self, instruction):   686    687         """   688         Optimise away operations which just store their inputs in the place   689         the inputs originally came from.   690         """   691    692         if self._should_optimise_away_no_operations() and \   693             self._is_resultant_no_operation(instruction):   694    695             return 1   696         else:   697             return 0   698    699     def _optimise_unused_results(self):   700    701         "Discard results which will not be used."   702    703         if self._have_simple_input():   704             self.remove_active_value()   705    706     # Visitor methods.   707    708     def default(self, node, *args):   709         raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__)   710    711     def dispatch(self, node, *args):   712         return ASTVisitor.dispatch(self, node, *args)   713    714     # Internal helper methods.   715    716     def _visitAttr(self, node, classes):   717    718         """   719         Visit the attribute-related 'node', generating instructions based on the   720         given 'classes'.   721         """   722    723         self.dispatch(node.expr)   724         self._generateAttr(node, node.attrname, classes)   725    726     def _generateAttr(self, node, attrname, classes):   727    728         """   729         Generate code for the access to 'attrname' using the given 'classes'.   730         """   731    732         AddressInstruction, AddressContextInstruction, AttrInstruction, AttrIndexInstruction = classes   733    734         # Where the last operation (defining the attribute owner) yields a   735         # constant...   736    737         if self._have_constant_input():   738             last = self.active_value   739    740             # Get the details of the access.   741    742             if isinstance(last.attr, Const):   743                 target_name = last.attr.value_type_name()   744             else:   745                 target = last.attr.value   746    747                 if isinstance(target, Const):   748                     target_name = target.value_type_name()   749                 elif isinstance(target, Instance):   750                     target_name = None # skip production of optimised code   751                 else:   752                     target_name = target.full_name()   753    754             # Only try and discover the position if the target can be resolved.   755    756             if target_name is not None:   757    758                 # Access the object table to get the attribute position.   759    760                 try:   761                     table_entry = self.objtable.table[target_name]   762                 except KeyError:   763                     raise TranslateError(self.module.full_name(), node,   764                         "No object entry exists for target %r." % target_name)   765    766                 try:   767                     pos = table_entry[attrname]   768                 except KeyError:   769                     raise TranslateError(self.module.full_name(), node,   770                         "No attribute entry exists for name %r in target %r." % (attrname, target_name))   771    772                 # Produce a suitable instruction.   773    774                 if AddressInstruction is not None:   775                     self.replace_active_value(AddressInstruction(pos))   776                 else:   777                     raise TranslateError(self.module.full_name(), node,   778                         "Storing of class or module attribute %r via an object is not permitted." % attrname)   779    780                 return   781    782         # Where the last operation involves the special 'self' name, check to   783         # see if the attribute is acceptably positioned and produce a direct   784         # access to the attribute.   785    786         elif self._optimise_self_access(attrname, (AddressInstruction, AddressContextInstruction, AttrInstruction), node):   787             return   788    789         # Otherwise, perform a normal operation.   790    791         try:   792             index = self.objtable.get_index(attrname)   793         except self.objtable.TableError:   794             raise TranslateError(self.module.full_name(), node,   795                 "No attribute entry exists for name %r." % attrname)   796    797         self.new_op(AttrIndexInstruction(index))   798    799     # Invocations involve the following:   800     #   801     # 1. Reservation of a frame for the arguments   802     # 2. Identification of the target which is then held in temporary storage   803     # 3. Optional inclusion of a context (important for methods)   804     # 4. Preparation of the argument frame   805     # 5. Invocation of the target   806     # 6. Discarding of the frame   807     #   808     # In order to support nested invocations - eg. a(b(c)) - use of the   809     # temporary storage is essential.   810    811     def _startCallFunc(self):   812    813         "Record the location of the invocation."   814    815         op = MakeFrame()   816         self.new_op(op) # records the start of the frame   817         self.frame_makers.append(op)   818    819     def _generateCallFunc(self, args, node):   820    821         """   822         Support a generic function invocation using the given 'args', occurring   823         on the given 'node', where the expression providing the invocation   824         target has just been generated.   825    826         In other situations, the invocation is much simpler and does not need to   827         handle the full flexibility of a typical Python invocation. Internal   828         invocations, such as those employed by operators and certain   829         control-flow mechanisms, use predetermined arguments and arguably do not   830         need to support the same things as the more general invocations.   831         """   832    833         target, context, temp = self._generateCallFuncContext()   834         self._generateCallFuncArgs(target, context, temp, args, node)   835         return temp, target   836    837     def _generateCallFuncContext(self):   838    839         """   840         Produce code which loads and checks the context of the current   841         invocation, the instructions for whose target have already been   842         produced, returning a list of instructions which reference the   843         invocation target.   844         """   845    846         t = self._optimise_known_target()   847         if t:   848             target, context = t   849         else:   850             target, context = None, None   851    852         # Store the target in temporary storage for subsequent referencing.   853         # NOTE: This may not be appropriate for class invocations   854         # NOTE: (instantiation).   855    856         temp = self._optimise_temp_storage()   857    858         # Where a target or context are not known or where an instance is known   859         # to be the context, load the context.   860    861         if target is None or isinstance(context, Instance):   862             self.new_op(temp)   863             self.new_op(LoadContext())   864             self.new_op(StoreFrame(0))   865    866         # For known instantiations, provide a new object as the first argument   867         # to the __init__ method.   868    869         elif isinstance(target, Class):   870             self.make_object(target, len(target.instance_attributes()))   871             self.new_op(StoreFrame(0))   872    873         # Otherwise omit the context.   874    875         else:   876             pass # NOTE: Class methods should be supported.   877    878         return target, context, temp   879    880     def _generateCallFuncArgs(self, target, context, temp, args, node):   881    882         """   883         Given invocation 'target' and 'context' information, the 'temp'   884         reference to the target, a list of nodes representing the 'args'   885         (arguments), generate instructions which load the arguments for the   886         invocation defined by the given 'node'.   887         """   888    889         # Evaluate the arguments.   890    891         employed_positions = set()   892         employed_keywords = set()   893         extra_keywords = []   894    895         # Find keyword arguments in advance in order to help resolve targets.   896    897         for arg in args:   898             if isinstance(arg, compiler.ast.Keyword):   899                 employed_keywords.add(arg.name)   900    901         possible_targets = self.paramtable.all_possible_objects(employed_keywords)   902    903         # Note the presence of the context in the frame where appropriate.   904    905         if target is None or isinstance(context, Instance):   906             ncontext = 1   907             expect_context = 0   908    909         # Handle calls to classes.   910    911         elif isinstance(target, Class):   912             ncontext = 1   913             expect_context = 0   914             target = target.get_init_method()   915    916         # Method calls via classes.   917    918         elif isinstance(context, Class):   919             ncontext = 0   920             expect_context = 1   921    922         # Function calls.   923    924         else:   925             ncontext = 0   926             expect_context = 0   927    928         first = 1   929         frame_pos = ncontext   930         max_keyword_pos = -1   931    932         for arg in args:   933    934             # Handle positional and keyword arguments separately.   935    936             if isinstance(arg, compiler.ast.Keyword):   937    938                 # Optimise where the target is known now.   939    940                 if target is not None:   941    942                     # Find the parameter table entry for the target.   943    944                     target_name = target.full_name()   945    946                     # Look for a callable with the precise target name.   947    948                     table_entry = self.paramtable.table[target_name]   949    950                     # Look the name up in the parameter table entry.   951    952                     try:   953                         pos = table_entry[arg.name]   954    955                     # Where no position is found, this could be an extra keyword   956                     # argument.   957    958                     except KeyError:   959                         extra_keywords.append(arg)   960                         continue   961    962                     # Test for illegal conditions.   963    964                     if pos in employed_positions:   965                         raise TranslateError(self.module.full_name(), node,   966                             "Keyword argument %r overwrites parameter %r." % (arg.name, pos))   967    968                     employed_positions.add(pos)   969    970                     # Generate code for the keyword and the positioning   971                     # operation.   972    973                     self.dispatch(arg.expr)   974                     self.new_op(StoreFrame(pos))   975    976                 # Otherwise, generate the code needed to obtain the details of   977                 # the parameter location.   978    979                 else:   980    981                     # Combine the target details with the name to get the location.   982                     # See the access method on the List class.   983    984                     try:   985                         paramindex = self.paramtable.get_index(arg.name)   986    987                     # Where no position is found, this could be an extra keyword   988                     # argument.   989    990                     except self.paramtable.TableError:   991                         extra_keywords.append(arg)   992                         continue   993    994                     # Generate code for the keyword and the positioning   995                     # operation.   996    997                     self.dispatch(arg.expr)   998                     self.new_op(StoreFrameIndex(paramindex))   999   1000                     # use (callable+0)+paramindex+table  1001                     # checks embedded offset against (callable+0)  1002                     # moves the current value to frame+position  1003   1004                     # Record the highest possible frame position for this argument.  1005   1006                     max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name)))  1007   1008             else:  1009                 self.dispatch(arg)  1010                 self.new_op(StoreFrame(frame_pos))  1011   1012                 employed_positions.add(frame_pos)  1013   1014             # Check to see if the first argument is appropriate (compatible with  1015             # the target where methods are being invoked via classes).  1016   1017             if first and expect_context:  1018   1019                 # Drop any test if the target and the context are known.  1020   1021                 if not self._have_correct_self_for_target(context):  1022   1023                     continue_label = self.new_label()  1024                     self.new_op(CheckSelf())  1025                     self.active.source = temp  1026                     self.new_op(JumpIfTrue(continue_label))  1027   1028                     # Where the context is inappropriate, drop the incomplete frame and  1029                     # raise an exception.  1030   1031                     self.new_op(DropFrame())  1032                     self.new_op(LoadResult())  1033   1034                     self.load_builtin("TypeError", node)  1035                     self.new_op(StoreException())  1036                     self.new_op(RaiseException())  1037                     self.set_label(continue_label)  1038   1039             first = 0  1040             frame_pos += 1  1041   1042         # NOTE: Extra keywords are not supported.  1043         # NOTE: Somehow, the above needs to be combined with * arguments.  1044   1045         if extra_keywords:  1046             print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords])  1047   1048         # Either test for a complete set of arguments.  1049   1050         if target is not None:  1051   1052             # Make sure that enough arguments have been given.  1053   1054             nargs_max = len(target.positional_names)  1055             ndefaults = len(target.defaults)  1056             nargs_min = nargs_max - ndefaults  1057   1058             for i in range(ncontext, nargs_min):  1059                 if i not in employed_positions:  1060                     raise TranslateError(self.module.full_name(), node,  1061                         "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min))  1062   1063             nargs = frame_pos  1064   1065             if nargs > nargs_max and not target.has_star and not target.has_dstar:  1066                 raise TranslateError(self.module.full_name(), node,  1067                     "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max))  1068   1069             # Where defaults are involved, put them into the frame.  1070   1071             self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions)  1072   1073             # Set the frame size.  1074   1075             self._endCallFuncArgs(nargs_max)  1076   1077         # Or generate instructions to do this at run-time.  1078         # NOTE: CheckFrame has to check the number of arguments and to fill in  1079         # NOTE: defaults; it also has to shift the invocation frame according to  1080         # NOTE: the context in use.  1081   1082         else:  1083             max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1)  1084   1085             # Only check non-empty frames (using the callable's details).  1086   1087             if employed_positions or max_pos >= 0:  1088                 self.new_op(temp)  1089                 self.new_op(CheckFrame(max_pos + 1))  1090   1091             # Set the frame size.  1092   1093             self._endCallFuncArgs(max_pos + 1)  1094   1095     def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions):  1096   1097         """  1098         For the given 'target' and 'temp' reference to the target, generate  1099         default arguments for those positions in the range 'nargs_min'...  1100         'nargs_max' which are not present in the 'employed_positions'  1101         collection.  1102         """  1103   1104         # Where a lambda is involved, construct a dynamic object to hold the  1105         # defaults.  1106   1107         dynamic = target.name is None  1108   1109         # Here, we use negative index values to visit the right hand end of  1110         # the defaults list.  1111   1112         for pos in range(nargs_min, nargs_max):  1113             if pos not in employed_positions:  1114                 if dynamic:  1115                     self.new_op(temp)  1116                     self.new_op(LoadAttr(target.default_attrs[pos - nargs_min]))  1117                 else:  1118                     self.new_op(LoadAddress(target.default_attrs[pos - nargs_min]))  1119                 self.new_op(StoreFrame(pos))  1120   1121     def _doCallFunc(self, instruction, target=None):  1122   1123         "Make the invocation."  1124   1125         if isinstance(target, Class):  1126             self.new_op(LoadConst(target.get_init_method()))  1127         else:  1128             self.new_op(instruction)  1129         self.new_op(LoadCallable())  1130         self.new_op(JumpWithFrame())  1131   1132     def _endCallFuncArgs(self, nargs):  1133   1134         "Set the frame size."  1135   1136         self.frame_makers[-1].attr = nargs  1137         self.frame_makers.pop()  1138   1139     def _endCallFunc(self, instruction=None, target=None, load_result=1):  1140   1141         "Finish the invocation and tidy up afterwards."  1142   1143         if isinstance(target, Class):  1144             self.new_op(LoadName(target.get_init_method().all_locals()["self"])) # load the context in the invocation frame  1145             self.new_op(StoreResult())  1146         self.new_op(DropFrame())  1147         if load_result:  1148             self.new_op(LoadResult())  1149   1150         # Discard any temporary storage instructions.  1151   1152         if instruction is not None:  1153             self.discard_temp(instruction)  1154   1155     def _generateFunctionDefaults(self, function):  1156   1157         """  1158         Generate the default initialisation code for 'function', returning  1159         a temporary storage reference if a dynamic object was created for the  1160         function.  1161         """  1162   1163         attr_to_default = zip(function.default_attrs, function.defaults)  1164         if not attr_to_default:  1165             return None  1166   1167         # Where a lambda is involved, construct a dynamic object to hold the  1168         # defaults.  1169   1170         dynamic = function.name is None  1171   1172         if dynamic:  1173             self.make_object(self.get_builtin_class("function", function), len(attr_to_default))  1174             temp = self.get_temp()  1175   1176         for attr, default in attr_to_default:  1177             self.dispatch(default)  1178   1179             self.record_value()  1180             if dynamic:  1181                 self.new_op(temp)  1182                 self.new_op(StoreAttr(attr))  1183             else:  1184                 self.new_op(StoreAddress(attr))  1185             self.set_source()  1186             self.discard_value()  1187   1188         if dynamic:  1189             return temp  1190         else:  1191             return None  1192   1193     def _visitName(self, node, classes):  1194   1195         """  1196         Visit the name-related 'node', generating instructions based on the  1197         given 'classes'.  1198         """  1199   1200         name = node.name  1201         scope = self.get_scope(name)  1202         #print self.module.name, node.lineno, name, scope  1203         self._generateName(name, scope, classes, node)  1204   1205     def _generateName(self, name, scope, classes, node):  1206   1207         """  1208         Generate code for the access to 'name' in 'scope' using the given  1209         'classes', and using the given 'node' as the source of the access.  1210         """  1211   1212         NameInstruction, AddressInstruction = classes  1213   1214         if scope == "local":  1215             unit = self.unit  1216             if isinstance(unit, Function):  1217                 self.new_op(NameInstruction(unit.all_locals()[name]))  1218             elif isinstance(unit, Class):  1219                 self.new_op(AddressInstruction(unit.all_class_attributes()[name]))  1220             elif isinstance(unit, Module):  1221                 self.new_op(AddressInstruction(unit.module_attributes()[name]))  1222             else:  1223                 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name))  1224   1225         elif scope == "global":  1226             globals = self.module.module_attributes()  1227             if globals.has_key(name):  1228                 self.new_op(AddressInstruction(globals[name]))  1229             else:  1230                 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name))  1231   1232         else:  1233             self.new_op(AddressInstruction(self.get_builtin(name, node)))  1234   1235     def _visitUnary(self, node, method):  1236   1237         """  1238         _t = node.expr  1239         try:  1240             _result = _t.__pos__()  1241         except AttributeError:  1242             raise TypeError  1243         """  1244   1245         end_call_label = self.new_label()  1246         end_label = self.new_label()  1247   1248         # Evaluate and store the operand in temporary storage.  1249   1250         self.dispatch(node.expr)  1251         temp = self._optimise_temp_storage()  1252   1253         # Produce the invocation.  1254   1255         self._startCallFunc()  1256         self.new_op(temp)  1257   1258         # Get the method on temp.  1259   1260         self._generateAttr(node, method, self.attribute_load_instructions)  1261         temp_method = self._optimise_temp_storage()  1262   1263         self._handleAttributeError(node, end_call_label)  1264   1265         # Add arguments.  1266         # NOTE: No support for defaults.  1267   1268         self.new_op(temp) # Explicit context as first argument.  1269         self.new_op(StoreFrame(0))  1270         self._endCallFuncArgs(1)  1271         self._doCallFunc(temp_method)  1272         self._endCallFunc(temp_method)  1273         self.new_op(Jump(end_label))  1274   1275         # End method attempt.  1276   1277         self.set_label(end_call_label)  1278         self._endCallFunc() # From the method call.  1279   1280         # Raise a TypeError.  1281   1282         self.load_builtin("TypeError", node)  1283         self.new_op(StoreException())  1284         self.new_op(RaiseException())  1285   1286         self.set_label(end_label)  1287   1288         # Compilation duties...  1289   1290         self.discard_temp(temp)  1291   1292     def _visitBinary(self, node, left_method, right_method):  1293   1294         """  1295         _t1 = node.left  1296         _t2 = node.right  1297         try:  1298             _result = _t1.__add__(_t2)  1299             if _result is NotImplemented:  1300                 raise AttributeError  1301         except AttributeError:  1302             try:  1303                 _result = _t2.__radd__(_t1)  1304                 if _result is NotImplemented:  1305                     raise AttributeError  1306             except AttributeError:  1307                 raise TypeError  1308         """  1309   1310         # Evaluate and store the left operand in temporary storage.  1311   1312         self.dispatch(node.left)  1313         temp1 = self._optimise_temp_storage()  1314   1315         # Evaluate and store the right operand in temporary storage.  1316   1317         self.dispatch(node.right)  1318         temp2 = self._optimise_temp_storage()  1319   1320         self._generateBinary(node, temp1, temp2, left_method, right_method)  1321   1322         # Compilation duties...  1323   1324         self.discard_temp(temp1)  1325         self.discard_temp(temp2)  1326   1327     def _generateBinary(self, node, temp1, temp2, left_method, right_method):  1328   1329         """  1330         For the given 'node', generate the binary operator pattern for the  1331         operands 'temp1' and 'temp2', employing 'left_method' and 'right_method'  1332         as defined for binary operators, but also used in comparisons (for which  1333         this method is provided).  1334         """  1335   1336         right_label = self.new_label()  1337         type_error_label = self.new_label()  1338         end_label = self.new_label()  1339   1340         # Left method.  1341   1342         self._generateOpMethod(node, temp1, temp2, left_method, right_label, end_label)  1343   1344         # Right method.  1345   1346         self.set_label(right_label)  1347         self._generateOpMethod(node, temp2, temp1, right_method, type_error_label, end_label)  1348   1349         # Raise a TypeError.  1350   1351         self.set_label(type_error_label)  1352         self.load_builtin("TypeError", node)  1353         self.new_op(StoreException())  1354         self.new_op(RaiseException())  1355   1356         self.set_label(end_label)  1357   1358     def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_label, end_label):  1359   1360         """  1361         For the given 'node', generate the operator method invocation using the  1362         operands 'temp1' and 'temp2', employing the given 'method_name', and  1363         jumping appropriately to 'next_method_label' where a NotImplemented  1364         result is returned, or to 'end_label' if the method call was successful.  1365         """  1366   1367         end_attempt_label = self.new_label()  1368   1369         self.new_op(temp1)  1370   1371         # Get method on temp1.  1372   1373         self._generateAttr(node, method_name, self.attribute_load_instructions)  1374         temp_method = self._optimise_temp_storage()  1375   1376         self._handleAttributeError(node, end_attempt_label)  1377   1378         # Add arguments.  1379         # NOTE: No support for defaults.  1380   1381         self._startCallFunc()  1382         self.new_op(temp1)  1383         self.new_op(StoreFrame(0))  1384         self.new_op(temp2)  1385         self.new_op(StoreFrame(1))  1386         self._endCallFuncArgs(2)  1387         self._doCallFunc(temp_method)  1388         self._endCallFunc(temp_method)  1389   1390         # Test for NotImplemented.  1391         # Don't actually raise an exception.  1392   1393         self.new_op(TestIdentityAddress(self.get_builtin("NotImplemented", node)))  1394         self.new_op(JumpIfTrue(next_method_label))  1395         self.new_op(Jump(end_label))  1396   1397         # End method attempt.  1398   1399         self.set_label(end_attempt_label)  1400   1401     def _handleAttributeError(self, node, end_call_label):  1402   1403         """  1404         Add exception handling to the method acquisition instructions where the  1405         attribute access cannot be resolved at compile-time.  1406         """  1407   1408         if not self._optimise_known_target():  1409             self.load_builtin("AttributeError", node)  1410             self.new_op(CheckException())  1411             self.new_op(JumpIfTrue(end_call_label))  1412   1413     def _generateSequence(self, sequence_type, node):  1414   1415         "Make a sequence of 'sequence_type' for the given program 'node'."  1416   1417         self.make_object(self.get_builtin(sequence_type, node), len(node.nodes))  1418         temp = self.get_temp()  1419   1420         for i, n in enumerate(node.nodes):  1421             self.dispatch(n)  1422             self.record_value()  1423             self.new_op(temp)  1424             self.new_op(StoreAttr(Attr(i, None, None, None)))  1425             self.set_source()  1426             self.discard_value()  1427   1428         self.new_op(temp)  1429         self.discard_temp(temp)  1430   1431     def _generateTestBoolean(self, node, temp):  1432   1433         """  1434         Generate a test of the boolean status of the current value for the given  1435         program 'node'.  1436         """  1437   1438         # Get method on temp.  1439         # NOTE: Using __bool__ instead of __nonzero__.  1440   1441         self._generateAttr(node, "__bool__", self.attribute_load_instructions)  1442         temp_method = self._optimise_temp_storage()  1443   1444         self._startCallFunc()  1445         self.new_op(temp)  1446         self.new_op(StoreFrame(0))  1447         self._endCallFuncArgs(1)  1448         self._doCallFunc(temp_method)  1449         self._endCallFunc(temp_method)  1450   1451         self.discard_temp(temp_method)  1452   1453         # Convert result to boolean (a StoreBoolean operation).  1454   1455         self.new_op(TestIdentityAddress(self.get_builtin("True", node)))  1456   1457     def _generateLoadBoolean(self, node):  1458   1459         """  1460         Generate instructions to load the appropriate value given the current  1461         boolean status.  1462         """  1463   1464         true_label = self.new_label()  1465         end_label = self.new_label()  1466   1467         self.new_op(JumpIfTrue(true_label))  1468         self.load_builtin("False", node)  1469         self.new_op(Jump(end_label))  1470   1471         self.set_label(true_label)  1472         self.load_builtin("True", node)  1473   1474         self.set_label(end_label)  1475   1476     # Concrete visitor methods.  1477   1478     def visitAdd(self, node):  1479         self._visitBinary(node, "__add__", "__radd__")  1480   1481     def visitAnd(self, node):  1482         end_label = self.new_label()  1483         temp_pos = self.reserve_temp()  1484         temp = LoadTemp(temp_pos)  1485   1486         for n in node.nodes[:-1]:  1487             self.dispatch(n)  1488             self.new_op(StoreTemp(temp_pos))  1489   1490             self._generateTestBoolean(n, temp)  1491             self.new_op(JumpIfFalse(end_label))  1492   1493         self.dispatch(node.nodes[-1])  1494         self.new_op(StoreTemp(temp_pos))  1495   1496         self.set_label(end_label)  1497   1498         # Prevent incorrect optimisation.  1499   1500         self.clear_active()  1501   1502         self.new_op(temp)  1503         self.discard_temp(temp)  1504   1505     def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert")  1506   1507     def visitAssign(self, node):  1508         self.dispatch(node.expr)  1509         self.record_value()  1510   1511         for n in node.nodes:  1512             self.dispatch(n)  1513   1514         self.discard_value()  1515   1516     def visitAssAttr(self, node):  1517         self._visitAttr(node, self.attribute_store_instructions)  1518         self.set_source()  1519   1520     def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList")  1521   1522     def visitAssName(self, node):  1523   1524         # Optimise away intermediate source storage.  1525   1526         no_source = self._optimise_source_storage()  1527         self._visitName(node, self.name_store_instructions)  1528         if not no_source:  1529             self.set_source()  1530   1531     visitAssTuple = visitAssList  1532   1533     def visitAugAssign(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign")  1534   1535     def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote")  1536   1537     def visitBitand(self, node):  1538         self._visitBinary(node, "__and__", "__rand__")  1539   1540     def visitBitor(self, node):  1541         self._visitBinary(node, "__or__", "__ror__")  1542   1543     def visitBitxor(self, node):  1544         self._visitBinary(node, "__xor__", "__rxor__")  1545   1546     def visitBreak(self, node):  1547         next_label, exit_label = self.get_loop_labels()  1548         self.new_op(Jump(exit_label))  1549   1550     def visitCallFunc(self, node):  1551   1552         """  1553         Evaluate positional arguments, evaluate and store keyword arguments in  1554         the correct location, then invoke the function.  1555         """  1556   1557         # Mark the frame, evaluate the target, generate the call.  1558   1559         self._startCallFunc()  1560         self.dispatch(node.node)  1561         temp, target = self._generateCallFunc(node.args, node)  1562         self._doCallFunc(temp, target)  1563         self._endCallFunc(temp, target)  1564   1565     def visitClass(self, node):  1566   1567         # Store the name.  1568   1569         self.new_op(LoadConst(node.unit))  1570         self.record_value()  1571         self._visitName(node, self.name_store_instructions)  1572         self.set_source()  1573         self.discard_value()  1574   1575         # Visit the code.  1576   1577         unit = self.unit  1578         self.unit = node.unit  1579         self.unit.code_location = self.module.code_location # class body code is not independently addressable  1580         self.dispatch(node.code)  1581         self.unit = unit  1582   1583     def visitCompare(self, node):  1584   1585         """  1586         _t1 = node.expr  1587         _t1 op1 _t2 and _t2 op2 _t3 and ...  1588         """  1589   1590         end_label = self.new_label()  1591         temp_pos = self.reserve_temp()  1592         temp_result = LoadTemp(temp_pos)  1593   1594         self.dispatch(node.expr)  1595         temp2 = self._optimise_temp_storage()  1596   1597         last_op = node.ops[-1]  1598   1599         for op in node.ops:  1600             op_name, next_node = op  1601             methods = self.comparison_methods[op_name]  1602   1603             temp1 = temp2  1604             self.dispatch(next_node)  1605             temp2 = self._optimise_temp_storage()  1606   1607             # Use the appropriate mechanism, setting the boolean status for the  1608             # comparison.  1609   1610             if methods is not None:  1611                 left_method, right_method = methods  1612   1613                 # Generate method call using evaluated argument and next node.  1614   1615                 self._generateBinary(node, temp1, temp2, left_method, right_method)  1616                 self.new_op(StoreTemp(temp_pos))  1617                 self._generateTestBoolean(node, temp_result)  1618   1619             else:  1620                 # Deal with the special operators.  1621   1622                 if op_name.startswith("is"):  1623                     self.new_op(temp1)  1624                     self.record_value()  1625                     self.new_op(temp2)  1626                     self.new_op(TestIdentity())  1627                     self.set_source()  1628                     self.discard_value()  1629   1630                 elif op_name.endswith("in"):  1631                     self._startCallFunc()  1632                     self.new_op(temp2)  1633   1634                     # Get method on temp2.  1635   1636                     self._generateAttr(node, "__contains__", self.attribute_load_instructions)  1637                     temp_method = self._optimise_temp_storage()  1638   1639                     # Add arguments.  1640                     # NOTE: No support for defaults.  1641   1642                     self.new_op(temp2)  1643                     self.new_op(StoreFrame(0))  1644                     self.new_op(temp1)  1645                     self.new_op(StoreFrame(1))  1646                     self._endCallFuncArgs(2)  1647                     self._doCallFunc(temp_method)  1648                     self._endCallFunc(temp_method)  1649   1650                     self.new_op(StoreTemp(temp_pos))  1651                     self._generateTestBoolean(node, temp_result)  1652   1653                 if op_name.find("not") != -1:  1654                     self.new_op(InvertBoolean())  1655   1656             # Test the result and jump to the end label if false.  1657   1658             if op is not last_op:  1659                 self.new_op(JumpIfFalse(end_label))  1660   1661             # Compilation duties...  1662   1663             self.discard_temp(temp1)  1664   1665         self.discard_temp(temp2)  1666         self.discard_temp(temp_result)  1667         self.set_label(end_label)  1668   1669         # Yield the appropriate value.  1670   1671         self._generateLoadBoolean(node)  1672   1673     def visitConst(self, node):  1674         const = self.module.constant_values[node.value]  1675         self.new_op(LoadConst(const))  1676   1677     def visitContinue(self, node):  1678         next_label, exit_label = self.get_loop_labels()  1679         self.new_op(Jump(next_label))  1680   1681     def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators")  1682   1683     def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict")  1684   1685     def visitDiscard(self, node):  1686         self.dispatch(node.expr)  1687         self._optimise_unused_results()  1688   1689     def visitDiv(self, node):  1690         self._visitBinary(node, "__div__", "__rdiv__")  1691   1692     def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis")  1693   1694     def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec")  1695   1696     def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression")  1697   1698     def visitFloorDiv(self, node):  1699         self._visitBinary(node, "__floordiv__", "__rfloordiv__")  1700   1701     def visitFor(self, node):  1702         exit_label = self.new_label()  1703         next_label = self.new_label()  1704         else_label = self.new_label()  1705   1706         # Get the "list" to be iterated over, obtain its iterator.  1707   1708         self._startCallFunc()  1709         self.dispatch(node.list)  1710         self._generateAttr(node, "__iter__", self.attribute_load_instructions)  1711         temp, target = self._generateCallFunc([], node)  1712         self._doCallFunc(temp, target)  1713         self._endCallFunc(temp, target)  1714   1715         temp_iterator = self._optimise_temp_storage()  1716   1717         # In the loop...  1718   1719         self.set_label(next_label)  1720   1721         # Use the iterator to get the next value.  1722   1723         self._startCallFunc()  1724         self.new_op(temp_iterator)  1725         self._generateAttr(node, "next", self.attribute_load_instructions)  1726         temp, target = self._generateCallFunc([], node)  1727         self._doCallFunc(temp, target)  1728         self._endCallFunc(temp, target)  1729   1730         # Test for StopIteration.  1731   1732         self.load_builtin("StopIteration", node)  1733         self.new_op(CheckException())  1734         if node.else_ is not None:  1735             self.new_op(JumpIfTrue(else_label))  1736         else:  1737             self.new_op(JumpIfTrue(exit_label))  1738   1739         # Assign to the target.  1740   1741         self.dispatch(node.assign)  1742   1743         # Process the body with the current next and exit points.  1744   1745         self.add_loop_labels(next_label, exit_label)  1746         self.dispatch(node.body)  1747         self.drop_loop_labels()  1748   1749         # Repeat the loop.  1750   1751         self.new_op(Jump(next_label))  1752   1753         # Produce the "else" section.  1754   1755         if node.else_ is not None:  1756             self.set_label(exit_label)  1757             self.dispatch(node.else_)  1758   1759         # After the loop...  1760   1761         self.set_label(exit_label)  1762   1763         # Compilation duties...  1764   1765         self.discard_temp(temp_iterator)  1766   1767     def visitFrom(self, node): pass  1768   1769     def visitFunction(self, node):  1770   1771         # Only store the name when visiting this node from outside.  1772   1773         if self.unit is not node.unit:  1774             self.new_op(LoadConst(node.unit))  1775   1776             self.record_value()  1777             self._visitName(node, self.name_store_instructions) # AssName equivalent  1778             self.set_source()  1779             self.discard_value()  1780   1781             self._generateFunctionDefaults(node.unit)  1782   1783         # Visiting of the code occurs when get_code is invoked on this node.  1784   1785         else:  1786             extend = ExtendFrame()  1787             self.new_op(extend)  1788   1789             self.dispatch(node.code)  1790             if not isinstance(self.last_op(), Return):  1791                 self.dispatch(compiler.ast.Name("None"))  1792                 self.new_op(StoreResult())  1793   1794                 self.new_op(Return())  1795   1796             self.set_frame_usage(node, extend)  1797   1798     def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr")  1799   1800     def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor")  1801   1802     def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf")  1803   1804     def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner")  1805   1806     def visitGetattr(self, node):  1807         self._visitAttr(node, self.attribute_load_instructions)  1808   1809     def visitGlobal(self, node): pass  1810   1811     def visitIf(self, node):  1812         first = 1  1813         exit_label = self.new_label()  1814   1815         clauses = node.tests + [(None, node.else_)]  1816         last_clause = clauses[-1]  1817   1818         for clause in clauses:  1819             test, body = clause  1820             if body is None:  1821                 break  1822             if not first:  1823                 self.set_label(next_label)  1824             if test is not None:  1825                 self.dispatch(test)  1826                 next_label = self.new_label()  1827                 self.new_op(JumpIfFalse(next_label))  1828             self.dispatch(body)  1829             if clause is not last_clause:  1830                 self.new_op(Jump(exit_label))  1831             first = 0  1832   1833         self.set_label(exit_label)  1834   1835     def visitImport(self, node): pass  1836   1837     def visitInvert(self, node):  1838         self._visitUnary(node, "__invert__")  1839   1840     def visitKeyword(self, node): pass  1841   1842     def visitLambda(self, node):  1843   1844         """  1845         Lambda functions can be represented as globally defined functions  1846         provided they do not define any default parameter values, since these  1847         may defined in a non-global scope.  1848   1849         Where defaults are defined, an object must be created and its content  1850         defined: the callable member of the object's structure must be set to  1851         the lambda function definition; each default must be attached to the  1852         object as an attribute, as is the case with normal functions and  1853         methods.  1854         """  1855   1856         # Produce the reference to this function when visiting this node from  1857         # outside.  1858   1859         if self.unit is not node.unit:  1860             temp = self._generateFunctionDefaults(node.unit)  1861             self.new_op(LoadConst(node.unit))  1862   1863             # Populate the new object required for the function.  1864   1865             if temp is not None:  1866                 self.new_op(LoadCallable())  1867                 self.new_op(temp)  1868                 self.new_op(StoreCallable())  1869   1870                 self.new_op(temp)  1871                 #self.discard_temp(temp)  1872   1873         # Visiting of the code occurs when get_code is invoked on this node.  1874   1875         else:  1876             self.dispatch(node.code)  1877             self.new_op(StoreResult())  1878             self.new_op(Return())  1879   1880     def visitLeftShift(self, node):  1881         self._visitBinary(node, "__lshift__", "__rlshift__")  1882   1883     def visitList(self, node):  1884         self._generateSequence("list", node)  1885   1886     def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp")  1887   1888     def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor")  1889   1890     def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf")  1891   1892     def visitMod(self, node):  1893         self._visitBinary(node, "__mod__", "__rmod__")  1894   1895     def visitModule(self, node):  1896         self.dispatch(node.node)  1897   1898     def visitMul(self, node):  1899         self._visitBinary(node, "__mul__", "__rmul__")  1900   1901     def visitName(self, node):  1902         if node.name == "None":  1903             const = self.module.constant_values[None]  1904             self.new_op(LoadConst(const))  1905         else:  1906             self._visitName(node, self.name_load_instructions)  1907   1908     def visitNot(self, node):  1909         self.dispatch(node.expr)  1910   1911         temp = self._optimise_temp_storage()  1912         self._generateTestBoolean(node.expr, temp)  1913         self.discard_temp(temp)  1914   1915         self.new_op(InvertBoolean())  1916         self._generateLoadBoolean(node)  1917   1918         # Prevent incorrect optimisation.  1919   1920         self.clear_active()  1921   1922     def visitOr(self, node):  1923         end_label = self.new_label()  1924         temp_pos = self.reserve_temp()  1925         temp = LoadTemp(temp_pos)  1926   1927         for n in node.nodes[:-1]:  1928             self.dispatch(n)  1929             self.new_op(StoreTemp(temp_pos))  1930   1931             self._generateTestBoolean(n, temp)  1932             self.new_op(JumpIfTrue(end_label))  1933   1934         self.dispatch(node.nodes[-1])  1935         self.new_op(StoreTemp(temp_pos))  1936   1937         self.set_label(end_label)  1938   1939         # Prevent incorrect optimisation.  1940   1941         self.clear_active()  1942   1943         self.new_op(temp)  1944         self.discard_temp(temp)  1945   1946     def visitPass(self, node): pass  1947   1948     def visitPower(self, node):  1949         self._visitBinary(node, "__pow__", "__rpow__")  1950   1951     def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print")  1952   1953     def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl")  1954   1955     def visitRaise(self, node):  1956         # NOTE: expr1 only => instance provided  1957         self.dispatch(node.expr1)  1958   1959         if node.expr2 is not None:  1960             temp = self._optimise_temp_storage()  1961   1962             self.dispatch(node.expr2)  1963             temp_arg = self._optimise_temp_storage()  1964   1965             self._startCallFunc()  1966             self.new_op(temp_arg)  1967             self.new_op(StoreFrame(0))  1968             self._endCallFuncArgs(1)  1969             self._doCallFunc(temp)  1970             self._endCallFunc(temp)  1971   1972             self.discard_temp(temp_arg)  1973   1974         self.new_op(StoreException())  1975         self.new_op(RaiseException())  1976   1977     def visitReturn(self, node):  1978         if node.value is not None:  1979             self.dispatch(node.value)  1980         else:  1981             self.dispatch(compiler.ast.Name("None"))  1982   1983         self.new_op(StoreResult())  1984         self.new_op(Return())  1985   1986     def visitRightShift(self, node):  1987         self._visitBinary(node, "__rshift__", "__rrshift__")  1988   1989     def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice")  1990   1991     def visitStmt(self, node):  1992         for n in node.nodes:  1993             self.dispatch(n)  1994   1995     def visitSub(self, node):  1996         self._visitBinary(node, "__sub__", "__rsub__")  1997   1998     def visitSubscript(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Subscript")  1999   2000     def visitTryExcept(self, node):  2001         exit_label = self.new_label()  2002         success_label = self.new_label()  2003         handler_label = self.new_label()  2004   2005         self.add_exception_labels(handler_label, exit_label)  2006   2007         # Try...  2008         # Produce the code, then jump to the exit.  2009   2010         self.new_op(PushHandler(handler_label))  2011         self.dispatch(node.body)  2012         self.new_op(PopHandler())  2013         self.new_op(Jump(exit_label))  2014   2015         # Start of handlers.  2016   2017         self.set_label(handler_label)  2018         self.new_op(PopHandler())  2019   2020         for name, assignment, handler in node.handlers:  2021             next_label = self.new_label()  2022   2023             # Test the given exception against the current exception.  2024   2025             if name is not None:  2026                 self.dispatch(name)  2027                 self.new_op(CheckException())  2028                 self.new_op(JumpIfFalse(next_label))  2029   2030             # Handle assignment to exception variable.  2031   2032             if assignment is not None:  2033                 self.dispatch(assignment)  2034   2035             # Produce the handler code, then jump to the exit.  2036   2037             self.dispatch(handler)  2038             self.new_op(Jump(exit_label))  2039   2040             self.set_label(next_label)  2041   2042         # Unhandled exceptions.  2043   2044         #self.new_op(LoadException())  2045         self.new_op(RaiseException())  2046   2047         # Optional else clause.  2048   2049         if node.else_ is not None:  2050             self.dispatch(node.else_)  2051   2052         self.set_label(exit_label)  2053         self.drop_exception_labels()  2054   2055     def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally")  2056   2057     def visitTuple(self, node):  2058         self._generateSequence("tuple", node)  2059   2060     def visitUnaryAdd(self, node):  2061         self._visitUnary(node, "__pos__")  2062   2063     def visitUnarySub(self, node):  2064         self._visitUnary(node, "__neg__")  2065   2066     def visitWhile(self, node):  2067         exit_label = self.new_label()  2068         next_label = self.new_label()  2069         else_label = self.new_label()  2070   2071         self.set_label(next_label)  2072         self.dispatch(node.test)  2073         if node.else_ is not None:  2074             self.new_op(JumpIfFalse(else_label))  2075         else:  2076             self.new_op(JumpIfFalse(exit_label))  2077   2078         self.add_loop_labels(next_label, exit_label)  2079   2080         self.dispatch(node.body)  2081         self.new_op(Jump(next_label))  2082   2083         if node.else_ is not None:  2084             self.set_label(else_label)  2085             self.dispatch(node.else_)  2086   2087         self.set_label(exit_label)  2088         self.drop_loop_labels()  2089   2090         # Prevent incorrect optimisation.  2091   2092         self.clear_active()  2093   2094     def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With")  2095   2096     def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield")  2097   2098     # Useful data.  2099   2100     comparison_methods = {  2101         "==" : ("__eq__", "__ne__"),  2102         "!=" : ("__ne__", "__eq__"),  2103         "<" : ("__lt__", "__gt__"),  2104         "<=" : ("__le__", "__ge__"),  2105         ">=" : ("__ge__", "__le__"),  2106         ">" : ("__gt__", "__lt__"),  2107         "is" : None,  2108         "is not" : None,  2109         "in" : None,  2110         "not in" : None  2111         }  2112   2113 # vim: tabstop=4 expandtab shiftwidth=4