micropython

micropython/trans.py

442:13aae946513b
2011-07-05 Paul Boddie Introduced Instance() in place of None as a result and for the value of the active expression where no definitive object can be deduced. Made all Instance values compare equal to each other in order to avoid duplication in sets. Improved Constant comparisons. Fixed assignment counting where many values are provided in a single assignment. Added inspection support for conditional expressions (since they are used in the standard library).
     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, 2010, 2011 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     27 class Helper:    28     29     "Internal helper methods for AST visitors."    30     31     # Allocation-related methods.    32     33     def make_instance(self, cls, n):    34     35         """    36         Request a new instance using the given class 'cls' and with 'n'    37         attributes.    38         """    39     40         # Load the class in order to locate the instance template.    41     42         self.new_op(LoadConst(cls))    43     44         # NOTE: Instance headers are one location.    45     46         self.new_op(MakeInstance(n + 1))    47     48     def make_exception(self, name, node):    49     50         "Make an exception of the given 'name' using 'node'."    51     52         # NOTE: Reserving an attribute.    53     54         self.make_instance(self.get_builtin_class(name, node), 1)    55     56     # Name-related methods.    57     58     def get_scope(self, name):    59     60         "Return the scope for the given 'name'."    61     62         attr, scope, from_name = self.unit._get_with_scope(name)    63         return scope    64     65     def load_builtin(self, name, node):    66     67         "Generate an instruction loading 'name' for the given 'node'."    68     69         self.new_op(LoadAddress(self.get_builtin(name, node)))    70     71     def get_builtin_class(self, name, node):    72     73         "Return the built-in class with the given 'name' for the given 'node'."    74     75         return self.get_builtin(name, node).get_value()    76     77     def get_builtin(self, name, node):    78     79         """    80         Return the built-in module definition for the given 'name', used by the    81         given 'node'.    82         """    83     84         if self.builtins is not None:    85             try:    86                 return self.builtins[name]    87             except KeyError:    88                 raise TranslateError("No __builtins__ definition is available for name %r." % name)    89         else:    90             raise TranslateError("No __builtins__ module is available for name %r." % name)    91     92     # Common methods.    93     94     def _generateGuards(self, node):    95     96         if not (self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrtypes")):    97             return    98     99         # For each name, attempt to restrict the type employed.   100    101         for name, targets in node._attrtypes.items():   102    103             # NOTE: Need to merge targets using the same type but suggesting   104             # NOTE: different kinds of attributes (instance vs. class).   105    106             # Where only one object type is suggested, produce a guard.   107             # NOTE: This only supports classes as types, not modules.   108    109             if len(targets) == 1:   110                 target_name, is_static = list(targets)[0]   111    112                 # Access the object table to get the attribute.   113                 # NOTE: This depends on the special entry in the table   114                 # NOTE: for class equivalence tests.   115    116                 try:   117                     obj = self.objtable.access(target_name, target_name)   118    119                 # Where no attribute entry exists, the target could be a module.   120                 # NOTE: Should perhaps raise an error.   121    122                 except TableError, exc:   123                     print "Possible guard for", target_name, "not enforceable."   124                     continue   125    126                 # NOTE: Could test the correctness of the guard where the nature   127                 # NOTE: of the name is known.   128                 # NOTE: The known value would be retrieved from the unit's   129                 # NOTE: locals and tested as being a class or an instance of a   130                 # NOTE: particular class.   131    132                 # Generate the guard by loading a reference to the class.   133    134                 after_test_block = self.new_block()   135    136                 self.new_op(LoadClass(obj))   137                 temp_target = self.optimiser.optimise_temp_storage()   138    139                 # For only static attributes, classes are acceptable.   140    141                 if is_static:   142    143                     # Generate name is target (for classes).   144    145                     self.dispatch(compiler.ast.Name(name))   146                     self.new_op(TestIdentity())   147                     self.optimiser.set_source(temp_target)   148    149                     # Jump to the next guard or the code if successful.   150    151                     self.new_op(JumpIfTrue(after_test_block))   152    153                 # Where instance attributes are involved, only instances are   154                 # acceptable.   155    156                 # Generate isinstance(name, target).   157    158                 self.dispatch(compiler.ast.Name(name))   159                 self.new_op(CheckInstance())   160                 self.optimiser.set_source(temp_target)   161    162                 # Jump to the next guard or the code if successful.   163    164                 self.new_op(JumpIfTrue(after_test_block))   165    166                 # Where the type is inappropriate, raise an exception.   167    168                 self.make_exception("TypeError", node)   169                 self.new_op(StoreException())   170                 self.new_op(RaiseException())   171    172                 self.set_block(after_test_block)   173    174     def _visitAttr(self, node, classes):   175    176         """   177         Visit the attribute-related 'node', generating instructions based on the   178         given 'classes'.   179         """   180    181         self.dispatch(node.expr)   182         self._generateAttr(node, node.attrname, classes)   183    184     def _generateAttr(self, node, attrname, classes):   185    186         """   187         Generate code for the access to 'attrname' using the given 'classes'.   188         """   189    190         AddressInstruction, AddressContextInstruction, AddressContextCondInstruction, \   191             AttrInstruction, AttrIndexInstruction, AttrIndexContextCondInstruction = classes   192    193         # Where the last operation (defining the attribute owner) yields a   194         # constant...   195    196         target_plus_name = self.optimiser.optimise_constant_accessor()   197    198         # Only try and discover the position if the target can be resolved.   199         # Since instances cannot be constants, this involves classes and   200         # modules.   201         # It is acceptable to replace the instruction providing the constant   202         # input because doing so does not lose any input information required by   203         # the replacement instructions.   204    205         if target_plus_name is not None:   206             target, target_name = target_plus_name   207    208             # Check for class.__class__.   209    210             if attrname == "__class__":   211                 if isinstance(target, Class):   212                     if AddressInstruction is LoadAddress:   213                         self.replace_active_value(LoadAddress(self.get_builtin("type", node)))   214                         return   215                     else:   216                         raise TranslateError("Assigning to __class__ is not permitted.")   217    218             # Access the object table to get the attribute.   219    220             try:   221                 attr = self.objtable.access(target_name, attrname)   222             except TableError, exc:   223                 raise TranslateError(exc.args[0])   224    225             # Produce a suitable instruction.   226    227             if AddressInstruction is not None:   228                 self.replace_active_value(AddressInstruction(attr))   229             else:   230                 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)   231    232             return   233    234         # Where the last operation involves the special 'self' name, check to   235         # see if the attribute is acceptably positioned and produce a direct   236         # access to the attribute.   237    238         # This is the only reliable way of detecting instance accesses at   239         # compile-time since in general, objects could be classes or modules,   240         # but 'self' should only refer to instances.   241    242         elif self.optimiser.optimise_self_access(self.unit, attrname):   243    244             # Either generate an instruction operating on an instance attribute.   245    246             try:   247                 attr = self.unit.parent.instance_attributes()[attrname]   248                 self.new_op(AttrInstruction(attr))   249                 return   250    251             # Or generate an instruction operating on a class attribute.   252             # NOTE: Any simple instruction providing self is not removed.   253    254             except KeyError:   255    256                 try:   257                     attr = self.unit.parent.all_attributes()[attrname]   258    259                     # Switch the context if the class attribute is compatible with   260                     # the instance.   261    262                     if attr.defined_within_hierarchy():   263    264                         # Only permit loading (not storing) of class attributes via self.   265    266                         if AddressContextInstruction is not None:   267                             self.new_op(AddressContextInstruction(attr))   268                         else:   269                             raise TranslateError("Storing of class attribute %r via self not permitted." % attrname)   270    271                     # Preserve the context if the class attribute comes from an   272                     # incompatible class.   273    274                     elif attr.defined_outside_hierarchy():   275    276                         # Only permit loading (not storing) of class attributes via self.   277    278                         if AddressInstruction is not None:   279                             self.new_op(AddressInstruction(attr))   280                         else:   281                             raise TranslateError("Storing of class attribute %r via self not permitted." % attrname)   282    283                     # Otherwise, test for a suitable context at run-time.   284    285                     else:   286    287                         # Only permit loading (not storing) of class attributes via self.   288    289                         if AddressContextCondInstruction is not None:   290                             self.new_op(AddressContextCondInstruction(attr))   291                         else:   292                             raise TranslateError("Storing of class attribute %r via self not permitted." % attrname)   293    294                     return   295    296                 # Or delegate the attribute access to a general instruction   297                 # since the kind of attribute cannot be deduced.   298    299                 except KeyError:   300                     pass   301    302         # Attempt to deduce the target of an attribute access by searching for a   303         # unique type providing the names associated with the accessed object.   304    305         elif self.optimiser.should_optimise_accesses_by_attribute_usage():   306    307             target_names = self.possible_accessor_types(node)   308    309             if target_names is not None and len(target_names) == 1:   310                 target_name, is_static = list(target_names)[0]   311    312                 # Check for class.__class__.   313    314                 if attrname == "__class__":   315                     if is_static:   316                         self.load_builtin("type", node)   317                         return   318    319                 # Access the object table to get the attribute.   320    321                 try:   322                     attr = self.objtable.access(target_name, attrname)   323    324                 # Disallow non-class/instance optimisations.   325    326                 except TableError, exc:   327                     print "Possible optimisation for", target_name, "not permissable."   328    329                 # Produce a suitable instruction.   330    331                 else:   332                     if AddressContextCondInstruction is not None and attr.is_static_attribute():   333                         self.new_op(AddressContextCondInstruction(attr))   334                     elif AttrInstruction is not None and not attr.is_static_attribute():   335                         self.new_op(AttrInstruction(attr))   336                     else:   337                         raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)   338    339                     return   340    341         # Check for class.__class__.   342    343         if attrname == "__class__":   344    345             # Remember the accessor.   346    347             temp_accessor = self.optimiser.optimise_temp_storage()   348    349             attr_block = self.new_block()   350             end_block = self.new_block()   351    352             self.new_op(CheckClass())   353             self.new_op(JumpIfFalse(attr_block))   354             self.load_builtin("type", node)   355             self.new_op(Jump(end_block))   356             self.set_block(attr_block)   357    358             # Recall the accessor.   359    360             self.new_op(temp_accessor)   361    362         # Otherwise, perform a normal operation.   363    364         try:   365             index = self.objtable.get_index(attrname)   366    367         except self.objtable.TableError:   368    369             # If this error arises on generated code, check the names_used   370             # attribute on the Importer.   371    372             raise TranslateError("No attribute entry exists for name %r." % attrname)   373    374         # NOTE: Test for class vs. instance attributes, generating   375         # NOTE: context-related instructions.   376    377         if AttrIndexContextCondInstruction is not None:   378             self.new_op(AttrIndexContextCondInstruction(index))   379    380         # Store instructions do not need to consider context modifications.   381    382         else:   383             self.new_op(AttrIndexInstruction(index))   384    385         # Where __class__ was involved, define the start of the following code.   386    387         if attrname == "__class__":   388             self.set_block(end_block)   389    390     # Invocations involve the following:   391     #   392     # 1. Reservation of a frame for the arguments   393     # 2. Identification of the target which is then held in temporary storage   394     # 3. Optional inclusion of a context (important for methods)   395     # 4. Preparation of the argument frame   396     # 5. Invocation of the target   397     # 6. Discarding of the frame   398     #   399     # In order to support nested invocations - such as a(b(c)) - use of the   400     # temporary storage is essential.   401    402     def _startCallFunc(self):   403    404         "Record the location of the invocation."   405    406         op = MakeFrame()   407         self.new_op(op) # records the start of the frame   408         self.frame_makers.append(op)   409    410     def _generateCallFunc(self, args, node):   411    412         """   413         Support a generic function invocation using the given 'args', occurring   414         on the given 'node', where the expression providing the invocation   415         target has just been generated.   416    417         In other situations, the invocation is much simpler and does not need to   418         handle the full flexibility of a typical Python invocation. Internal   419         invocations, such as those employed by operators and certain   420         control-flow mechanisms, use predetermined arguments and arguably do not   421         need to support the same things as the more general invocations.   422         """   423    424         target, context, temp_target, temp_context = self._generateCallFuncContext()   425         self._generateCallFuncArgs(target, context, temp_target, temp_context, args, node)   426         return temp_target, target, temp_context   427    428     def _generateCallFuncContext(self):   429    430         """   431         Produce code which loads and checks the context of the current   432         invocation, the instructions for whose target have already been   433         produced, returning a list of instructions which reference the   434         invocation target.   435         """   436    437         t = self.optimiser.optimise_known_target()   438         if t:   439             target, context = t   440    441             # Detect dynamic functions acting like instances.   442    443             if isinstance(target, Function) and target.is_dynamic():   444                 target, context = None, None   445         else:   446             target, context = None, None   447    448         # Store the target in temporary storage for subsequent referencing.   449    450         temp_target = self.optimiser.optimise_temp_storage()   451    452         # Where a target or context are not known or where an instance is known   453         # to be the context, load the context.   454    455         if target is None or isinstance(context, Instance):   456             self.new_op(temp_target)   457             self.new_op(LoadContextIntoValue())   458             temp_context = self.optimiser.optimise_temp_storage()   459             self.new_op(StoreFrame(0))   460    461         # Class contexts should be made available for testing of the first   462         # argument.   463         # NOTE: Class methods should eventually be supported.   464    465         elif isinstance(context, Class):   466             self.new_op(temp_target)   467             self.new_op(LoadContextIntoValue())   468             temp_context = self.optimiser.optimise_temp_storage()   469    470         # Otherwise omit the context.   471    472         else:   473             temp_context = None   474    475         return target, context, temp_target, temp_context   476    477     def _generateCallFuncArgs(self, target, context, temp_target, temp_context, args, node):   478    479         """   480         Given invocation 'target' and 'context' information, the 'temp_target'   481         reference to the target, the 'temp_context' reference to the context, a   482         list of nodes representing the 'args' (arguments), generate instructions   483         which load the arguments for the invocation defined by the given 'node'.   484         """   485    486         # Evaluate the arguments.   487    488         employed_positions = set()   489         employed_keywords = set()   490         extra_keywords = []   491         positional_args = []   492         keyword_args = []   493    494         # Find keyword arguments in advance in order to help resolve targets.   495    496         have_keywords = 0   497    498         for arg in args:   499             if isinstance(arg, compiler.ast.Keyword):   500                 employed_keywords.add(arg.name)   501                 keyword_args.append(arg)   502                 have_keywords = 1   503             elif not have_keywords:   504                 positional_args.append(arg)   505    506         possible_targets = self.paramtable.all_possible_objects(employed_keywords)   507    508         # Note the presence of the context in the frame where appropriate.   509    510         # For unknown invocations and method invocations.   511    512         if target is None or isinstance(context, Instance):   513             ncontext = 1   514             expect_testable_self = 0   515    516         # Handle calls to classes by obtaining the instantiator function.   517         # A context is reserved for the new instance, but this is not provided   518         # in the invocation (since the instantiator will fill the locals slot   519         # concerned).   520    521         elif isinstance(target, Class):   522             ncontext = 1   523             expect_testable_self = 0   524             target = target.get_instantiator()   525    526         # Method calls via classes.   527    528         elif isinstance(context, Class):   529             ncontext = 0   530             expect_testable_self = 1   531    532         # Function calls.   533    534         else:   535             ncontext = 0   536             expect_testable_self = 0   537    538         # Traverse the positional arguments adding them using the incrementing   539         # frame position.   540    541         first = 1   542         frame_pos = ncontext   543         temp_first_argument = None   544    545         for arg in positional_args:   546             self.dispatch(arg)   547             self.new_op(StoreFrame(frame_pos))   548             employed_positions.add(frame_pos)   549    550             # Check to see if the first argument is appropriate (compatible with   551             # the target where methods are being invoked via classes).   552    553             if first and (expect_testable_self or target is None):   554    555                 # Drop any test if the target and the context are known.   556    557                 if not self.optimiser.have_correct_self_for_target(context, self.unit):   558    559                     # Otherwise, remember the first argument for a subsequent   560                     # test.   561    562                     temp_first_argument = self.optimiser.optimise_temp_storage()   563    564             first = 0   565             frame_pos += 1   566    567         # Adjust the invocation frame for unknown invocations.   568         # Test the first argument if appropriate.   569    570         self._generateCallFuncContextTest(temp_target, target, temp_context, temp_first_argument, node)   571    572         # Traverse the keyword arguments adding them at the appropriate frame   573         # positions.   574    575         max_keyword_pos = -1   576    577         for arg in keyword_args:   578    579             # Optimise where the target is known now.   580    581             if target is not None:   582    583                 # Find the parameter table entry for the target.   584    585                 target_name = target.full_name()   586    587                 # Look for a callable with the precise target name.   588    589                 table_entry = self.paramtable.table[target_name]   590    591                 # Look the name up in the parameter table entry.   592    593                 try:   594                     pos = table_entry[arg.name]   595    596                 # Where no position is found, this could be an extra keyword   597                 # argument.   598    599                 except KeyError:   600                     extra_keywords.append(arg)   601                     continue   602    603                 # Test for illegal conditions.   604    605                 if pos in employed_positions:   606                     raise TranslateError("Keyword argument %r overwrites parameter %r." % (arg.name, pos))   607    608                 employed_positions.add(pos)   609    610                 # Generate code for the keyword and the positioning   611                 # operation.   612    613                 self.dispatch(arg.expr)   614                 self.new_op(StoreFrame(pos))   615    616             # Otherwise, generate the code needed to obtain the details of   617             # the parameter location.   618    619             else:   620    621                 # Combine the target details with the name to get the location.   622                 # See the access method on the List class.   623    624                 try:   625                     paramindex = self.paramtable.get_index(arg.name)   626    627                 # Where no position is found, this could be an extra keyword   628                 # argument.   629    630                 except self.paramtable.TableError:   631                     extra_keywords.append(arg)   632                     continue   633    634                 # Generate code for the keyword and the positioning   635                 # operation. Get the value as the source of the assignment.   636    637                 self.dispatch(arg.expr)   638                 self.record_value()   639    640                 # Store the source value using the callable's parameter   641                 # table information.   642    643                 self.new_op(temp_target)   644                 self.new_op(StoreFrameIndex(paramindex))   645    646                 self.set_source()   647                 self.discard_value()   648    649                 # Record the highest possible frame position for this argument.   650    651                 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name)))   652    653             # Use the frame position counter as a general argument counter.   654    655             frame_pos += 1   656    657         # NOTE: Extra keywords are not supported.   658         # NOTE: Somehow, the above needs to be combined with * arguments.   659    660         if extra_keywords:   661             print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords])   662    663         # Either test for a complete set of arguments.   664    665         if target is not None:   666    667             # Make sure that enough arguments have been given.   668    669             nargs_max = len(target.positional_names)   670             ndefaults = len(target.defaults)   671             nargs_min = nargs_max - ndefaults   672    673             # Visit each argument position and look for a supplied argument.   674    675             for i in range(ncontext, nargs_min):   676                 if i not in employed_positions:   677                     raise TranslateError(   678                         "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min))   679    680             nargs = frame_pos   681    682             # Determine whether too many arguments have been given and how big   683             # the frame should be.   684    685             # For parameter lists with * or ** parameters, accept as many   686             # arguments as are allowed or as many as we have.   687    688             if target.has_star or target.has_dstar:   689                 frame_size = max(nargs, nargs_max)   690    691                 # NOTE: We now need to pack these arguments into a suitable   692                 # NOTE: structure for the * parameter.   693    694             # For other parameter lists, only accept as many arguments as we are   695             # allowed.   696    697             elif nargs > nargs_max:   698                 raise TranslateError(   699                     "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max))   700    701             else:   702                 frame_size = nargs_max   703    704             # Where defaults are involved, put them into the frame.   705    706             self._generateCallFuncDefaultArgs(target, temp_target, nargs_min, nargs_max, employed_positions)   707    708             # Set the frame size.   709    710             self._endCallFuncArgs(frame_size)   711    712         # Or just set the frame size and have the function check the arguments.   713    714         else:   715             max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1)   716             self._endCallFuncArgs(max_pos + 1)   717    718     def _generateCallFuncDefaultArgs(self, target, temp_target, nargs_min, nargs_max, employed_positions):   719    720         """   721         For the given 'target' and 'temp_target' reference to the target,   722         generate default arguments for those positions in the range   723         'nargs_min'...'nargs_max' which are not present in the   724         'employed_positions' collection.   725         """   726    727         # Where appropriate, construct a dynamic object to hold the defaults.   728    729         dynamic = target.is_dynamic()   730    731         # Here, we use negative index values to visit the right hand end of   732         # the defaults list.   733    734         for pos in range(nargs_min, nargs_max):   735             if pos not in employed_positions:   736                 if dynamic:   737                     self.new_op(temp_target)   738                     self.new_op(LoadAttr(target.default_attrs[pos - nargs_min]))   739                 else:   740                     self.new_op(LoadAddress(target.default_attrs[pos - nargs_min]))   741                 self.new_op(StoreFrame(pos))   742    743     def _generateCallFuncContextTest(self, temp_target, target, temp_context, temp_first_argument, node):   744    745         """   746         Generate code to test for 'temp_target', representing the given   747         'target', the context provided by 'temp_context' against   748         'temp_first_argument', and to signal an exception (using 'node') if the   749         context is incompatible with the first frame argument.   750    751         In addition, the invocation frame will be shifted if 'temp_context'   752         indicates a function or a class.   753         """   754    755         adjust_block = self.new_block()   756         continue_block = self.new_block()   757    758         # Add some preliminary tests where the target is not known.   759    760         if target is None:   761    762             # Adjust the frame if a replaceable context is provided.   763    764             self.new_op(temp_context)   765             self.new_op(CheckContext())   766             self.new_op(JumpIfFalse(adjust_block))   767    768             # Skip adjustment and tests if the context is not a class.   769             # Classes themselves employ a placeholder context so that   770             # instantiators can be callable with a context which will be   771             # overwritten in the frame.   772    773             self.new_op(temp_context)   774             self.new_op(CheckClass())   775             self.new_op(JumpIfFalse(continue_block))   776    777         if temp_first_argument is not None:   778             self.new_op(temp_first_argument)   779    780             # Check the current value (the argument) against the known context   781             # (given as the source).   782    783             self.new_op(CheckInstance())   784             self.optimiser.set_source(temp_context)   785    786             self.new_op(JumpIfTrue(adjust_block))   787    788             # Where the context is inappropriate, drop the incomplete frame and   789             # raise an exception.   790    791             self.new_op(DropFrame())   792             self.new_op(LoadResultIntoValue())   793    794             self.make_exception("TypeError", node)   795             self.new_op(StoreException())   796             self.new_op(RaiseException())   797    798         if target is None or temp_first_argument is not None:   799             self.set_block(adjust_block)   800             self.new_op(AdjustFrame(1))   801    802             self.set_block(continue_block)   803    804     def _doCallFunc(self, temp_target, target=None):   805    806         "Make the invocation."   807    808         # For classes, the target itself is used, since the instantiator will be   809         # obtained via the class.   810    811         if isinstance(target, (Class, Function)):   812             self.new_op(JumpWithFrameDirect(target))   813         else:   814             self.new_op(temp_target)   815             self.new_op(LoadCallable())   816             self.new_op(JumpWithFrame())   817    818     def _endCallFuncArgs(self, nargs):   819    820         "Set the frame size."   821    822         self.frame_makers[-1].attr = nargs   823         self.frame_makers.pop()   824    825     def _endCallFunc(self, temp_target=None, temp_context=None, load_result=1):   826    827         "Finish the invocation and tidy up afterwards."   828    829         self.new_op(DropFrame())   830         if load_result:   831             self.new_op(LoadResultIntoValue())   832    833         # Discard any temporary storage instructions.   834    835         if temp_target is not None:   836             self.discard_temp(temp_target)   837    838         if temp_context is not None:   839             self.discard_temp(temp_context)   840    841     def _visitFunctionDeclaration(self, node):   842    843         """   844         Visit the function declaration at 'node', which can be a lambda or a   845         named function. As a consequence an instruction will be generated which   846         provides a reference to the function.   847         """   848    849         fn = node.unit   850         ndefaults = len(fn.defaults)   851         temp = self._generateFunctionDefaults(fn)   852    853         # Populate the new object required for the function.   854    855         if temp is not None:   856             self.new_op(LoadConst(fn))   857             self.new_op(LoadCallable())   858             self.new_op(temp)   859             self.new_op(StoreCallable())   860    861             self.new_op(temp)   862             #self.discard_temp(temp)   863         else:   864             self.new_op(LoadFunction(fn))   865    866     def _visitFunctionDefinition(self, node):   867    868         """   869         Visit the function definition at 'node', which can be a lambda or a   870         named function, generating the prelude with argument and default   871         checking, plus the body of the function itself.   872         """   873    874         # Check frames using the function's details.   875    876         fn = node.unit   877         nparams = len(fn.positional_names)   878         ndefaults = len(fn.defaults)   879    880         fn.body_block = self.new_block()   881    882         # Check the number of parameters and defaults.   883    884         self.new_op(CheckFrame((nparams, ndefaults)))   885    886         if ndefaults > 0:   887             if fn.is_dynamic():   888                 self.new_op(LoadTemp(0)) # context provides storage   889             else:   890                 self.new_op(LoadFunction(fn))   891    892             self.new_op(FillDefaults((nparams, ndefaults)))   893    894         # Produce the body.   895    896         self.set_block(fn.body_block)   897    898         # For functions with star parameters, make a special list for the   899         # extra arguments and re-map the parameter.   900    901         if fn.has_star:   902             self.new_op(CopyExtra(nparams))   903    904             # Ensure that the star parameter has a slot in the frame.   905    906             self.new_op(CheckExtra(nparams))   907             self.new_op(StoreTemp(nparams))   908    909         # Extend the frame for local usage.   910    911         extend = ExtendFrame()   912         self.new_op(extend)   913    914         # Perform tuple assignment for any tuple parameters.   915    916         self._visitFunctionTupleParameters(fn, node)   917    918         # Add any attribute usage guards.   919    920         self._generateGuards(node)   921    922         # Visit the actual code.   923    924         self.dispatch(node.code)   925    926         # Add a return statement where one is not already produced.   927    928         if not isinstance(self.last_op(), Return):   929    930             # Return None for normal functions without explicit return   931             # statements.   932    933             if not fn.is_lambda():   934                 self.dispatch(compiler.ast.Name("None"))   935    936             self.new_op(LoadValueIntoResult())   937             self.new_op(Return())   938    939         # Make sure that enough frame space is reserved from the start.   940    941         self.set_frame_usage(node, extend)   942    943     def _visitFunctionTupleParameters(self, fn, node, parameters=None):   944    945         """   946         Visit the tuple parameters for function 'fn', obtaining the appropriate   947         elements from each supplied argument and assigning them to the specified   948         names for each parameter.   949         """   950    951         if parameters is not None:   952             self._generateAttr(node, "__getitem__", self.attribute_load_instructions)   953             temp_getitem = self.optimiser.optimise_temp_storage()   954    955         for i, parameter in parameters or fn.tuple_parameters():   956    957             # Either load the parameter from the frame.   958    959             if parameters is None:   960                 self.new_op(LoadName(Attr(i, None, None)))   961    962             # Or load a value from the current collection.   963    964             else:   965                 self._startCallFunc()   966                 self.new_op(temp_getitem)   967                 temp_target, target, temp_context = self._generateCallFunc([compiler.ast.Const(i)], node)   968                 self._doCallFunc(temp_target, target)   969                 self._endCallFunc()   970    971             # Where a tuple is the target, attempt to descend into the value   972             # obtained.   973    974             if isinstance(parameter, list):   975                 self._visitFunctionTupleParameters(fn, node, parameter)   976    977             # Store the item in the namespace entry for the given name.   978    979             else:   980                 self.record_value()   981                 self.new_op(StoreName(fn[parameter]))   982                 self.set_source()   983                 self.discard_value()   984    985         if parameters is not None:   986             self.discard_temp(temp_getitem)   987    988     def _generateFunctionDefaults(self, function):   989    990         """   991         Generate the default initialisation code for 'function', returning   992         a temporary storage reference if a dynamic object was created for the   993         function.   994         """   995    996         attr_to_default = zip(function.default_attrs, function.defaults)   997         if not attr_to_default:   998             return None   999   1000         # Where non-constant defaults are involved, construct a dynamic object  1001         # to hold the defaults.  1002   1003         dynamic = function.is_dynamic()  1004   1005         if dynamic:  1006             self.make_instance(self.get_builtin_class("function", function), len(attr_to_default))  1007             temp = self.get_temp()  1008   1009         for attr, default in attr_to_default:  1010             self.dispatch(default)  1011   1012             self.record_value()  1013             if dynamic:  1014                 self.new_op(temp)  1015                 self.new_op(StoreAttr(attr))  1016             else:  1017                 self.new_op(StoreAddress(attr))  1018             self.set_source()  1019             self.discard_value()  1020   1021         if dynamic:  1022             return temp  1023         else:  1024             return None  1025   1026     def _visitName(self, node, classes):  1027   1028         """  1029         Visit the name-related 'node', generating instructions based on the  1030         given 'classes'.  1031         """  1032   1033         name = node.name  1034   1035         # Get the expected scope of the name.  1036   1037         scope = getattr(node, "_scope", None) or self.get_scope(name)  1038         self._generateName(name, scope, classes, node)  1039   1040     def _generateName(self, name, scope, classes, node):  1041   1042         """  1043         Generate code for the access to 'name' in 'scope' using the given  1044         'classes', and using the given 'node' as the source of the access.  1045         """  1046   1047         NameInstruction, AddressInstruction, AddressContextInstruction = classes  1048   1049         # Handle names referring to constants.  1050   1051         if scope == "constant":  1052             const = self.importer.get_predefined_constant(name)  1053             self.new_op(LoadConst(const))  1054   1055         # Handle all other names.  1056   1057         elif scope == "local":  1058             unit = self.unit  1059             if isinstance(unit, Function):  1060                 self.new_op(NameInstruction(unit.all_locals()[name]))  1061             elif isinstance(unit, Class):  1062                 if AddressContextInstruction is not None:  1063                     self.new_op(LoadConst(unit))  1064                     self.new_op(AddressContextInstruction(unit.all_class_attributes()[name]))  1065                 else:  1066                     self.new_op(AddressInstruction(unit.all_class_attributes()[name]))  1067             elif isinstance(unit, Module):  1068                 self.new_op(AddressInstruction(unit.module_attributes()[name]))  1069             else:  1070                 raise TranslateError("Program unit has no local %r." % name)  1071   1072         elif scope == "global":  1073             globals = self.module.module_attributes()  1074             if globals.has_key(name):  1075                 self.new_op(AddressInstruction(globals[name]))  1076             else:  1077                 raise TranslateError("Module has no attribute %r." % name)  1078   1079         elif scope == "builtins":  1080             self.new_op(AddressInstruction(self.get_builtin(name, node)))  1081   1082         else:  1083             # NOTE: This may happen because a class attribute is optimised away.  1084             print "Program unit uses unknown name %r." % name  1085   1086     def _visitUnary(self, node):  1087   1088         """  1089         Invoke the appropriate operator module function for the operation  1090         represented by 'node'.  1091         """  1092   1093         temp_fn = self._getOperatorFunction(node)  1094         self._visitCall(node, temp_fn, (node.expr,))  1095         self.discard_temp(temp_fn)  1096   1097     def _visitBinaryBit(self, node):  1098   1099         """  1100         Need to impose binary rules over a sequence of nodes. The  1101         short-circuiting of the similar logical operators is not imposed by the  1102         bitwise operators.  1103         """  1104   1105         temp_fn = self._getOperatorFunction(node)  1106         left = None  1107   1108         for right in node.nodes:  1109             if left is not None:  1110                 self._visitCall(node, temp_fn, (left, right))  1111             left = right  1112   1113         self.discard_temp(temp_fn)  1114   1115     def _visitBinary(self, node):  1116   1117         """  1118         Invoke the appropriate operator module function for the operation  1119         represented by 'node'.  1120         """  1121   1122         temp_fn = self._getOperatorFunction(node)  1123         self._visitCall(node, temp_fn, (node.left, node.right))  1124         self.discard_temp(temp_fn)  1125   1126     def _visitCall(self, node, temp_fn, args):  1127   1128         """  1129         Invoke the appropriate operator module function for the operation  1130         represented by 'node', given a 'temp_fn' reference to a function, along  1131         with the 'args' (the operand nodes).  1132         """  1133   1134         # Evaluate and store the operands in temporary storage.  1135   1136         temp_list = []  1137   1138         for arg in args:  1139             self.dispatch(arg)  1140             temp_list.append(self.optimiser.optimise_temp_storage())  1141   1142         self._generateInvocation(temp_fn, temp_list)  1143   1144         # Compilation duties...  1145   1146         for temp in temp_list:  1147             self.discard_temp(temp)  1148   1149     def _generateInvocation(self, temp_fn, temp_list):  1150   1151         """  1152         Invoke the function 'temp_fn' using the operands from 'temp_list' as  1153         arguments.  1154         """  1155   1156         self._startCallFunc()  1157   1158         for i, temp in enumerate(temp_list):  1159             self.new_op(temp)  1160             self.new_op(StoreFrame(i))  1161   1162         self._endCallFuncArgs(len(temp_list))  1163         self._doCallFunc(temp_fn)  1164         self._endCallFunc(temp_fn)  1165   1166     def _getOperatorFunction(self, node, operator_name=None):  1167   1168         "Return an operator function reference for the given 'node'."  1169   1170         return self._generateOperatorFunction(operator_name or node.__class__.__name__)  1171   1172     def _getOperatorAugAssignFunction(self, node):  1173   1174         """  1175         Return an operator augmented assignment function reference for the given  1176         'node'.  1177         """  1178   1179         return self._generateOperatorFunction(node.op)  1180   1181     def _generateOperatorFunction(self, opname):  1182   1183         "Return an operator function reference for the given 'opname'."  1184   1185         operator_fn = operator_functions[opname]  1186   1187         # Get the operator module.  1188   1189         operator_module = self.importer.get_module("operator")  1190   1191         # Get the appropriate function from the operator module.  1192   1193         self.new_op(LoadAddress(operator_module[operator_fn]))  1194         return self.optimiser.optimise_temp_storage()  1195   1196     def _handleAttributeError(self, node, temp_method, handled_block):  1197   1198         """  1199         Add exception handling to the method acquisition instructions where the  1200         attribute access cannot be resolved at compile-time.  1201         """  1202   1203         if not (self.optimiser.should_optimise_known_target() and self.optimiser.is_constant_input(temp_method)):  1204             self.load_builtin("AttributeError", node)  1205             self.new_op(CheckException())  1206             self.new_op(JumpIfTrue(handled_block))  1207             self.new_op(RaiseException())  1208   1209     def _generateTuple(self, node):  1210   1211         "Make a tuple using the given program 'node'."  1212   1213         # Reserve space for the elements themselves.  1214   1215         self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes))  1216         temp = self.get_temp()  1217   1218         # Store using 0-based index values.  1219   1220         self._populateSequence(temp, node)  1221   1222         self.new_op(temp)  1223         self.discard_temp(temp)  1224   1225     def _generateList(self, node):  1226   1227         "Make a list using the given program 'node'."  1228   1229         # Make a fragment containing the list elements.  1230   1231         self.new_op(MakeFragment(len(node.nodes) + 1))  1232         temp = self.get_temp()  1233         self._populateSequence(temp, node)  1234         self.new_op(temp)  1235         self.record_value()  1236   1237         # Reserve space for _elements (the fragment reference).  1238   1239         self.make_instance(self.get_builtin_class("list", node), 1)  1240         list_temp = self.get_temp()  1241         self.new_op(list_temp)  1242         self.new_op(StoreAttr(Attr(0, None, None))) # _elements is at position 0  1243         self.set_source()  1244         self.discard_value()  1245   1246         self.new_op(list_temp)  1247         self.discard_temp(temp)  1248         self.discard_temp(list_temp)  1249   1250     def _populateSequence(self, temp, node, offset=0):  1251   1252         """  1253         Populate a sequence using the given 'temp' reference and program 'node'.  1254         """  1255   1256         for i, n in enumerate(node.nodes):  1257             self.dispatch(n)  1258             self.record_value()  1259             self._storeInSequence(temp, i, offset)  1260             self.discard_value()  1261   1262     def _storeInSequence(self, temp, i, offset=0):  1263   1264         """  1265         Store the current active value in the fragment referenced by 'temp' at  1266         position 'i' with the given starting 'offset'.  1267         """  1268   1269         self.new_op(temp)  1270         self.new_op(StoreAttr(Attr(i + offset, None, None)))  1271         self.set_source()  1272   1273     def _generateTestBoolean(self, node, temp):  1274   1275         """  1276         Generate a test of the boolean status of the current value for the given  1277         program 'node'.  1278         """  1279   1280         # Get method on temp.  1281         # NOTE: Using __bool__ instead of __nonzero__.  1282   1283         self._generateAttr(node, "__bool__", self.attribute_load_instructions)  1284         temp_method = self.optimiser.optimise_temp_storage()  1285   1286         self._generateInvocation(temp_method, (temp,))  1287   1288         self.discard_temp(temp_method)  1289   1290         # Convert result to boolean (a StoreBoolean operation).  1291   1292         self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True")))  1293   1294     def _generateLoadBoolean(self, node):  1295   1296         """  1297         Generate instructions to load the appropriate value given the current  1298         boolean status.  1299         """  1300   1301         true_block = self.new_block()  1302         end_block = self.new_block()  1303   1304         self.new_op(JumpIfTrue(true_block))  1305         self.new_op(LoadConst(self.importer.get_predefined_constant("False")))  1306         self.new_op(Jump(end_block))  1307   1308         self.set_block(true_block)  1309         self.new_op(LoadConst(self.importer.get_predefined_constant("True")))  1310   1311         self.set_block(end_block)  1312   1313     def _visitPrint(self, node, function_name):  1314         self._startCallFunc()  1315         self.load_builtin(function_name, node)  1316   1317         args = [node.dest or compiler.ast.Name("None")] + node.nodes  1318   1319         temp_target, target, temp_context = self._generateCallFunc(args, node)  1320         self._doCallFunc(temp_target, target)  1321         self._endCallFunc(temp_target, temp_context)  1322   1323 # vim: tabstop=4 expandtab shiftwidth=4