Lichen

translator.py

890:2cbff01cc586
2019-02-02 Paul Boddie Introduced special case treatment of __class__ as a ubiquitous attribute.
     1 #!/usr/bin/env python     2      3 """     4 Translate programs.     5      6 Copyright (C) 2015, 2016, 2017, 2018 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 common import AccessLocation, CommonModule, CommonOutput, Location, \    23                    first, get_builtin_class, init_item, is_newer, \    24                    predefined_constants    25 from encoders import encode_access_instruction, encode_access_instruction_arg, \    26                      encode_function_pointer, encode_literal_instantiator, \    27                      encode_instantiator_pointer, encode_path, encode_symbol, \    28                      encode_type_attribute, is_type_attribute, \    29                      type_ops, typename_ops    30 from errors import InspectError, TranslateError    31 from os.path import exists, join    32 from os import makedirs    33 from referencing import Reference, combine_types    34 from results import Result    35 from transresults import TrConstantValueRef, TrInstanceRef, \    36                          TrLiteralSequenceRef, TrResolvedNameRef, \    37                          AliasResult, AttrResult, Expression, InstantiationResult, \    38                          InvocationResult, LogicalOperationResult, \    39                          LogicalResult, NegationResult, PredefinedConstantRef, \    40                          ReturnRef    41 from StringIO import StringIO    42 import compiler    43 import sys    44     45 class Translator(CommonOutput):    46     47     "A program translator."    48     49     def __init__(self, importer, deducer, optimiser, output):    50         self.importer = importer    51         self.deducer = deducer    52         self.optimiser = optimiser    53         self.output = output    54     55     def to_output(self, reset=False, debug=False, gc_sections=False):    56     57         "Write a program to the configured output directory."    58     59         # Make a directory for the final sources.    60     61         output = join(self.output, "src")    62     63         if not exists(output):    64             makedirs(output)    65     66         # Clean the output directory of irrelevant data.    67     68         self.check_output("debug=%r gc_sections=%r" % (debug, gc_sections))    69     70         for module in self.importer.modules.values():    71             output_filename = join(output, "%s.c" % module.name)    72     73             # Do not generate modules in the native package. They are provided    74             # by native functionality source files.    75     76             parts = module.name.split(".")    77     78             if parts[0] != "native" and \    79                (reset or is_newer(module.filename, output_filename)):    80     81                 tm = TranslatedModule(module.name, self.importer, self.deducer, self.optimiser)    82                 tm.translate(module.filename, output_filename)    83     84     85     86 def make_expression(expr):    87     88     "Make a new expression from the existing 'expr'."    89     90     if isinstance(expr, Result):    91         return expr    92     else:    93         return Expression(str(expr))    94     95     96     97 # The actual translation process itself.    98     99 class TranslatedModule(CommonModule):   100    101     "A module translator."   102    103     def __init__(self, name, importer, deducer, optimiser):   104         CommonModule.__init__(self, name, importer)   105         self.deducer = deducer   106         self.optimiser = optimiser   107    108         # Output stream.   109    110         self.out_toplevel = self.out = None   111         self.indent = 0   112         self.tabstop = "    "   113    114         # Recorded namespaces.   115    116         self.namespaces = []   117         self.in_conditional = False   118         self.in_parameter_list = False   119    120         # Exception raising adjustments.   121    122         self.in_try_finally = False   123         self.in_try_except = False   124    125         # Attribute access and accessor counting.   126    127         self.attr_accesses = {}   128         self.attr_accessors = {}   129    130         # Special variable usage.   131    132         self.temp_usage = {}   133    134         # Initialise some data used for attribute access generation.   135    136         self.init_substitutions()   137    138     def __repr__(self):   139         return "TranslatedModule(%r, %r)" % (self.name, self.importer)   140    141     def translate(self, filename, output_filename):   142    143         """   144         Parse the file having the given 'filename', writing the translation to   145         the given 'output_filename'.   146         """   147    148         self.parse_file(filename)   149    150         # Collect function namespaces for separate processing.   151    152         self.record_namespaces(self.astnode)   153    154         # Reset the lambda naming (in order to obtain the same names again) and   155         # translate the program.   156    157         self.reset_lambdas()   158    159         self.out_toplevel = self.out = open(output_filename, "w")   160         try:   161             self.start_output()   162    163             # Process namespaces, writing the translation.   164    165             for path, node in self.namespaces:   166                 self.process_namespace(path, node)   167    168             # Process the module namespace including class namespaces.   169    170             self.process_namespace([], self.astnode)   171    172         finally:   173             self.out.close()   174    175     def have_object(self):   176    177         "Return whether a namespace is a recorded object."   178    179         return self.importer.objects.get(self.get_namespace_path())   180    181     def get_builtin_class(self, name):   182    183         "Return a reference to the actual object providing 'name'."   184    185         return self.importer.get_object(get_builtin_class(name))   186    187     def is_method(self, path):   188    189         "Return whether 'path' is a method."   190    191         class_name, method_name = path.rsplit(".", 1)   192         return self.importer.classes.has_key(class_name) and class_name or None   193    194     def in_method(self):   195    196         "Return whether the current namespace provides a method."   197    198         return self.in_function and self.is_method(self.get_namespace_path())   199    200     # Namespace recording.   201    202     def record_namespaces(self, node):   203    204         "Process the program structure 'node', recording namespaces."   205    206         for n in node.getChildNodes():   207             self.record_namespaces_in_node(n)   208    209     def record_namespaces_in_node(self, node):   210    211         "Process the program structure 'node', recording namespaces."   212    213         # Function namespaces within modules, classes and other functions.   214         # Functions appearing within conditional statements are given arbitrary   215         # names.   216    217         if isinstance(node, compiler.ast.Function):   218             self.record_function_node(node, (self.in_conditional or self.in_function) and self.get_lambda_name() or node.name)   219    220         elif isinstance(node, compiler.ast.Lambda):   221             self.record_function_node(node, self.get_lambda_name())   222    223         # Classes are visited, but may be ignored if inside functions.   224    225         elif isinstance(node, compiler.ast.Class):   226             self.enter_namespace(node.name)   227             if self.have_object():   228                 self.record_namespaces(node)   229             self.exit_namespace()   230    231         # Conditional nodes are tracked so that function definitions may be   232         # handled. Since "for" loops are converted to "while" loops, they are   233         # included here.   234    235         elif isinstance(node, (compiler.ast.For, compiler.ast.If, compiler.ast.While)):   236             in_conditional = self.in_conditional   237             self.in_conditional = True   238             self.record_namespaces(node)   239             self.in_conditional = in_conditional   240    241         # All other nodes are processed depth-first.   242    243         else:   244             self.record_namespaces(node)   245    246     def record_function_node(self, n, name):   247    248         """   249         Record the given function, lambda, if expression or list comprehension   250         node 'n' with the given 'name'.   251         """   252    253         self.in_function = True   254         self.enter_namespace(name)   255    256         if self.have_object():   257    258             # Record the namespace path and the node itself.   259    260             self.namespaces.append((self.namespace_path[:], n))   261             self.record_namespaces_in_node(n.code)   262    263         self.exit_namespace()   264         self.in_function = False   265    266     # Constant referencing.   267    268     def get_literal_instance(self, n, name=None):   269    270         """   271         For node 'n', return a reference for the type of the given 'name', or if   272         'name' is not specified, deduce the type from the value.   273         """   274    275         # Handle stray None constants (Sliceobj seems to produce them).   276    277         if name is None and n.value is None:   278             return self.process_name_node(compiler.ast.Name("None"))   279    280         if name in ("dict", "list", "tuple"):   281             ref = self.get_builtin_class(name)   282             return self.process_literal_sequence_node(n, name, ref, TrLiteralSequenceRef)   283         else:   284             value, typename, encoding = self.get_constant_value(n.value, n.literals)   285             ref = self.get_builtin_class(typename)   286             value_type = ref.get_origin()   287    288             path = self.get_namespace_path()   289    290             # Obtain the local numbering of the constant and thus the   291             # locally-qualified name.   292    293             local_number = self.importer.all_constants[path][(value, value_type, encoding)]   294             constant_name = "$c%d" % local_number   295             objpath = self.get_object_path(constant_name)   296    297             # Obtain the unique identifier for the constant.   298    299             number = self.optimiser.constant_numbers[objpath]   300             return TrConstantValueRef(constant_name, ref.instance_of(), value, number)   301    302     # Namespace translation.   303    304     def process_namespace(self, path, node):   305    306         """   307         Process the namespace for the given 'path' defined by the given 'node'.   308         """   309    310         self.namespace_path = path   311    312         if isinstance(node, (compiler.ast.Function, compiler.ast.Lambda)):   313             self.in_function = True   314             self.process_function_body_node(node)   315         else:   316             self.in_function = False   317             self.function_target = 0   318             self.max_function_target = 0   319             self.context_index = 0   320             self.max_context_index = 0   321             self.accessor_index = 0   322             self.max_accessor_index = 0   323             self.start_module()   324             self.process_structure(node)   325             self.end_module()   326    327     def process_structure(self, node):   328    329         "Process the given 'node' or result."   330    331         # Handle processing requests on results.   332    333         if isinstance(node, Result):   334             return node   335    336         # Handle processing requests on nodes.   337    338         else:   339             l = CommonModule.process_structure(self, node)   340    341             # Return indications of return statement usage.   342    343             if l and isinstance(l[-1], ReturnRef):   344                 return l[-1]   345             else:   346                 return None   347    348     def process_structure_node(self, n):   349    350         "Process the individual node 'n'."   351    352         # Plain statements emit their expressions.   353    354         if isinstance(n, compiler.ast.Discard):   355             expr = self.process_structure_node(n.expr)   356             self.statement(expr)   357    358         # Module import declarations.   359    360         elif isinstance(n, compiler.ast.From):   361             self.process_from_node(n)   362    363         # Nodes using operator module functions.   364    365         elif isinstance(n, compiler.ast.Operator):   366             return self.process_operator_node(n)   367    368         elif isinstance(n, compiler.ast.AugAssign):   369             self.process_augassign_node(n)   370    371         elif isinstance(n, compiler.ast.Compare):   372             return self.process_compare_node(n)   373    374         elif isinstance(n, compiler.ast.Slice):   375             return self.process_slice_node(n)   376    377         elif isinstance(n, compiler.ast.Sliceobj):   378             return self.process_sliceobj_node(n)   379    380         elif isinstance(n, compiler.ast.Subscript):   381             return self.process_subscript_node(n)   382    383         # Classes are visited, but may be ignored if inside functions.   384    385         elif isinstance(n, compiler.ast.Class):   386             self.process_class_node(n)   387    388         # Functions within namespaces have any dynamic defaults initialised.   389    390         elif isinstance(n, compiler.ast.Function):   391             self.process_function_node(n)   392    393         # Lambdas are replaced with references to separately-generated   394         # functions.   395    396         elif isinstance(n, compiler.ast.Lambda):   397             return self.process_lambda_node(n)   398    399         # Assignments.   400    401         elif isinstance(n, compiler.ast.Assign):   402    403             # Handle each assignment node.   404    405             for node in n.nodes:   406                 self.process_assignment_node(node, n.expr)   407    408         # Accesses.   409    410         elif isinstance(n, compiler.ast.Getattr):   411             return self.process_attribute_access(n)   412    413         # Names.   414    415         elif isinstance(n, compiler.ast.Name):   416             return self.process_name_node(n)   417    418         # Loops and conditionals.   419    420         elif isinstance(n, compiler.ast.For):   421             self.process_for_node(n)   422    423         elif isinstance(n, compiler.ast.While):   424             self.process_while_node(n)   425    426         elif isinstance(n, compiler.ast.If):   427             self.process_if_node(n)   428    429         elif isinstance(n, (compiler.ast.And, compiler.ast.Or)):   430             return self.process_logical_node(n)   431    432         elif isinstance(n, compiler.ast.Not):   433             return self.process_not_node(n)   434    435         # Exception control-flow tracking.   436    437         elif isinstance(n, compiler.ast.TryExcept):   438             self.process_try_node(n)   439    440         elif isinstance(n, compiler.ast.TryFinally):   441             self.process_try_finally_node(n)   442    443         # Control-flow modification statements.   444    445         elif isinstance(n, compiler.ast.Break):   446             self.writestmt("break;")   447    448         elif isinstance(n, compiler.ast.Continue):   449             self.writestmt("continue;")   450    451         elif isinstance(n, compiler.ast.Raise):   452             self.process_raise_node(n)   453    454         elif isinstance(n, compiler.ast.Return):   455             return self.process_return_node(n)   456    457         # Print statements.   458    459         elif isinstance(n, (compiler.ast.Print, compiler.ast.Printnl)):   460             self.statement(self.process_print_node(n))   461    462         # Invocations.   463    464         elif isinstance(n, compiler.ast.CallFunc):   465             return self.process_invocation_node(n)   466    467         elif isinstance(n, compiler.ast.Keyword):   468             return self.process_structure_node(n.expr)   469    470         # Constant usage.   471    472         elif isinstance(n, compiler.ast.Const):   473             return self.get_literal_instance(n)   474    475         elif isinstance(n, compiler.ast.Dict):   476             return self.get_literal_instance(n, "dict")   477    478         elif isinstance(n, compiler.ast.List):   479             return self.get_literal_instance(n, "list")   480    481         elif isinstance(n, compiler.ast.Tuple):   482             return self.get_literal_instance(n, "tuple")   483    484         # All other nodes are processed depth-first.   485    486         else:   487             return self.process_structure(n)   488    489     def process_assignment_node(self, n, expr):   490    491         "Process the individual node 'n' to be assigned the contents of 'expr'."   492    493         # Names and attributes are assigned the entire expression.   494    495         if isinstance(n, compiler.ast.AssName):   496             name_ref = self.process_name_node(n, self.process_structure_node(expr))   497             self.statement(name_ref)   498    499             # Employ guards after assignments if required.   500    501             if expr and name_ref.is_name():   502                 self.generate_guard(name_ref.name)   503    504         elif isinstance(n, compiler.ast.AssAttr):   505             in_assignment = self.in_assignment   506             self.in_assignment = self.process_structure_node(expr)   507             self.statement(self.process_attribute_access(n))   508             self.in_assignment = in_assignment   509    510         # Lists and tuples are matched against the expression and their   511         # items assigned to expression items.   512    513         elif isinstance(n, (compiler.ast.AssList, compiler.ast.AssTuple)):   514             self.process_assignment_node_items(n, expr)   515    516         # Slices and subscripts are permitted within assignment nodes.   517    518         elif isinstance(n, compiler.ast.Slice):   519             self.statement(self.process_slice_node(n, expr))   520    521         elif isinstance(n, compiler.ast.Subscript):   522             self.statement(self.process_subscript_node(n, expr))   523    524     def process_attribute_access(self, n):   525    526         "Process the given attribute access node 'n'."   527    528         # Obtain any completed chain and return the reference to it.   529    530         attr_expr = self.process_attribute_chain(n)   531         if self.have_access_expression(n):   532             return attr_expr   533    534         # Where the start of the chain of attributes has been reached, process   535         # the complete access.   536    537         name_ref = attr_expr and attr_expr.is_name() and attr_expr   538         name = name_ref and self.get_name_for_tracking(name_ref.name, name_ref) or None   539    540         location = self.get_access_location(name, self.attrs)   541         refs = self.get_referenced_attributes(location)   542    543         # Generate access instructions.   544    545         subs = {   546             "<expr>" : attr_expr,   547             "<name>" : attr_expr,   548             "<assexpr>" : self.in_assignment,   549             }   550    551         subs.update(self.temp_subs)   552         subs.update(self.op_subs)   553    554         output = []   555         substituted = set()   556    557         # The context set or retrieved will be that used by any enclosing   558         # invocation.   559    560         accessor_index = self.accessor_index   561         context_index = self.context_index   562         context_identity = None   563         context_identity_verified = False   564         final_identity = None   565         accessor_test = False   566         accessor_stored = False   567    568         # Obtain encoded versions of each instruction, accumulating temporary   569         # variables.   570    571         for instruction in self.deducer.access_instructions[location]:   572    573             # Intercept a special instruction identifying the context.   574    575             if instruction[0] in ("<context_identity>", "<context_identity_verified>"):   576                 context_identity, _substituted = \   577                     encode_access_instruction_arg(instruction[1], subs, instruction[0],   578                                                   accessor_index, context_index)   579                 context_identity_verified = instruction[0] == "<context_identity_verified>"   580                 continue   581    582             # Intercept a special instruction identifying the target. The value   583             # is not encoded since it is used internally.   584    585             elif instruction[0] == "<final_identity>":   586                 final_identity = instruction[1]   587                 continue   588    589             # Modify test instructions.   590    591             elif instruction[0] in typename_ops or instruction[0] in type_ops:   592                 instruction = ("__to_error", instruction)   593                 accessor_test = True   594    595             # Intercept accessor storage.   596    597             elif instruction[0] == "<set_accessor>":   598                 accessor_stored = True   599    600             # Collect the encoded instruction, noting any temporary variables   601             # required by it.   602    603             encoded, _substituted = encode_access_instruction(instruction, subs,   604                                         accessor_index, context_index)   605             output.append(encoded)   606             substituted.update(_substituted)   607    608         # Record temporary name usage.   609    610         for sub in substituted:   611             if self.temp_subs.has_key(sub):   612                 self.record_temp(self.temp_subs[sub])   613    614         # Get full final identity details.   615    616         if final_identity and not refs:   617             refs = set([self.importer.identify(final_identity)])   618    619         del self.attrs[0]   620         return AttrResult(output, refs, location,   621                           context_identity, context_identity_verified,   622                           accessor_test, accessor_stored)   623    624     def init_substitutions(self):   625    626         """   627         Initialise substitutions, defining temporary variable mappings, some of   628         which are also used as substitutions, together with operation mappings   629         used as substitutions in instructions defined by the optimiser.   630         """   631    632         self.temp_subs = {   633    634             # Substitutions used by instructions.   635    636             "<private_context>" : "__tmp_private_context",   637             "<target_accessor>" : "__tmp_target_value",   638    639             # Mappings to be replaced by those given below.   640    641             "<accessor>" : "__tmp_values",   642             "<context>" : "__tmp_contexts",   643             "<test_context_revert>" : "__tmp_contexts",   644             "<test_context_static>" : "__tmp_contexts",   645             "<set_context>" : "__tmp_contexts",   646             "<set_private_context>" : "__tmp_private_context",   647             "<set_accessor>" : "__tmp_values",   648             "<set_target_accessor>" : "__tmp_target_value",   649             }   650    651         self.op_subs = {   652             "<accessor>" : "__get_accessor",   653             "<context>" : "__get_context",   654             "<test_context_revert>" : "__test_context_revert",   655             "<test_context_static>" : "__test_context_static",   656             "<set_context>" : "__set_context",   657             "<set_private_context>" : "__set_private_context",   658             "<set_accessor>" : "__set_accessor",   659             "<set_target_accessor>" : "__set_target_accessor",   660             }   661    662     def get_referenced_attributes(self, location):   663    664         """   665         Convert 'location' to the form used by the deducer and retrieve any   666         identified attributes.   667         """   668    669         # Determine whether any deduced references refer to the accessed   670         # attribute.   671    672         attrnames = location.attrnames   673         attrnames = attrnames and attrnames.split(".")   674         remaining = attrnames and len(attrnames) > 1   675    676         access_location = self.deducer.const_accesses.get(location)   677    678         if remaining and not access_location:   679             return set()   680    681         return self.deducer.get_references_for_access(access_location or location)   682    683     def get_referenced_attribute_invocations(self, location):   684    685         """   686         Convert 'location' to the form used by the deducer and retrieve any   687         identified attribute invocation details.   688         """   689    690         access_location = self.deducer.const_accesses.get(location)   691         return self.deducer.reference_invocations_unsuitable.get(access_location or location)   692    693     def get_accessor_kinds(self, location):   694    695         "Return the accessor kinds for 'location'."   696    697         return self.deducer.accessor_kinds.get(location)   698    699     def get_access_location(self, name, attrnames=None):   700    701         """   702         Using the current namespace, the given 'name', and the 'attrnames'   703         employed in an access, return the access location.   704         """   705    706         path = self.get_path_for_access()   707    708         # Get the location used by the deducer and optimiser and find any   709         # recorded access.   710    711         attrnames = attrnames and ".".join(self.attrs)   712         access_number = self.get_access_number(path, name, attrnames)   713         self.update_access_number(path, name, attrnames)   714         return AccessLocation(path, name, attrnames, access_number)   715    716     def get_access_number(self, path, name, attrnames):   717         access = name, attrnames   718         if self.attr_accesses.has_key(path) and self.attr_accesses[path].has_key(access):   719             return self.attr_accesses[path][access]   720         else:   721             return 0   722    723     def update_access_number(self, path, name, attrnames):   724         access = name, attrnames   725         if name:   726             init_item(self.attr_accesses, path, dict)   727             init_item(self.attr_accesses[path], access, lambda: 0)   728             self.attr_accesses[path][access] += 1   729    730     def get_accessor_location(self, name):   731    732         """   733         Using the current namespace and the given 'name', return the accessor   734         location.   735         """   736    737         path = self.get_path_for_access()   738    739         # Get the location used by the deducer and optimiser and find any   740         # recorded accessor.   741    742         version = self.get_accessor_number(path, name)   743         self.update_accessor_number(path, name)   744         return Location(path, name, None, version)   745    746     def get_accessor_number(self, path, name):   747         if self.attr_accessors.has_key(path) and self.attr_accessors[path].has_key(name):   748             return self.attr_accessors[path][name]   749         else:   750             return 0   751    752     def update_accessor_number(self, path, name):   753         if name:   754             init_item(self.attr_accessors, path, dict)   755             init_item(self.attr_accessors[path], name, lambda: 0)   756             self.attr_accessors[path][name] += 1   757    758     def process_class_node(self, n):   759    760         "Process the given class node 'n'."   761    762         class_name = self.get_object_path(n.name)   763    764         # Where a class is set conditionally or where the name may refer to   765         # different values, assign the name.   766    767         ref = self.importer.identify(class_name)   768    769         if not ref.static():   770             self.process_assignment_for_object(n.name,   771                 make_expression("__ATTRVALUE(&%s)" % encode_path(class_name)))   772    773         self.enter_namespace(n.name)   774    775         if self.have_object():   776             self.write_comment("Class: %s" % class_name)   777    778             self.initialise_inherited_members(class_name)   779    780             self.process_structure(n)   781             self.write_comment("End class: %s" % class_name)   782    783         self.exit_namespace()   784    785     def initialise_inherited_members(self, class_name):   786    787         "Initialise members of 'class_name' inherited from its ancestors."   788    789         for name, path in self.importer.all_class_attrs[class_name].items():   790             target = "%s.%s" % (class_name, name)   791    792             # Ignore attributes with definitions.   793    794             ref = self.importer.identify(target)   795             if ref:   796                 continue   797    798             # Ignore special type attributes.   799    800             if is_type_attribute(name):   801                 continue   802    803             # Reference inherited attributes.   804    805             ref = self.importer.identify(path)   806             if ref and not ref.static():   807                 parent, attrname = path.rsplit(".", 1)   808    809                 self.writestmt("__store_via_object(&%s, %s, __load_via_object(&%s, %s));" % (   810                     encode_path(class_name), name,   811                     encode_path(parent), attrname   812                     ))   813    814     def process_from_node(self, n):   815    816         "Process the given node 'n', importing from another module."   817    818         path = self.get_namespace_path()   819    820         # Attempt to obtain the referenced objects.   821    822         for name, alias in n.names:   823             if name == "*":   824                 raise InspectError("Only explicitly specified names can be imported from modules.", path, n)   825    826             # Obtain the path of the assigned name.   827    828             objpath = self.get_object_path(alias or name)   829    830             # Obtain the identity of the name.   831    832             ref = self.importer.identify(objpath)   833    834             # Where the name is not static, assign the value.   835    836             if ref and not ref.static() and ref.get_name():   837                 self.writestmt("%s;" %    838                     TrResolvedNameRef(alias or name, Reference("<var>", None, objpath),   839                                       expr=TrResolvedNameRef(name, ref)))   840    841     def process_function_body_node(self, n):   842    843         """   844         Process the given function, lambda, if expression or list comprehension   845         node 'n', generating the body.   846         """   847    848         function_name = self.get_namespace_path()   849         self.start_function(function_name)   850    851         # Process the function body.   852    853         in_conditional = self.in_conditional   854         self.in_conditional = False   855         self.function_target = 0   856         self.max_function_target = 0   857         self.context_index = 0   858         self.max_context_index = 0   859         self.accessor_index = 0   860         self.max_accessor_index = 0   861    862         # Volatile locals for exception handling.   863    864         self.volatile_locals = set()   865    866         # Process any guards defined for the parameters.   867    868         for name in self.importer.function_parameters.get(function_name):   869             self.generate_guard(name)   870    871         # Also support self in methods, since some mix-in methods may only work   872         # with certain descendant classes.   873    874         if self.in_method():   875             self.generate_guard("self")   876    877         # Make assignments for .name entries in the parameters, provided this is   878         # a method.   879    880         if self.in_method():   881             for name in self.importer.function_attr_initialisers.get(function_name) or []:   882                 self.process_assignment_node(   883                     compiler.ast.AssAttr(compiler.ast.Name("self"), name, "OP_ASSIGN"),   884                     compiler.ast.Name(name))   885    886         # Produce the body and any additional return statement.   887    888         expr = self.process_structure_node(n.code) or \   889                self.in_method() and \   890                    function_name.rsplit(".", 1)[-1] == "__init__" and \   891                    TrResolvedNameRef("self", self.importer.function_locals[function_name]["self"]) or \   892                PredefinedConstantRef("None")   893    894         if not isinstance(expr, ReturnRef):   895             self.writestmt("return %s;" % expr)   896    897         self.in_conditional = in_conditional   898    899         self.end_function(function_name)   900    901     def generate_guard(self, name):   902    903         """   904         Get the accessor details for 'name', found in the current namespace, and   905         generate any guards defined for it.   906         """   907    908         # Obtain the location, keeping track of assignment versions.   909    910         location = self.get_accessor_location(name)   911         test = self.deducer.accessor_guard_tests.get(location)   912    913         # Generate any guard from the deduced information.   914    915         if test:   916             guard, guard_type = test   917    918             if guard == "specific":   919                 ref = first(self.deducer.accessor_all_types[location])   920                 argstr = "&%s" % encode_path(ref.get_origin())   921             elif guard == "common":   922                 ref = first(self.deducer.accessor_all_general_types[location])   923                 argstr = encode_path(encode_type_attribute(ref.get_origin()))   924             else:   925                 return   926    927             # Write a test that raises a TypeError upon failure.   928    929             self.writestmt("if (!__test_%s_%s(__VALUE(%s), %s)) __raise_type_error();" % (   930                 guard, guard_type, encode_path(name), argstr))   931    932     def process_function_node(self, n):   933    934         """   935         Process the given function, lambda, if expression or list comprehension   936         node 'n', generating any initialisation statements.   937         """   938    939         # Where a function is declared conditionally, use a separate name for   940         # the definition, and assign the definition to the stated name.   941    942         original_name = n.name   943    944         if self.in_conditional or self.in_function:   945             name = self.get_lambda_name()   946         else:   947             name = n.name   948    949         objpath = self.get_object_path(name)   950    951         # Obtain details of the defaults.   952    953         defaults = self.process_function_defaults(n, name, objpath)   954         if defaults:   955             for default in defaults:   956                 self.writeline("%s;" % default)   957    958         # Where a function is set conditionally or where the name may refer to   959         # different values, assign the name.   960    961         ref = self.importer.identify(objpath)   962    963         if self.in_conditional or self.in_function:   964             self.process_assignment_for_object(original_name, compiler.ast.Name(name))   965         elif not ref.static():   966             context = self.is_method(objpath)   967    968             self.process_assignment_for_object(original_name,   969                 make_expression("__ATTRVALUE(&%s)" % encode_path(objpath)))   970    971     def process_function_defaults(self, n, name, objpath, instance_name=None):   972    973         """   974         Process the given function or lambda node 'n', initialising defaults   975         that are dynamically set. The given 'name' indicates the name of the   976         function. The given 'objpath' indicates the origin of the function.   977         The given 'instance_name' indicates the name of any separate instance   978         of the function created to hold the defaults.   979    980         Return a list of operations setting defaults on a function instance.   981         """   982    983         function_name = self.get_object_path(name)   984         function_defaults = self.importer.function_defaults.get(function_name)   985         if not function_defaults:   986             return None   987    988         # Determine whether any unidentified defaults are involved.   989    990         for argname, default in function_defaults:   991             if not default.static():   992                 break   993         else:   994             return None   995    996         # Handle bound methods.   997    998         if not instance_name:   999             instance_name = "&%s" % encode_path(objpath)  1000         else:  1001             instance_name = "__VALUE(%s)" % instance_name  1002   1003         # Where defaults are involved but cannot be identified, obtain a new  1004         # instance of the lambda and populate the defaults.  1005   1006         defaults = []  1007   1008         # Join the original defaults with the inspected defaults.  1009   1010         original_defaults = [(argname, default) for (argname, default) in compiler.ast.get_defaults(n) if default]  1011   1012         for i, (original, inspected) in enumerate(map(None, original_defaults, function_defaults)):  1013   1014             # Obtain any reference for the default.  1015   1016             if original:  1017                 argname, default = original  1018                 name_ref = self.process_structure_node(default)  1019             elif inspected:  1020                 argname, default = inspected  1021                 name_ref = TrResolvedNameRef(argname, default)  1022             else:  1023                 continue  1024   1025             # Generate default initialisers except when constants are employed.  1026             # Constants should be used when populating the function structures.  1027   1028             if name_ref and not isinstance(name_ref, TrConstantValueRef):  1029                 defaults.append("__SETDEFAULT(%s, %s, %s)" % (instance_name, i, name_ref))  1030   1031         return defaults  1032   1033     def process_if_node(self, n):  1034   1035         """  1036         Process the given "if" node 'n'.  1037         """  1038   1039         first = True  1040         for test, body in n.tests:  1041             test_ref = self.process_structure_node(test)  1042             self.start_if(first, test_ref)  1043   1044             in_conditional = self.in_conditional  1045             self.in_conditional = True  1046             self.process_structure_node(body)  1047             self.in_conditional = in_conditional  1048   1049             self.end_if()  1050             first = False  1051   1052         if n.else_:  1053             self.start_else()  1054             self.process_structure_node(n.else_)  1055             self.end_else()  1056   1057         print >>self.out  1058   1059     def process_invocation_node(self, n):  1060   1061         "Process the given invocation node 'n'."  1062   1063         # Process the expression.  1064   1065         expr = self.process_structure_node(n.node)  1066   1067         # Obtain details of the invocation expression.  1068   1069         objpath = expr.get_origin()  1070         location = expr.access_location()  1071         refs = expr.references()  1072   1073         # Identified target details.  1074   1075         target = None  1076         target_structure = None  1077   1078         # Specific function target information.  1079   1080         function = None  1081   1082         # Instantiation involvement.  1083   1084         instantiation = False  1085         literal_instantiation = False  1086   1087         # Invocation requirements.  1088   1089         context_required = True  1090         have_access_context = isinstance(expr, AttrResult)  1091   1092         # The context identity is merely the thing providing the context.  1093         # A verified context is one that does not need further testing for  1094         # suitability.  1095   1096         context_identity = have_access_context and expr.context()  1097         context_verified = have_access_context and expr.context_verified()  1098   1099         # The presence of any test operations in the accessor expression.  1100         # With such operations present, the expression cannot be eliminated.  1101   1102         tests_accessor = have_access_context and expr.tests_accessor()  1103         stores_accessor = have_access_context and expr.stores_accessor()  1104   1105         # Parameter details and parameter list dimensions.  1106   1107         parameters = None  1108         num_parameters = None  1109         num_defaults = None  1110   1111         # Obtain details of the callable and of its parameters.  1112   1113         # Literals may be instantiated specially.  1114   1115         if expr.is_name() and expr.name.startswith("$L") and objpath:  1116             instantiation = literal_instantiation = objpath  1117             target = encode_literal_instantiator(objpath)  1118             context_required = False  1119   1120         # Identified targets employ function pointers directly.  1121   1122         elif objpath:  1123             parameters = self.importer.function_parameters.get(objpath)  1124             function_defaults = self.importer.function_defaults.get(objpath)  1125             num_parameters = parameters and len(parameters) or 0  1126             num_defaults = function_defaults and len(function_defaults) or 0  1127   1128             # Class invocation involves instantiators.  1129   1130             if expr.has_kind("<class>"):  1131                 instantiation = objpath  1132                 target = encode_instantiator_pointer(objpath)  1133                 init_ref = self.importer.all_class_attrs[objpath]["__init__"]  1134                 target_structure = "&%s" % encode_path(init_ref)  1135                 context_required = False  1136   1137             # Only plain functions and bound methods employ function pointers.  1138   1139             elif expr.has_kind("<function>"):  1140                 function = objpath  1141   1142                 # Test for functions and methods.  1143   1144                 context_required = self.is_method(objpath)  1145   1146                 accessor_kinds = location and self.get_accessor_kinds(location)  1147   1148                 instance_accessor = accessor_kinds and \  1149                                     len(accessor_kinds) == 1 and \  1150                                     first(accessor_kinds) == "<instance>"  1151   1152                 # Only identify certain bound methods or functions.  1153   1154                 if not context_required or instance_accessor:  1155                     target = encode_function_pointer(objpath)  1156   1157                 # Access bound method defaults even if it is not clear whether  1158                 # the accessor is appropriate.  1159   1160                 target_structure = "&%s" % encode_path(objpath)  1161   1162         # Other targets are retrieved at run-time.  1163   1164         else:  1165             if location:  1166                 attrnames = location.attrnames  1167                 attrname = attrnames and attrnames.rsplit(".", 1)[-1]  1168   1169                 # Determine common aspects of any identifiable targets.  1170   1171                 if attrname or refs:  1172                     all_params = set()  1173                     all_defaults = set()  1174                     min_params = set()  1175                     max_params = set()  1176   1177                     # Employ references from the expression or find all  1178                     # possible attributes for the given attribute name.  1179   1180                     refs = refs or self.get_attributes_for_attrname(attrname)  1181   1182                     # Obtain parameters and defaults for each possible target.  1183   1184                     for ref in refs:  1185                         origin = ref.get_origin()  1186                         params = self.importer.function_parameters.get(origin)  1187   1188                         defaults = self.importer.function_defaults.get(origin)  1189                         if defaults is not None:  1190                             all_defaults.add(tuple(defaults))  1191   1192                         if params is not None:  1193                             all_params.add(tuple(params))  1194                             min_params.add(len(params) - (defaults and len(defaults) or 0))  1195                             max_params.add(len(params))  1196                         else:  1197                             refs = set()  1198                             break  1199   1200                     # Where the parameters and defaults are always the same,  1201                     # permit populating them in advance.  1202   1203                     if refs:  1204                         if self.uses_keyword_arguments(n):  1205                             if len(all_params) == 1 and (not all_defaults or len(all_defaults) == 1):  1206                                 parameters = first(all_params)  1207                                 function_defaults = all_defaults and first(all_defaults) or []  1208                                 num_parameters = parameters and len(parameters) or 0  1209                                 num_defaults = function_defaults and len(function_defaults) or 0  1210                         else:  1211                             if len(min_params) == 1 and len(max_params) == 1:  1212                                 num_parameters = first(max_params)  1213                                 num_defaults = first(max_params) - first(min_params)  1214   1215             # Some information about the target may be available and be used to  1216             # provide warnings about argument compatibility.  1217   1218             if self.importer.give_warning("args"):  1219                 unsuitable = self.get_referenced_attribute_invocations(location)  1220   1221                 if unsuitable:  1222                     for ref in unsuitable:  1223                         _objpath = ref.get_origin()  1224                         print >>sys.stderr, \  1225                             "In %s, at line %d, inappropriate number of " \  1226                             "arguments given. Need %d arguments to call %s." % (  1227                             self.get_namespace_path(), n.lineno,  1228                             len(self.importer.function_parameters[_objpath]),  1229                             _objpath)  1230   1231         # Logical statement about available parameter information.  1232   1233         known_parameters = num_parameters is not None  1234   1235         # The source of context information: target or temporary.  1236   1237         need_context_target = context_required and not have_access_context  1238   1239         need_context_stored = context_required and context_identity and \  1240                               context_identity.startswith("__get_context")  1241   1242         # Determine any readily-accessible target identity.  1243   1244         target_named = expr.is_name() and str(expr) or None  1245         target_identity = target or target_named  1246   1247         # Use of target information to populate defaults.  1248   1249         defaults_target_var = not (parameters and function_defaults is not None) and \  1250                               known_parameters and len(n.args) < num_parameters  1251   1252         # Use of a temporary target variable in these situations:  1253         #  1254         # A target provided by an expression needed for defaults.  1255         #  1256         # A target providing the context but not using a name to do so.  1257         #  1258         # A target expression involving the definition of a context which may  1259         # then be evaluated and stored to ensure that the context is available  1260         # during argument evaluation.  1261         #  1262         # An expression featuring an accessor test.  1263   1264         need_target_stored = defaults_target_var and not target_identity or \  1265                              need_context_target and not target_identity or \  1266                              need_context_stored or \  1267                              tests_accessor and not target  1268   1269         # Define stored target details.  1270   1271         target_stored = "__tmp_targets[%d]" % self.function_target  1272         target_var = need_target_stored and target_stored or target_identity  1273   1274         if need_target_stored:  1275             self.record_temp("__tmp_targets")  1276   1277         if need_context_stored:  1278             self.record_temp("__tmp_contexts")  1279   1280         if stores_accessor:  1281             self.record_temp("__tmp_values")  1282   1283         # Arguments are presented in a temporary frame array with any context  1284         # always being the first argument. Where it would be unused, it may be  1285         # set to null.  1286   1287         if context_required:  1288             if have_access_context:  1289                 context_arg = context_identity  1290             else:  1291                 context_arg = "__CONTEXT_AS_VALUE(%s)" % target_var  1292         else:  1293             context_arg = "__NULL"  1294   1295         args = [context_arg]  1296   1297         # Complete the array with null values, permitting tests for a complete  1298         # set of arguments.  1299   1300         args += [None] * (num_parameters is None and len(n.args) or num_parameters is not None and num_parameters or 0)  1301         kwcodes = []  1302         kwargs = []  1303   1304         # Any invocations in the arguments will store target details in a  1305         # different location.  1306   1307         function_target = self.function_target  1308         context_index = self.context_index  1309         accessor_index = self.accessor_index  1310   1311         if need_target_stored:  1312             self.next_target()  1313   1314         if need_context_stored:  1315             self.next_context()  1316   1317         if stores_accessor:  1318             self.next_accessor()  1319   1320         in_parameter_list = self.in_parameter_list  1321         self.in_parameter_list = True  1322   1323         for i, arg in enumerate(n.args):  1324             argexpr = self.process_structure_node(arg)  1325   1326             # Store a keyword argument, either in the argument list or  1327             # in a separate keyword argument list for subsequent lookup.  1328   1329             if isinstance(arg, compiler.ast.Keyword):  1330   1331                 # With knowledge of the target, store the keyword  1332                 # argument directly.  1333   1334                 if parameters:  1335                     try:  1336                         argnum = parameters.index(arg.name)  1337                     except ValueError:  1338                         raise TranslateError("Argument %s is not recognised." % arg.name,  1339                                              self.get_namespace_path(), n)  1340                     args[argnum+1] = str(argexpr)  1341   1342                 # Otherwise, store the details in a separate collection.  1343   1344                 else:  1345                     kwargs.append(str(argexpr))  1346                     kwcodes.append("{%s, %s}" % (  1347                         encode_ppos(arg.name), encode_pcode(arg.name)))  1348   1349             # Store non-keyword arguments in the argument list, rejecting  1350             # superfluous arguments.  1351   1352             else:  1353                 try:  1354                     args[i+1] = str(argexpr)  1355                 except IndexError:  1356                     raise TranslateError("Too many arguments specified.",  1357                                          self.get_namespace_path(), n)  1358   1359         # Reference the current target again.  1360   1361         self.in_parameter_list = in_parameter_list  1362   1363         if not self.in_parameter_list:  1364             self.function_target = function_target  1365             self.context_index = context_index  1366             self.accessor_index = accessor_index  1367   1368         # Defaults are added to the frame where arguments are missing.  1369   1370         if parameters and function_defaults is not None:  1371   1372             # Visit each default and set any missing arguments. Where keyword  1373             # arguments have been used, the defaults must be inspected and, if  1374             # necessary, inserted into gaps in the argument list.  1375   1376             for i, (argname, default) in enumerate(function_defaults):  1377                 argnum = parameters.index(argname)  1378                 if not args[argnum+1]:  1379                     args[argnum+1] = "__GETDEFAULT(%s, %d)" % (target_structure, i)  1380   1381         elif known_parameters:  1382   1383             # No specific parameter details are provided, but no keyword  1384             # arguments are used. Thus, defaults can be supplied using position  1385             # information only.  1386   1387             i = len(n.args)  1388             pos = i - (num_parameters - num_defaults)  1389             while i < num_parameters:  1390                 args[i+1] = "__GETDEFAULT(%s.value, %d)" % (target_var, pos)  1391                 i += 1  1392                 pos += 1  1393   1394         # Test for missing arguments.  1395   1396         if None in args:  1397             raise TranslateError("Not all arguments supplied.",  1398                                  self.get_namespace_path(), n)  1399   1400         # Encode the arguments.  1401   1402         # Where literal instantiation is occurring, add an argument indicating  1403         # the number of values. The context is excluded.  1404   1405         if literal_instantiation:  1406             argstr = "%d, %s" % (len(args) - 1, ", ".join(args[1:]))  1407         else:  1408             argstr = ", ".join(args)  1409   1410         kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0"  1411         kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0"  1412   1413         # First, the invocation expression is presented.  1414   1415         stages = []  1416         emit = stages.append  1417   1418         # Assign and yield any stored target.  1419         # The context may be set in the expression.  1420   1421         if need_target_stored:  1422             emit("%s = %s" % (target_var, expr))  1423             target_expr = target_var  1424   1425         # Otherwise, retain the expression for later use.  1426   1427         else:  1428             target_expr = str(expr)  1429   1430         # Any specific callable is then obtained for invocation.  1431   1432         if target:  1433   1434             # An expression involving a test of the accessor providing the target.  1435             # This must be emitted in order to perform the test.  1436   1437             if tests_accessor:  1438                 emit(str(expr))  1439   1440             emit(target)  1441   1442         # Methods accessed via unidentified accessors are obtained for  1443         # invocation.  1444   1445         elif function:  1446             if context_required:  1447   1448                 # Avoid further context testing if appropriate.  1449   1450                 if have_access_context and context_verified:  1451                     emit("__get_function_member(%s)" % target_expr)  1452   1453                 # Otherwise, test the context for the function/method.  1454   1455                 else:  1456                     emit("__get_function(%s, %s)" % (context_arg, target_expr))  1457             else:  1458                 emit("_get_function_member(%s)" % target_expr)  1459   1460         # With known parameters, the target can be tested.  1461   1462         elif known_parameters:  1463             if self.always_callable(refs):  1464                 if context_verified:  1465                     emit("__get_function_member(%s)" % target_expr)  1466                 else:  1467                     emit("__get_function(%s, %s)" % (context_arg, target_expr))  1468             else:  1469                 emit("__check_and_get_function(%s, %s)" % (context_arg, target_expr))  1470   1471         # With a known target, the function is obtained directly and called.  1472         # By putting the invocation at the end of the final element in the  1473         # instruction sequence (the stages), the result becomes the result of  1474         # the sequence. Moreover, the parameters become part of the sequence  1475         # and thereby participate in a guaranteed evaluation order.  1476   1477         if target or function or known_parameters:  1478             stages[-1] += "(%s)" % argstr  1479             if instantiation:  1480                 return InstantiationResult(instantiation, stages)  1481             else:  1482                 return InvocationResult(stages)  1483   1484         # With unknown targets, the generic invocation function is applied to  1485         # the callable and argument collections.  1486   1487         else:  1488             emit("__invoke(\n%s,\n%d, %d, %s, %s,\n%d, %s\n)" % (  1489                 target_expr,  1490                 self.always_callable(refs) and 1 or 0,  1491                 len(kwargs), kwcodestr, kwargstr,  1492                 len(args), "__ARGS(%s)" % argstr))  1493             return InvocationResult(stages)  1494   1495     def next_target(self):  1496   1497         "Allocate the next function target storage."  1498   1499         self.function_target += 1  1500         self.max_function_target = max(self.function_target, self.max_function_target)  1501   1502     def next_context(self):  1503   1504         "Allocate the next context value storage."  1505   1506         self.context_index += 1  1507         self.max_context_index = max(self.context_index, self.max_context_index)  1508   1509     def next_accessor(self):  1510   1511         "Allocate the next accessor value storage."  1512   1513         self.accessor_index += 1  1514         self.max_accessor_index = max(self.accessor_index, self.max_accessor_index)  1515   1516     def always_callable(self, refs):  1517   1518         "Determine whether all 'refs' are callable."  1519   1520         if not refs:  1521             return False  1522   1523         for ref in refs:  1524             if not ref.has_kind("<function>") and not self.importer.get_attributes(ref, "__fn__"):  1525                 return False  1526   1527         return True  1528   1529     def need_default_arguments(self, objpath, nargs):  1530   1531         """  1532         Return whether any default arguments are needed when invoking the object  1533         given by 'objpath'.  1534         """  1535   1536         parameters = self.importer.function_parameters.get(objpath)  1537         return nargs < len(parameters)  1538   1539     def uses_keyword_arguments(self, n):  1540   1541         "Return whether invocation node 'n' uses keyword arguments."  1542   1543         for arg in enumerate(n.args):  1544             if isinstance(arg, compiler.ast.Keyword):  1545                 return True  1546   1547         return False  1548   1549     def get_attributes_for_attrname(self, attrname):  1550   1551         "Return a set of all attributes exposed by 'attrname'."  1552   1553         usage = [(attrname, True, False)]  1554         class_types = self.deducer.get_class_types_for_usage(usage)  1555         instance_types = self.deducer.get_instance_types_for_usage(usage)  1556         module_types = self.deducer.get_module_types_for_usage(usage)  1557         attrs = set()  1558   1559         for ref in combine_types(class_types, instance_types, module_types):  1560             attrs.update(self.importer.get_attributes(ref, attrname))  1561   1562         return attrs  1563   1564     def process_lambda_node(self, n):  1565   1566         "Process the given lambda node 'n'."  1567   1568         name = self.get_lambda_name()  1569         function_name = self.get_object_path(name)  1570         instance_name = "__get_accessor(%d)" % self.accessor_index  1571   1572         defaults = self.process_function_defaults(n, name, function_name, instance_name)  1573   1574         # Without defaults, produce an attribute referring to the function.  1575   1576         if not defaults:  1577             return make_expression("__ATTRVALUE(&%s)" % encode_path(function_name))  1578   1579         # With defaults, copy the function structure and set the defaults on the  1580         # copy.  1581   1582         else:  1583             self.record_temp("__tmp_values")  1584             return make_expression("""\  1585 (__set_accessor(%d, __ATTRVALUE(__COPY(&%s, sizeof(%s)))),  1586  %s,  1587  __get_accessor(%d))""" % (  1588                 self.accessor_index,  1589                 encode_path(function_name),  1590                 encode_symbol("obj", function_name),  1591                 ", ".join(defaults),  1592                 self.accessor_index))  1593   1594     def process_logical_node(self, n):  1595   1596         "Process the given operator node 'n'."  1597   1598         self.record_temp("__tmp_result")  1599   1600         conjunction = isinstance(n, compiler.ast.And)  1601         results = []  1602   1603         for node in n.nodes:  1604             results.append(self.process_structure_node(node))  1605   1606         return LogicalOperationResult(results, conjunction)  1607   1608     def process_name_node(self, n, expr=None):  1609   1610         "Process the given name node 'n' with the optional assignment 'expr'."  1611   1612         # Determine whether the name refers to a static external entity.  1613   1614         if n.name in predefined_constants:  1615             return PredefinedConstantRef(n.name, expr)  1616   1617         # Convert literal references, operator function names, and print  1618         # function names to references.  1619   1620         elif n.name.startswith("$L") or n.name.startswith("$op") or \  1621              n.name.startswith("$seq") or n.name.startswith("$print"):  1622   1623             ref, paths = self.importer.get_module(self.name).special[n.name]  1624             return TrResolvedNameRef(n.name, ref)  1625   1626         # Get the appropriate name for the name reference, using the same method  1627         # as in the inspector.  1628   1629         path = self.get_namespace_path()  1630         objpath = self.get_object_path(n.name)  1631   1632         # Determine any assigned globals.  1633   1634         globals = self.importer.get_module(self.name).scope_globals.get(path)  1635   1636         # Explicitly declared globals.  1637   1638         if globals and n.name in globals:  1639             objpath = self.get_global_path(n.name)  1640             is_global = True  1641   1642         # Implicitly referenced globals in functions.  1643   1644         elif self.in_function:  1645             is_global = n.name not in self.importer.function_locals[path]  1646   1647         # Implicitly referenced globals elsewhere.  1648   1649         else:  1650             namespace = self.importer.identify(path)  1651             is_global = not self.importer.get_attributes(namespace, n.name)  1652   1653         # Get the static identity of the name.  1654   1655         ref = self.importer.identify(objpath)  1656         if ref and not ref.get_name():  1657             ref = ref.alias(objpath)  1658   1659         # Obtain any resolved names for non-assignment names.  1660   1661         if not expr and not ref and self.in_function:  1662             locals = self.importer.function_locals.get(path)  1663             ref = locals and locals.get(n.name)  1664   1665         # Find any invocation or alias details.  1666   1667         name = self.get_name_for_tracking(n.name, is_global=is_global)  1668         location = not expr and self.get_access_location(name) or None  1669   1670         # Mark any local assignments as volatile in exception blocks.  1671   1672         if expr and self.in_function and not is_global and self.in_try_except:  1673             self.make_volatile(n.name)  1674   1675         # Qualified names are used for resolved static references or for  1676         # static namespace members. The reference should be configured to return  1677         # such names.  1678   1679         name_ref = TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global,  1680                                      location=location)  1681         return not expr and self.get_aliases(name_ref) or name_ref  1682   1683     def get_aliases(self, name_ref):  1684   1685         "Return alias references for the given 'name_ref'."  1686   1687         location = name_ref.access_location()  1688         accessor_locations = self.deducer.access_index.get(location)  1689   1690         if not accessor_locations:  1691             return None  1692   1693         refs = set()  1694   1695         for accessor_location in accessor_locations:  1696             alias_refs = self.deducer.referenced_objects.get(accessor_location)  1697             if alias_refs:  1698                 refs.update(alias_refs)  1699   1700         if refs:  1701             return AliasResult(name_ref, refs, location)  1702         else:  1703             return None  1704   1705     def make_volatile(self, name):  1706   1707         "Record 'name' as volatile in the current namespace."  1708   1709         self.volatile_locals.add(name)  1710   1711     def process_not_node(self, n):  1712   1713         "Process the given operator node 'n'."  1714   1715         return self.make_negation(self.process_structure_node(n.expr))  1716   1717     def process_raise_node(self, n):  1718   1719         "Process the given raise node 'n'."  1720   1721         # NOTE: Determine which raise statement variants should be permitted.  1722   1723         if n.expr1:  1724   1725             # Names with accompanying arguments are treated like invocations.  1726   1727             if n.expr2:  1728                 call = compiler.ast.CallFunc(n.expr1, [n.expr2])  1729                 exc = self.process_structure_node(call)  1730                 self.writestmt("__Raise(%s);" % exc)  1731   1732             # Raise instances, testing the kind at run-time if necessary and  1733             # instantiating any non-instance.  1734   1735             else:  1736                 exc = self.process_structure_node(n.expr1)  1737   1738                 if isinstance(exc, TrInstanceRef):  1739                     self.writestmt("__Raise(%s);" % exc)  1740                 else:  1741                     self.writestmt("__Raise(__ensure_instance(%s));" % exc)  1742         else:  1743             self.writestmt("__Throw(__tmp_exc);")  1744   1745     def process_return_node(self, n):  1746   1747         "Process the given return node 'n'."  1748   1749         expr = self.process_structure_node(n.value) or PredefinedConstantRef("None")  1750         if self.in_try_finally or self.in_try_except:  1751             self.writestmt("__Return(%s);" % expr)  1752         else:  1753             self.writestmt("return %s;" % expr)  1754   1755         return ReturnRef()  1756   1757     def process_try_node(self, n):  1758   1759         """  1760         Process the given "try...except" node 'n'.  1761         """  1762   1763         in_try_except = self.in_try_except  1764         self.in_try_except = True  1765   1766         # Use macros to implement exception handling.  1767   1768         self.writestmt("__Try")  1769         self.writeline("{")  1770         self.indent += 1  1771         self.process_structure_node(n.body)  1772   1773         # Put the else statement in another try block that handles any raised  1774         # exceptions and converts them to exceptions that will not be handled by  1775         # the main handling block.  1776   1777         if n.else_:  1778             self.writestmt("__Try")  1779             self.writeline("{")  1780             self.indent += 1  1781             self.process_structure_node(n.else_)  1782             self.indent -= 1  1783             self.writeline("}")  1784             self.writeline("__Catch (__tmp_exc)")  1785             self.writeline("{")  1786             self.indent += 1  1787             self.writeline("if (__tmp_exc.raising) __RaiseElse(__tmp_exc.arg);")  1788             self.writeline("else if (__tmp_exc.completing) __Throw(__tmp_exc);")  1789             self.indent -= 1  1790             self.writeline("}")  1791   1792         # Complete the try block and enter the finally block, if appropriate.  1793   1794         if self.in_try_finally:  1795             self.writestmt("__Complete;")  1796   1797         self.indent -= 1  1798         self.writeline("}")  1799   1800         self.in_try_except = in_try_except  1801   1802         # Handlers are tests within a common handler block.  1803   1804         self.writeline("__Catch (__tmp_exc)")  1805         self.writeline("{")  1806         self.indent += 1  1807   1808         # Introduce an if statement to handle the completion of a try block.  1809   1810         self.process_try_completion()  1811   1812         # Handle exceptions in else blocks converted to __RaiseElse, converting  1813         # them back to normal exceptions.  1814   1815         if n.else_:  1816             self.writeline("else if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")  1817   1818         # Exception handling.  1819   1820         for name, var, handler in n.handlers:  1821   1822             # Test for specific exceptions.  1823   1824             if name is not None:  1825                 name_ref = self.process_structure_node(name)  1826                 self.writeline("else if (__ISINSTANCE(__tmp_exc.arg, %s))" % name_ref)  1827             else:  1828                 self.writeline("else if (1)")  1829   1830             self.writeline("{")  1831             self.indent += 1  1832   1833             # Establish the local for the handler.  1834   1835             if var is not None:  1836                 self.writestmt("%s;" % self.process_name_node(var, make_expression("__tmp_exc.arg")))  1837   1838             if handler is not None:  1839                 self.process_structure_node(handler)  1840   1841             self.indent -= 1  1842             self.writeline("}")  1843   1844         # Re-raise unhandled exceptions.  1845   1846         self.writeline("else __Throw(__tmp_exc);")  1847   1848         # End the handler block.  1849   1850         self.indent -= 1  1851         self.writeline("}")  1852         print >>self.out  1853   1854     def process_try_finally_node(self, n):  1855   1856         """  1857         Process the given "try...finally" node 'n'.  1858         """  1859   1860         in_try_finally = self.in_try_finally  1861         self.in_try_finally = True  1862   1863         # Use macros to implement exception handling.  1864   1865         self.writestmt("__Try")  1866         self.writeline("{")  1867         self.indent += 1  1868         self.process_structure_node(n.body)  1869         self.indent -= 1  1870         self.writeline("}")  1871   1872         self.in_try_finally = in_try_finally  1873   1874         # Finally clauses handle special exceptions.  1875   1876         self.writeline("__Catch (__tmp_exc)")  1877         self.writeline("{")  1878         self.indent += 1  1879         self.process_structure_node(n.final)  1880   1881         # Introduce an if statement to handle the completion of a try block.  1882   1883         self.process_try_completion()  1884         self.writeline("else __Throw(__tmp_exc);")  1885   1886         self.indent -= 1  1887         self.writeline("}")  1888         print >>self.out  1889   1890     def process_try_completion(self):  1891   1892         "Generate a test for the completion of a try block."  1893   1894         self.writestmt("if (__tmp_exc.completing)")  1895         self.writeline("{")  1896         self.indent += 1  1897   1898         # Do not return anything at the module level.  1899   1900         if self.get_namespace_path() != self.name:  1901   1902             # Only use the normal return statement if no surrounding try blocks  1903             # apply.  1904   1905             if not self.in_try_finally and not self.in_try_except:  1906                 self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")  1907             else:  1908                 self.writeline("if (!__ISNULL(__tmp_exc.arg)) __Throw(__tmp_exc);")  1909   1910         self.indent -= 1  1911         self.writeline("}")  1912   1913     def process_while_node(self, n):  1914   1915         "Process the given while node 'n'."  1916   1917         self.writeline("while (1)")  1918         self.writeline("{")  1919         self.indent += 1  1920         test = self.process_structure_node(n.test)  1921   1922         # Emit the loop termination condition unless "while <true value>" is  1923         # indicated.  1924   1925         if not (isinstance(test, PredefinedConstantRef) and test.value):  1926   1927             # Emit a negated test of the continuation condition.  1928   1929             self.start_if(True, self.make_negation(test))  1930             if n.else_:  1931                 self.process_structure_node(n.else_)  1932             self.writestmt("break;")  1933             self.end_if()  1934   1935         in_conditional = self.in_conditional  1936         self.in_conditional = True  1937         self.process_structure_node(n.body)  1938         self.in_conditional = in_conditional  1939   1940         self.indent -= 1  1941         self.writeline("}")  1942         print >>self.out  1943   1944     # Special variable usage.  1945   1946     def get_temp_path(self):  1947   1948         """  1949         Return the appropriate namespace path for temporary names in the current  1950         namespace.  1951         """  1952   1953         if self.in_function:  1954             return self.get_namespace_path()  1955         else:  1956             return self.name  1957   1958     def record_temp(self, name):  1959   1960         """  1961         Record the use of the temporary 'name' in the current namespace. At the  1962         class or module level, the temporary name is associated with the module,  1963         since the variable will then be allocated in the module's own main  1964         program.  1965         """  1966   1967         path = self.get_temp_path()  1968   1969         init_item(self.temp_usage, path, list)  1970         self.temp_usage[path].append(name)  1971   1972     def remove_temps(self, names):  1973   1974         """  1975         Remove 'names' from temporary storage allocations, each instance  1976         removing each request for storage.  1977         """  1978   1979         path = self.get_temp_path()  1980   1981         for name in names:  1982             if self.uses_temp(path, name):  1983                 self.temp_usage[path].remove(name)  1984   1985     def uses_temp(self, path, name):  1986   1987         """  1988         Return whether the given namespace 'path' employs a temporary variable  1989         with the given 'name'. Note that 'path' should only be a module or a  1990         function or method, not a class.  1991         """  1992   1993         return self.temp_usage.has_key(path) and name in self.temp_usage[path]  1994   1995     def make_negation(self, expr):  1996   1997         "Return a negated form of 'expr'."  1998   1999         result = NegationResult(expr)  2000   2001         # Negation discards the temporary results of its operand.  2002   2003         temps = expr.discards_temporary()  2004         if temps:  2005             self.remove_temps(temps)  2006   2007         return result  2008   2009     # Output generation.  2010   2011     def start_output(self):  2012   2013         "Write the declarations at the top of each source file."  2014   2015         print >>self.out, """\  2016 #include "types.h"  2017 #include "exceptions.h"  2018 #include "ops.h"  2019 #include "progconsts.h"  2020 #include "progops.h"  2021 #include "progtypes.h"  2022 #include "main.h"  2023 """  2024   2025     def start_unit(self):  2026   2027         "Record output within a generated function for later use."  2028   2029         self.out = StringIO()  2030   2031     def end_unit(self):  2032   2033         "Restore the output stream."  2034   2035         out = self.out  2036         self.out = self.out_toplevel  2037         return out  2038   2039     def flush_unit(self, name, out):  2040   2041         "Add declarations and generated code."  2042   2043         self.write_temporaries(name)  2044         print >>self.out  2045         out.seek(0)  2046         self.out.write(out.read())  2047   2048     def start_module(self):  2049   2050         "Write the start of each module's main function."  2051   2052         print >>self.out, "void __main_%s()" % encode_path(self.name)  2053         print >>self.out, "{"  2054         self.indent += 1  2055   2056         # Define temporary variables, excluded from the module structure itself.  2057   2058         tempnames = []  2059   2060         for n in self.importer.all_module_attrs[self.name]:  2061             if n.startswith("$t"):  2062                 tempnames.append(encode_path(n))  2063   2064         if tempnames:  2065             tempnames.sort()  2066             self.writeline("__attr %s;" % ", ".join(tempnames))  2067   2068         self.start_unit()  2069   2070     def end_module(self):  2071   2072         "End each module by closing its main function."  2073   2074         out = self.end_unit()  2075         self.flush_unit(self.name, out)  2076   2077         self.indent -= 1  2078         print >>self.out, "}"  2079   2080     def start_function(self, name):  2081   2082         "Start the function having the given 'name'."  2083   2084         self.indent += 1  2085   2086         self.start_unit()  2087   2088     def end_function(self, name):  2089   2090         "End the function having the given 'name'."  2091   2092         out = self.end_unit()  2093   2094         # Write the signature at the top indentation level.  2095   2096         self.indent -= 1  2097         self.write_parameters(name)  2098         print >>self.out, "{"  2099   2100         # Obtain local names from parameters.  2101   2102         parameters = self.importer.function_parameters[name]  2103         locals = self.importer.function_locals[name].keys()  2104         names = []  2105         volatile_names = []  2106   2107         for n in locals:  2108   2109             # Filter out special names and parameters. Note that self is a local  2110             # regardless of whether it originally appeared in the parameters or  2111             # not.  2112   2113             if n.startswith("$l") or n in parameters or n == "self":  2114                 continue  2115             if n in self.volatile_locals:  2116                 volatile_names.append(encode_path(n))  2117             else:  2118                 names.append(encode_path(n))  2119   2120         # Emit required local names at the function indentation level.  2121   2122         self.indent += 1  2123   2124         if names:  2125             names.sort()  2126             self.writeline("__attr %s;" % ", ".join(names))  2127   2128         if volatile_names:  2129             volatile_names.sort()  2130             self.writeline("volatile __attr %s;" % ", ".join(volatile_names))  2131   2132         self.flush_unit(name, out)  2133   2134         self.indent -= 1  2135         print >>self.out, "}"  2136         print >>self.out  2137   2138     def write_parameters(self, name):  2139   2140         """  2141         For the function having the given 'name', write definitions of  2142         parameters found in the arguments array.  2143         """  2144   2145         # Generate any self reference.  2146   2147         l = []  2148   2149         if self.is_method(name):  2150             l.append("__attr self")  2151         else:  2152             l.append("__attr __self")  2153   2154         # Generate aliases for the parameters.  2155   2156         for parameter in self.importer.function_parameters[name]:  2157             l.append("%s__attr %s" % (  2158                 parameter in self.volatile_locals and "volatile " or "",  2159                 encode_path(parameter)))  2160   2161         self.writeline("__attr %s(%s)" % (  2162             encode_function_pointer(name), ", ".join(l)))  2163   2164     def write_temporaries(self, name):  2165   2166         "Write temporary storage employed by 'name'."  2167   2168         # Provide space for the recorded number of temporary variables.  2169   2170         if self.uses_temp(name, "__tmp_targets"):  2171             self.writeline("__attr __tmp_targets[%d];" % self.max_function_target)  2172   2173         if self.uses_temp(name, "__tmp_contexts"):  2174             self.writeline("__attr __tmp_contexts[%d];" % self.max_context_index)  2175   2176         if self.uses_temp(name, "__tmp_values"):  2177             self.writeline("__attr __tmp_values[%d];" % self.max_accessor_index)  2178   2179         # Add temporary variable usage details.  2180   2181         if self.uses_temp(name, "__tmp_private_context"):  2182             self.writeline("__attr __tmp_private_context;")  2183         if self.uses_temp(name, "__tmp_target_value"):  2184             self.writeline("__attr __tmp_target_value;")  2185         if self.uses_temp(name, "__tmp_result"):  2186             self.writeline("__attr __tmp_result;")  2187   2188         module = self.importer.get_module(self.name)  2189   2190         if name in module.exception_namespaces:  2191             self.writeline("__exc __tmp_exc;")  2192   2193     def start_if(self, first, test_ref):  2194         statement = "%sif" % (not first and "else " or "")  2195   2196         # Consume logical results directly.  2197   2198         if isinstance(test_ref, LogicalResult):  2199             self.writeline("%s %s" % (statement, test_ref.apply_test()))  2200             temps = test_ref.discards_temporary()  2201             if temps:  2202                 self.remove_temps(temps)  2203         else:  2204             self.writeline("%s (__BOOL(%s))" % (statement, test_ref))  2205   2206         self.writeline("{")  2207         self.indent += 1  2208   2209     def end_if(self):  2210         self.indent -= 1  2211         self.writeline("}")  2212   2213     def start_else(self):  2214         self.writeline("else")  2215         self.writeline("{")  2216         self.indent += 1  2217   2218     def end_else(self):  2219         self.indent -= 1  2220         self.writeline("}")  2221   2222     def statement(self, expr):  2223         s = str(expr)  2224         if s:  2225             self.writestmt("%s;" % s)  2226   2227     def statements(self, results):  2228         for result in results:  2229             self.statement(result)  2230   2231     def writeline(self, s):  2232         print >>self.out, "%s%s" % (self.pad(), self.indenttext(s, self.indent + 1))  2233   2234     def writestmt(self, s):  2235         self.writeline(s)  2236   2237     def write_comment(self, s):  2238         self.writestmt("/* %s */" % s)  2239   2240     def pad(self, extra=0):  2241         return (self.indent + extra) * self.tabstop  2242   2243     def indenttext(self, s, levels):  2244         lines = s.split("\n")  2245         out = [lines[0]]  2246         for line in lines[1:]:  2247             out.append(levels * self.tabstop + line)  2248             if line.endswith("("):  2249                 levels += 1  2250             elif line.startswith(")"):  2251                 levels -= 1  2252         return "\n".join(out)  2253   2254 # vim: tabstop=4 expandtab shiftwidth=4