Lichen

translator.py

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