Lichen

translator.py

830:fc7f612df68d
2018-06-24 Paul Boddie Made use of available reference information in order to determine the nature of invocations and to avoid generic __invoke calls.
     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             ref = self.importer.identify(final_identity)   605             refs = [ref]   606    607         del self.attrs[0]   608         return AttrResult(output, refs, location, context_identity, context_identity_verified, accessor_test)   609    610     def init_substitutions(self):   611    612         """   613         Initialise substitutions, defining temporary variable mappings, some of   614         which are also used as substitutions, together with operation mappings   615         used as substitutions in instructions defined by the optimiser.   616         """   617    618         self.temp_subs = {   619    620             # Substitutions used by instructions.   621    622             "<private_context>" : "__tmp_private_context",   623             "<accessor>" : "__tmp_value",   624             "<target_accessor>" : "__tmp_target_value",   625    626             # Mappings to be replaced by those given below.   627    628             "<context>" : "__tmp_contexts",   629             "<test_context_revert>" : "__tmp_contexts",   630             "<test_context_static>" : "__tmp_contexts",   631             "<set_context>" : "__tmp_contexts",   632             "<set_private_context>" : "__tmp_private_context",   633             "<set_accessor>" : "__tmp_value",   634             "<set_target_accessor>" : "__tmp_target_value",   635             }   636    637         self.op_subs = {   638             "<context>" : "__get_context",   639             "<test_context_revert>" : "__test_context_revert",   640             "<test_context_static>" : "__test_context_static",   641             "<set_context>" : "__set_context",   642             "<set_private_context>" : "__set_private_context",   643             "<set_accessor>" : "__set_accessor",   644             "<set_target_accessor>" : "__set_target_accessor",   645             }   646    647     def get_referenced_attributes(self, location):   648    649         """   650         Convert 'location' to the form used by the deducer and retrieve any   651         identified attributes.   652         """   653    654         # Determine whether any deduced references refer to the accessed   655         # attribute.   656    657         attrnames = location.attrnames   658         attrnames = attrnames and attrnames.split(".")   659         remaining = attrnames and len(attrnames) > 1   660    661         access_location = self.deducer.const_accesses.get(location)   662    663         if remaining and not access_location:   664             return []   665    666         refs = []   667         l = self.deducer.referenced_attrs.get(access_location or location)   668         if l:   669             for attrtype, objpath, attr in l:   670                 refs.append(attr)   671         return refs   672    673     def get_referenced_attribute_invocations(self, location):   674    675         """   676         Convert 'location' to the form used by the deducer and retrieve any   677         identified attribute invocation details.   678         """   679    680         access_location = self.deducer.const_accesses.get(location)   681         return self.deducer.reference_invocations_unsuitable.get(access_location or location)   682    683     def get_accessor_kinds(self, location):   684    685         "Return the accessor kinds for 'location'."   686    687         return self.deducer.accessor_kinds.get(location)   688    689     def get_access_location(self, name, attrnames=None):   690    691         """   692         Using the current namespace, the given 'name', and the 'attrnames'   693         employed in an access, return the access location.   694         """   695    696         path = self.get_path_for_access()   697    698         # Get the location used by the deducer and optimiser and find any   699         # recorded access.   700    701         attrnames = attrnames and ".".join(self.attrs)   702         access_number = self.get_access_number(path, name, attrnames)   703         self.update_access_number(path, name, attrnames)   704         return AccessLocation(path, name, attrnames, access_number)   705    706     def get_access_number(self, path, name, attrnames):   707         access = name, attrnames   708         if self.attr_accesses.has_key(path) and self.attr_accesses[path].has_key(access):   709             return self.attr_accesses[path][access]   710         else:   711             return 0   712    713     def update_access_number(self, path, name, attrnames):   714         access = name, attrnames   715         if name:   716             init_item(self.attr_accesses, path, dict)   717             init_item(self.attr_accesses[path], access, lambda: 0)   718             self.attr_accesses[path][access] += 1   719    720     def get_accessor_location(self, name):   721    722         """   723         Using the current namespace and the given 'name', return the accessor   724         location.   725         """   726    727         path = self.get_path_for_access()   728    729         # Get the location used by the deducer and optimiser and find any   730         # recorded accessor.   731    732         version = self.get_accessor_number(path, name)   733         self.update_accessor_number(path, name)   734         return Location(path, name, None, version)   735    736     def get_accessor_number(self, path, name):   737         if self.attr_accessors.has_key(path) and self.attr_accessors[path].has_key(name):   738             return self.attr_accessors[path][name]   739         else:   740             return 0   741    742     def update_accessor_number(self, path, name):   743         if name:   744             init_item(self.attr_accessors, path, dict)   745             init_item(self.attr_accessors[path], name, lambda: 0)   746             self.attr_accessors[path][name] += 1   747    748     def process_class_node(self, n):   749    750         "Process the given class node 'n'."   751    752         class_name = self.get_object_path(n.name)   753    754         # Where a class is set conditionally or where the name may refer to   755         # different values, assign the name.   756    757         ref = self.importer.identify(class_name)   758    759         if not ref.static():   760             self.process_assignment_for_object(n.name,   761                 make_expression("__ATTRVALUE(&%s)" % encode_path(class_name)))   762    763         self.enter_namespace(n.name)   764    765         if self.have_object():   766             self.write_comment("Class: %s" % class_name)   767    768             self.initialise_inherited_members(class_name)   769    770             self.process_structure(n)   771             self.write_comment("End class: %s" % class_name)   772    773         self.exit_namespace()   774    775     def initialise_inherited_members(self, class_name):   776    777         "Initialise members of 'class_name' inherited from its ancestors."   778    779         for name, path in self.importer.all_class_attrs[class_name].items():   780             target = "%s.%s" % (class_name, name)   781    782             # Ignore attributes with definitions.   783    784             ref = self.importer.identify(target)   785             if ref:   786                 continue   787    788             # Ignore special type attributes.   789    790             if is_type_attribute(name):   791                 continue   792    793             # Reference inherited attributes.   794    795             ref = self.importer.identify(path)   796             if ref and not ref.static():   797                 parent, attrname = path.rsplit(".", 1)   798    799                 self.writestmt("__store_via_object(&%s, %s, __load_via_object(&%s, %s));" % (   800                     encode_path(class_name), name,   801                     encode_path(parent), attrname   802                     ))   803    804     def process_from_node(self, n):   805    806         "Process the given node 'n', importing from another module."   807    808         path = self.get_namespace_path()   809    810         # Attempt to obtain the referenced objects.   811    812         for name, alias in n.names:   813             if name == "*":   814                 raise InspectError("Only explicitly specified names can be imported from modules.", path, n)   815    816             # Obtain the path of the assigned name.   817    818             objpath = self.get_object_path(alias or name)   819    820             # Obtain the identity of the name.   821    822             ref = self.importer.identify(objpath)   823    824             # Where the name is not static, assign the value.   825    826             if ref and not ref.static() and ref.get_name():   827                 self.writestmt("%s;" %    828                     TrResolvedNameRef(alias or name, Reference("<var>", None, objpath),   829                                       expr=TrResolvedNameRef(name, ref)))   830    831     def process_function_body_node(self, n):   832    833         """   834         Process the given function, lambda, if expression or list comprehension   835         node 'n', generating the body.   836         """   837    838         function_name = self.get_namespace_path()   839         self.start_function(function_name)   840    841         # Process the function body.   842    843         in_conditional = self.in_conditional   844         self.in_conditional = False   845         self.function_target = 0   846         self.max_function_target = 0   847         self.context_index = 0   848         self.max_context_index = 0   849    850         # Volatile locals for exception handling.   851    852         self.volatile_locals = set()   853    854         # Process any guards defined for the parameters.   855    856         for name in self.importer.function_parameters.get(function_name):   857             self.generate_guard(name)   858    859         # Also support self in methods, since some mix-in methods may only work   860         # with certain descendant classes.   861    862         if self.in_method():   863             self.generate_guard("self")   864    865         # Make assignments for .name entries in the parameters, provided this is   866         # a method.   867    868         if self.in_method():   869             for name in self.importer.function_attr_initialisers.get(function_name) or []:   870                 self.process_assignment_node(   871                     compiler.ast.AssAttr(compiler.ast.Name("self"), name, "OP_ASSIGN"),   872                     compiler.ast.Name(name))   873    874         # Produce the body and any additional return statement.   875    876         expr = self.process_structure_node(n.code) or \   877                self.in_method() and \   878                    function_name.rsplit(".", 1)[-1] == "__init__" and \   879                    TrResolvedNameRef("self", self.importer.function_locals[function_name]["self"]) or \   880                PredefinedConstantRef("None")   881    882         if not isinstance(expr, ReturnRef):   883             self.writestmt("return %s;" % expr)   884    885         self.in_conditional = in_conditional   886    887         self.end_function(function_name)   888    889     def generate_guard(self, name):   890    891         """   892         Get the accessor details for 'name', found in the current namespace, and   893         generate any guards defined for it.   894         """   895    896         # Obtain the location, keeping track of assignment versions.   897    898         location = self.get_accessor_location(name)   899         test = self.deducer.accessor_guard_tests.get(location)   900    901         # Generate any guard from the deduced information.   902    903         if test:   904             guard, guard_type = test   905    906             if guard == "specific":   907                 ref = first(self.deducer.accessor_all_types[location])   908                 argstr = "&%s" % encode_path(ref.get_origin())   909             elif guard == "common":   910                 ref = first(self.deducer.accessor_all_general_types[location])   911                 argstr = encode_path(encode_type_attribute(ref.get_origin()))   912             else:   913                 return   914    915             # Write a test that raises a TypeError upon failure.   916    917             self.writestmt("if (!__test_%s_%s(__VALUE(%s), %s)) __raise_type_error();" % (   918                 guard, guard_type, encode_path(name), argstr))   919    920     def process_function_node(self, n):   921    922         """   923         Process the given function, lambda, if expression or list comprehension   924         node 'n', generating any initialisation statements.   925         """   926    927         # Where a function is declared conditionally, use a separate name for   928         # the definition, and assign the definition to the stated name.   929    930         original_name = n.name   931    932         if self.in_conditional or self.in_function:   933             name = self.get_lambda_name()   934         else:   935             name = n.name   936    937         objpath = self.get_object_path(name)   938    939         # Obtain details of the defaults.   940    941         defaults = self.process_function_defaults(n, name, objpath)   942         if defaults:   943             for default in defaults:   944                 self.writeline("%s;" % default)   945    946         # Where a function is set conditionally or where the name may refer to   947         # different values, assign the name.   948    949         ref = self.importer.identify(objpath)   950    951         if self.in_conditional or self.in_function:   952             self.process_assignment_for_object(original_name, compiler.ast.Name(name))   953         elif not ref.static():   954             context = self.is_method(objpath)   955    956             self.process_assignment_for_object(original_name,   957                 make_expression("__ATTRVALUE(&%s)" % encode_path(objpath)))   958    959     def process_function_defaults(self, n, name, objpath, instance_name=None):   960    961         """   962         Process the given function or lambda node 'n', initialising defaults   963         that are dynamically set. The given 'name' indicates the name of the   964         function. The given 'objpath' indicates the origin of the function.   965         The given 'instance_name' indicates the name of any separate instance   966         of the function created to hold the defaults.   967    968         Return a list of operations setting defaults on a function instance.   969         """   970    971         function_name = self.get_object_path(name)   972         function_defaults = self.importer.function_defaults.get(function_name)   973         if not function_defaults:   974             return None   975    976         # Determine whether any unidentified defaults are involved.   977    978         for argname, default in function_defaults:   979             if not default.static():   980                 break   981         else:   982             return None   983    984         # Handle bound methods.   985    986         if not instance_name:   987             instance_name = "&%s" % encode_path(objpath)   988         else:   989             instance_name = "__VALUE(%s)" % instance_name   990    991         # Where defaults are involved but cannot be identified, obtain a new   992         # instance of the lambda and populate the defaults.   993    994         defaults = []   995    996         # Join the original defaults with the inspected defaults.   997    998         original_defaults = [(argname, default) for (argname, default) in compiler.ast.get_defaults(n) if default]   999   1000         for i, (original, inspected) in enumerate(map(None, original_defaults, function_defaults)):  1001   1002             # Obtain any reference for the default.  1003   1004             if original:  1005                 argname, default = original  1006                 name_ref = self.process_structure_node(default)  1007             elif inspected:  1008                 argname, default = inspected  1009                 name_ref = TrResolvedNameRef(argname, default)  1010             else:  1011                 continue  1012   1013             # Generate default initialisers except when constants are employed.  1014             # Constants should be used when populating the function structures.  1015   1016             if name_ref and not isinstance(name_ref, TrConstantValueRef):  1017                 defaults.append("__SETDEFAULT(%s, %s, %s)" % (instance_name, i, name_ref))  1018   1019         return defaults  1020   1021     def process_if_node(self, n):  1022   1023         """  1024         Process the given "if" node 'n'.  1025         """  1026   1027         first = True  1028         for test, body in n.tests:  1029             test_ref = self.process_structure_node(test)  1030             self.start_if(first, test_ref)  1031   1032             in_conditional = self.in_conditional  1033             self.in_conditional = True  1034             self.process_structure_node(body)  1035             self.in_conditional = in_conditional  1036   1037             self.end_if()  1038             first = False  1039   1040         if n.else_:  1041             self.start_else()  1042             self.process_structure_node(n.else_)  1043             self.end_else()  1044   1045         print >>self.out  1046   1047     def process_invocation_node(self, n):  1048   1049         "Process the given invocation node 'n'."  1050   1051         # Process the expression.  1052   1053         expr = self.process_structure_node(n.node)  1054   1055         # Obtain details of the invocation expression.  1056   1057         objpath = expr.get_origin()  1058         location = expr.access_location()  1059         refs = expr.references()  1060   1061         # Identified target details.  1062   1063         target = None  1064         target_structure = None  1065   1066         # Specific function target information.  1067   1068         function = None  1069   1070         # Instantiation involvement.  1071   1072         instantiation = False  1073         literal_instantiation = False  1074   1075         # Invocation requirements.  1076   1077         context_required = True  1078         have_access_context = isinstance(expr, AttrResult)  1079         context_identity = have_access_context and expr.context()  1080         context_verified = have_access_context and expr.context_verified()  1081         tests_accessor = have_access_context and expr.tests_accessor()  1082         parameters = None  1083         num_parameters = None  1084         num_defaults = None  1085   1086         # Obtain details of the callable and of its parameters.  1087   1088         # Literals may be instantiated specially.  1089   1090         if expr.is_name() and expr.name.startswith("$L") and objpath:  1091             instantiation = literal_instantiation = objpath  1092             target = encode_literal_instantiator(objpath)  1093             context_required = False  1094   1095         # Identified targets employ function pointers directly.  1096   1097         elif objpath:  1098             parameters = self.importer.function_parameters.get(objpath)  1099             function_defaults = self.importer.function_defaults.get(objpath)  1100             num_parameters = parameters and len(parameters) or 0  1101             num_defaults = function_defaults and len(function_defaults) or 0  1102   1103             # Class invocation involves instantiators.  1104   1105             if expr.has_kind("<class>"):  1106                 instantiation = objpath  1107                 target = encode_instantiator_pointer(objpath)  1108                 init_ref = self.importer.all_class_attrs[objpath]["__init__"]  1109                 target_structure = "&%s" % encode_path(init_ref)  1110                 context_required = False  1111   1112             # Only plain functions and bound methods employ function pointers.  1113   1114             elif expr.has_kind("<function>"):  1115                 function = objpath  1116   1117                 # Test for functions and methods.  1118   1119                 context_required = self.is_method(objpath)  1120   1121                 accessor_kinds = location and self.get_accessor_kinds(location)  1122   1123                 instance_accessor = accessor_kinds and \  1124                                     len(accessor_kinds) == 1 and \  1125                                     first(accessor_kinds) == "<instance>"  1126   1127                 # Only identify certain bound methods or functions.  1128   1129                 if not context_required or instance_accessor:  1130                     target = encode_function_pointer(objpath)  1131   1132                 # Access bound method defaults even if it is not clear whether  1133                 # the accessor is appropriate.  1134   1135                 target_structure = "&%s" % encode_path(objpath)  1136   1137         # Other targets are retrieved at run-time.  1138   1139         else:  1140             if location:  1141                 attrnames = location.attrnames  1142                 attrname = attrnames and attrnames.rsplit(".", 1)[-1]  1143   1144                 # Determine common aspects of any identifiable targets.  1145   1146                 if attrname or refs:  1147                     all_params = set()  1148                     all_defaults = set()  1149                     min_params = set()  1150                     max_params = set()  1151   1152                     # Employ references from the expression or find all  1153                     # possible attributes for the given attribute name.  1154   1155                     refs = refs or self.get_attributes_for_attrname(attrname)  1156   1157                     # Obtain parameters and defaults for each possible target.  1158   1159                     for ref in refs:  1160                         origin = ref.get_origin()  1161                         params = self.importer.function_parameters.get(origin)  1162   1163                         defaults = self.importer.function_defaults.get(origin)  1164                         if defaults is not None:  1165                             all_defaults.add(tuple(defaults))  1166   1167                         if params is not None:  1168                             all_params.add(tuple(params))  1169                             min_params.add(len(params) - (defaults and len(defaults) or 0))  1170                             max_params.add(len(params))  1171                         else:  1172                             refs = set()  1173                             break  1174   1175                     # Where the parameters and defaults are always the same,  1176                     # permit populating them in advance.  1177   1178                     if refs:  1179                         if self.uses_keyword_arguments(n):  1180                             if len(all_params) == 1 and (not all_defaults or len(all_defaults) == 1):  1181                                 parameters = first(all_params)  1182                                 function_defaults = all_defaults and first(all_defaults) or []  1183                                 num_parameters = parameters and len(parameters) or 0  1184                                 num_defaults = function_defaults and len(function_defaults) or 0  1185                         else:  1186                             if len(min_params) == 1 and len(max_params) == 1:  1187                                 num_parameters = first(max_params)  1188                                 num_defaults = first(max_params) - first(min_params)  1189   1190             # Some information about the target may be available and be used to  1191             # provide warnings about argument compatibility.  1192   1193             if self.importer.give_warning("args"):  1194                 unsuitable = self.get_referenced_attribute_invocations(location)  1195   1196                 if unsuitable:  1197                     for ref in unsuitable:  1198                         _objpath = ref.get_origin()  1199                         print >>sys.stderr, \  1200                             "In %s, at line %d, inappropriate number of " \  1201                             "arguments given. Need %d arguments to call %s." % (  1202                             self.get_namespace_path(), n.lineno,  1203                             len(self.importer.function_parameters[_objpath]),  1204                             _objpath)  1205   1206         # Logical statement about available parameter information.  1207   1208         known_parameters = num_parameters is not None  1209   1210         # The source of context information: target or temporary.  1211   1212         need_context_target = context_required and not have_access_context  1213   1214         need_context_stored = context_required and context_identity and \  1215                               context_identity.startswith("__get_context")  1216   1217         # Determine any readily-accessible target identity.  1218   1219         target_named = expr.is_name() and str(expr) or None  1220         target_identity = target or target_named  1221   1222         # Use of target information to populate defaults.  1223   1224         defaults_target_var = not (parameters and function_defaults is not None) and \  1225                               known_parameters and len(n.args) < num_parameters  1226   1227         # Use of a temporary target variable in these situations:  1228         #  1229         # A target provided by an expression needed for defaults.  1230         #  1231         # A target providing the context but not using a name to do so.  1232         #  1233         # A target expression involving the definition of a context which may  1234         # then be evaluated and stored to ensure that the context is available  1235         # during argument evaluation.  1236         #  1237         # An expression featuring an accessor test.  1238   1239         need_target_stored = defaults_target_var and not target_identity or \  1240                              need_context_target and not target_identity or \  1241                              need_context_stored or \  1242                              tests_accessor and not target  1243   1244         # Define stored target details.  1245   1246         target_stored = "__tmp_targets[%d]" % self.function_target  1247         target_var = need_target_stored and target_stored or target_identity  1248   1249         if need_target_stored:  1250             self.record_temp("__tmp_targets")  1251   1252         if need_context_stored:  1253             self.record_temp("__tmp_contexts")  1254   1255         # Arguments are presented in a temporary frame array with any context  1256         # always being the first argument. Where it would be unused, it may be  1257         # set to null.  1258   1259         if context_required:  1260             if have_access_context:  1261                 args = [context_identity]  1262             else:  1263                 args = ["__CONTEXT_AS_VALUE(%s)" % target_var]  1264         else:  1265             args = ["__NULL"]  1266   1267         # Complete the array with null values, permitting tests for a complete  1268         # set of arguments.  1269   1270         args += [None] * (num_parameters is None and len(n.args) or num_parameters is not None and num_parameters or 0)  1271         kwcodes = []  1272         kwargs = []  1273   1274         # Any invocations in the arguments will store target details in a  1275         # different location.  1276   1277         function_target = self.function_target  1278         context_index = self.context_index  1279   1280         if need_target_stored:  1281             self.next_target()  1282   1283         if need_context_stored:  1284             self.next_context()  1285   1286         for i, arg in enumerate(n.args):  1287             argexpr = self.process_structure_node(arg)  1288   1289             # Store a keyword argument, either in the argument list or  1290             # in a separate keyword argument list for subsequent lookup.  1291   1292             if isinstance(arg, compiler.ast.Keyword):  1293   1294                 # With knowledge of the target, store the keyword  1295                 # argument directly.  1296   1297                 if parameters:  1298                     try:  1299                         argnum = parameters.index(arg.name)  1300                     except ValueError:  1301                         raise TranslateError("Argument %s is not recognised." % arg.name,  1302                                              self.get_namespace_path(), n)  1303                     args[argnum+1] = str(argexpr)  1304   1305                 # Otherwise, store the details in a separate collection.  1306   1307                 else:  1308                     kwargs.append(str(argexpr))  1309                     kwcodes.append("{%s, %s}" % (  1310                         encode_ppos(arg.name), encode_pcode(arg.name)))  1311   1312             # Store non-keyword arguments in the argument list, rejecting  1313             # superfluous arguments.  1314   1315             else:  1316                 try:  1317                     args[i+1] = str(argexpr)  1318                 except IndexError:  1319                     raise TranslateError("Too many arguments specified.",  1320                                          self.get_namespace_path(), n)  1321   1322         # Reference the current target again.  1323   1324         self.function_target = function_target  1325         self.context_index = context_index  1326   1327         # Defaults are added to the frame where arguments are missing.  1328   1329         if parameters and function_defaults is not None:  1330   1331             # Visit each default and set any missing arguments. Where keyword  1332             # arguments have been used, the defaults must be inspected and, if  1333             # necessary, inserted into gaps in the argument list.  1334   1335             for i, (argname, default) in enumerate(function_defaults):  1336                 argnum = parameters.index(argname)  1337                 if not args[argnum+1]:  1338                     args[argnum+1] = "__GETDEFAULT(%s, %d)" % (target_structure, i)  1339   1340         elif known_parameters:  1341   1342             # No specific parameter details are provided, but no keyword  1343             # arguments are used. Thus, defaults can be supplied using position  1344             # information only.  1345   1346             i = len(n.args)  1347             pos = i - (num_parameters - num_defaults)  1348             while i < num_parameters:  1349                 args[i+1] = "__GETDEFAULT(%s.value, %d)" % (target_var, pos)  1350                 i += 1  1351                 pos += 1  1352   1353         # Test for missing arguments.  1354   1355         if None in args:  1356             raise TranslateError("Not all arguments supplied.",  1357                                  self.get_namespace_path(), n)  1358   1359         # Encode the arguments.  1360   1361         # Where literal instantiation is occurring, add an argument indicating  1362         # the number of values. The context is excluded.  1363   1364         if literal_instantiation:  1365             argstr = "%d, %s" % (len(args) - 1, ", ".join(args[1:]))  1366         else:  1367             argstr = ", ".join(args)  1368   1369         kwargstr = kwargs and ("__ARGS(%s)" % ", ".join(kwargs)) or "0"  1370         kwcodestr = kwcodes and ("__KWARGS(%s)" % ", ".join(kwcodes)) or "0"  1371   1372         # First, the invocation expression is presented.  1373   1374         stages = []  1375         emit = stages.append  1376   1377         # Assign and yield any stored target.  1378         # The context may be set in the expression.  1379   1380         if need_target_stored:  1381             emit("%s = %s" % (target_var, expr))  1382             target_expr = target_var  1383   1384         # Otherwise, retain the expression for later use.  1385   1386         else:  1387             target_expr = str(expr)  1388   1389         # Any specific callable is then obtained for invocation.  1390   1391         if target:  1392   1393             # An expression involving a test of the accessor providing the target.  1394             # This must be emitted in order to perform the test.  1395   1396             if tests_accessor:  1397                 emit(str(expr))  1398   1399             emit(target)  1400   1401         # Methods accessed via unidentified accessors are obtained for  1402         # invocation.  1403   1404         elif function:  1405             if context_required:  1406                 if have_access_context:  1407                     if context_verified:  1408                         emit("__get_function_member(%s)" % target_expr)  1409                     else:  1410                         emit("__get_function(%s, %s)" % (  1411                             context_identity, target_expr))  1412                 else:  1413                     emit("__get_function(__CONTEXT_AS_VALUE(%s), %s)" % (  1414                         target_var, target_expr))  1415             else:  1416                 emit("_get_function_member(%s)" % target_expr)  1417   1418         # With known parameters, the target can be tested.  1419   1420         elif known_parameters:  1421             context_arg = context_required and args[0] or "__NULL"  1422             if self.always_callable(refs):  1423                 if context_verified:  1424                     emit("__get_function_member(%s)" % target_expr)  1425                 else:  1426                     emit("__get_function(%s, %s)" % (context_arg, target_expr))  1427             else:  1428                 emit("__check_and_get_function(%s, %s)" % (context_arg, target_expr))  1429   1430         # With a known target, the function is obtained directly and called.  1431         # By putting the invocation at the end of the final element in the  1432         # instruction sequence (the stages), the result becomes the result of  1433         # the sequence. Moreover, the parameters become part of the sequence  1434         # and thereby participate in a guaranteed evaluation order.  1435   1436         if target or function or known_parameters:  1437             stages[-1] += "(%s)" % argstr  1438             if instantiation:  1439                 return InstantiationResult(instantiation, stages)  1440             else:  1441                 return InvocationResult(stages)  1442   1443         # With unknown targets, the generic invocation function is applied to  1444         # the callable and argument collections.  1445   1446         else:  1447             emit("__invoke(\n%s,\n%d, %d, %s, %s,\n%d, %s\n)" % (  1448                 target_expr,  1449                 self.always_callable(refs) and 1 or 0,  1450                 len(kwargs), kwcodestr, kwargstr,  1451                 len(args), "__ARGS(%s)" % argstr))  1452             return InvocationResult(stages)  1453   1454     def next_target(self):  1455   1456         "Allocate the next function target storage."  1457   1458         self.function_target += 1  1459         self.max_function_target = max(self.function_target, self.max_function_target)  1460   1461     def next_context(self):  1462   1463         "Allocate the next context value storage."  1464   1465         self.context_index += 1  1466         self.max_context_index = max(self.context_index, self.max_context_index)  1467   1468     def always_callable(self, refs):  1469   1470         "Determine whether all 'refs' are callable."  1471   1472         if not refs:  1473             return False  1474   1475         for ref in refs:  1476             if not ref.has_kind("<function>") and not self.importer.get_attributes(ref, "__fn__"):  1477                 return False  1478   1479         return True  1480   1481     def need_default_arguments(self, objpath, nargs):  1482   1483         """  1484         Return whether any default arguments are needed when invoking the object  1485         given by 'objpath'.  1486         """  1487   1488         parameters = self.importer.function_parameters.get(objpath)  1489         return nargs < len(parameters)  1490   1491     def uses_keyword_arguments(self, n):  1492   1493         "Return whether invocation node 'n' uses keyword arguments."  1494   1495         for arg in enumerate(n.args):  1496             if isinstance(arg, compiler.ast.Keyword):  1497                 return True  1498   1499         return False  1500   1501     def get_attributes_for_attrname(self, attrname):  1502   1503         "Return a set of all attributes exposed by 'attrname'."  1504   1505         usage = [(attrname, True, False)]  1506         class_types = self.deducer.get_class_types_for_usage(usage)  1507         instance_types = self.deducer.get_instance_types_for_usage(usage)  1508         module_types = self.deducer.get_module_types_for_usage(usage)  1509         attrs = set()  1510   1511         for ref in combine_types(class_types, instance_types, module_types):  1512             attrs.update(self.importer.get_attributes(ref, attrname))  1513   1514         return attrs  1515   1516     def process_lambda_node(self, n):  1517   1518         "Process the given lambda node 'n'."  1519   1520         name = self.get_lambda_name()  1521         function_name = self.get_object_path(name)  1522   1523         defaults = self.process_function_defaults(n, name, function_name, "__tmp_value")  1524   1525         # Without defaults, produce an attribute referring to the function.  1526   1527         if not defaults:  1528             return make_expression("__ATTRVALUE(&%s)" % encode_path(function_name))  1529   1530         # With defaults, copy the function structure and set the defaults on the  1531         # copy.  1532   1533         else:  1534             self.record_temp("__tmp_value")  1535             return make_expression("(__tmp_value = __ATTRVALUE(__COPY(&%s, sizeof(%s))), %s, __tmp_value)" % (  1536                 encode_path(function_name),  1537                 encode_symbol("obj", function_name),  1538                 ", ".join(defaults)))  1539   1540     def process_logical_node(self, n):  1541   1542         "Process the given operator node 'n'."  1543   1544         self.record_temp("__tmp_result")  1545   1546         conjunction = isinstance(n, compiler.ast.And)  1547         results = []  1548   1549         for node in n.nodes:  1550             results.append(self.process_structure_node(node))  1551   1552         return LogicalOperationResult(results, conjunction)  1553   1554     def process_name_node(self, n, expr=None):  1555   1556         "Process the given name node 'n' with the optional assignment 'expr'."  1557   1558         # Determine whether the name refers to a static external entity.  1559   1560         if n.name in predefined_constants:  1561             return PredefinedConstantRef(n.name, expr)  1562   1563         # Convert literal references, operator function names, and print  1564         # function names to references.  1565   1566         elif n.name.startswith("$L") or n.name.startswith("$op") or \  1567              n.name.startswith("$print"):  1568   1569             ref, paths = self.importer.get_module(self.name).special[n.name]  1570             return TrResolvedNameRef(n.name, ref)  1571   1572         # Get the appropriate name for the name reference, using the same method  1573         # as in the inspector.  1574   1575         path = self.get_namespace_path()  1576         objpath = self.get_object_path(n.name)  1577   1578         # Determine any assigned globals.  1579   1580         globals = self.importer.get_module(self.name).scope_globals.get(path)  1581   1582         # Explicitly declared globals.  1583   1584         if globals and n.name in globals:  1585             objpath = self.get_global_path(n.name)  1586             is_global = True  1587   1588         # Implicitly referenced globals in functions.  1589   1590         elif self.in_function:  1591             is_global = n.name not in self.importer.function_locals[path]  1592   1593         # Implicitly referenced globals elsewhere.  1594   1595         else:  1596             namespace = self.importer.identify(path)  1597             is_global = not self.importer.get_attributes(namespace, n.name)  1598   1599         # Get the static identity of the name.  1600   1601         ref = self.importer.identify(objpath)  1602         if ref and not ref.get_name():  1603             ref = ref.alias(objpath)  1604   1605         # Obtain any resolved names for non-assignment names.  1606   1607         if not expr and not ref and self.in_function:  1608             locals = self.importer.function_locals.get(path)  1609             ref = locals and locals.get(n.name)  1610   1611         # Find any invocation or alias details.  1612   1613         name = self.get_name_for_tracking(n.name, is_global=is_global)  1614         location = not expr and self.get_access_location(name) or None  1615   1616         # Mark any local assignments as volatile in exception blocks.  1617   1618         if expr and self.in_function and not is_global and self.in_try_except:  1619             self.make_volatile(n.name)  1620   1621         # Qualified names are used for resolved static references or for  1622         # static namespace members. The reference should be configured to return  1623         # such names.  1624   1625         name_ref = TrResolvedNameRef(n.name, ref, expr=expr, is_global=is_global,  1626                                      location=location)  1627         return not expr and self.get_aliases(name_ref) or name_ref  1628   1629     def get_aliases(self, name_ref):  1630   1631         "Return alias references for the given 'name_ref'."  1632   1633         location = name_ref.access_location()  1634   1635         refs = self.deducer.referenced_objects.get(location)  1636         refs = refs or self.deducer.accessor_all_types.get(location)  1637         return AliasResult(name_ref, refs or set(), location)  1638   1639     def make_volatile(self, name):  1640   1641         "Record 'name' as volatile in the current namespace."  1642   1643         self.volatile_locals.add(name)  1644   1645     def process_not_node(self, n):  1646   1647         "Process the given operator node 'n'."  1648   1649         return self.make_negation(self.process_structure_node(n.expr))  1650   1651     def process_raise_node(self, n):  1652   1653         "Process the given raise node 'n'."  1654   1655         # NOTE: Determine which raise statement variants should be permitted.  1656   1657         if n.expr1:  1658   1659             # Names with accompanying arguments are treated like invocations.  1660   1661             if n.expr2:  1662                 call = compiler.ast.CallFunc(n.expr1, [n.expr2])  1663                 exc = self.process_structure_node(call)  1664                 self.writestmt("__Raise(%s);" % exc)  1665   1666             # Raise instances, testing the kind at run-time if necessary and  1667             # instantiating any non-instance.  1668   1669             else:  1670                 exc = self.process_structure_node(n.expr1)  1671   1672                 if isinstance(exc, TrInstanceRef):  1673                     self.writestmt("__Raise(%s);" % exc)  1674                 else:  1675                     self.writestmt("__Raise(__ensure_instance(%s));" % exc)  1676         else:  1677             self.writestmt("__Throw(__tmp_exc);")  1678   1679     def process_return_node(self, n):  1680   1681         "Process the given return node 'n'."  1682   1683         expr = self.process_structure_node(n.value) or PredefinedConstantRef("None")  1684         if self.in_try_finally or self.in_try_except:  1685             self.writestmt("__Return(%s);" % expr)  1686         else:  1687             self.writestmt("return %s;" % expr)  1688   1689         return ReturnRef()  1690   1691     def process_try_node(self, n):  1692   1693         """  1694         Process the given "try...except" node 'n'.  1695         """  1696   1697         in_try_except = self.in_try_except  1698         self.in_try_except = True  1699   1700         # Use macros to implement exception handling.  1701   1702         self.writestmt("__Try")  1703         self.writeline("{")  1704         self.indent += 1  1705         self.process_structure_node(n.body)  1706   1707         # Put the else statement in another try block that handles any raised  1708         # exceptions and converts them to exceptions that will not be handled by  1709         # the main handling block.  1710   1711         if n.else_:  1712             self.writestmt("__Try")  1713             self.writeline("{")  1714             self.indent += 1  1715             self.process_structure_node(n.else_)  1716             self.indent -= 1  1717             self.writeline("}")  1718             self.writeline("__Catch (__tmp_exc)")  1719             self.writeline("{")  1720             self.indent += 1  1721             self.writeline("if (__tmp_exc.raising) __RaiseElse(__tmp_exc.arg);")  1722             self.writeline("else if (__tmp_exc.completing) __Throw(__tmp_exc);")  1723             self.indent -= 1  1724             self.writeline("}")  1725   1726         # Complete the try block and enter the finally block, if appropriate.  1727   1728         if self.in_try_finally:  1729             self.writestmt("__Complete;")  1730   1731         self.indent -= 1  1732         self.writeline("}")  1733   1734         self.in_try_except = in_try_except  1735   1736         # Handlers are tests within a common handler block.  1737   1738         self.writeline("__Catch (__tmp_exc)")  1739         self.writeline("{")  1740         self.indent += 1  1741   1742         # Introduce an if statement to handle the completion of a try block.  1743   1744         self.process_try_completion()  1745   1746         # Handle exceptions in else blocks converted to __RaiseElse, converting  1747         # them back to normal exceptions.  1748   1749         if n.else_:  1750             self.writeline("else if (__tmp_exc.raising_else) __Raise(__tmp_exc.arg);")  1751   1752         # Exception handling.  1753   1754         for name, var, handler in n.handlers:  1755   1756             # Test for specific exceptions.  1757   1758             if name is not None:  1759                 name_ref = self.process_structure_node(name)  1760                 self.writeline("else if (__ISINSTANCE(__tmp_exc.arg, %s))" % name_ref)  1761             else:  1762                 self.writeline("else if (1)")  1763   1764             self.writeline("{")  1765             self.indent += 1  1766   1767             # Establish the local for the handler.  1768   1769             if var is not None:  1770                 self.writestmt("%s;" % self.process_name_node(var, make_expression("__tmp_exc.arg")))  1771   1772             if handler is not None:  1773                 self.process_structure_node(handler)  1774   1775             self.indent -= 1  1776             self.writeline("}")  1777   1778         # Re-raise unhandled exceptions.  1779   1780         self.writeline("else __Throw(__tmp_exc);")  1781   1782         # End the handler block.  1783   1784         self.indent -= 1  1785         self.writeline("}")  1786         print >>self.out  1787   1788     def process_try_finally_node(self, n):  1789   1790         """  1791         Process the given "try...finally" node 'n'.  1792         """  1793   1794         in_try_finally = self.in_try_finally  1795         self.in_try_finally = True  1796   1797         # Use macros to implement exception handling.  1798   1799         self.writestmt("__Try")  1800         self.writeline("{")  1801         self.indent += 1  1802         self.process_structure_node(n.body)  1803         self.indent -= 1  1804         self.writeline("}")  1805   1806         self.in_try_finally = in_try_finally  1807   1808         # Finally clauses handle special exceptions.  1809   1810         self.writeline("__Catch (__tmp_exc)")  1811         self.writeline("{")  1812         self.indent += 1  1813         self.process_structure_node(n.final)  1814   1815         # Introduce an if statement to handle the completion of a try block.  1816   1817         self.process_try_completion()  1818         self.writeline("else __Throw(__tmp_exc);")  1819   1820         self.indent -= 1  1821         self.writeline("}")  1822         print >>self.out  1823   1824     def process_try_completion(self):  1825   1826         "Generate a test for the completion of a try block."  1827   1828         self.writestmt("if (__tmp_exc.completing)")  1829         self.writeline("{")  1830         self.indent += 1  1831   1832         # Do not return anything at the module level.  1833   1834         if self.get_namespace_path() != self.name:  1835   1836             # Only use the normal return statement if no surrounding try blocks  1837             # apply.  1838   1839             if not self.in_try_finally and not self.in_try_except:  1840                 self.writeline("if (!__ISNULL(__tmp_exc.arg)) return __tmp_exc.arg;")  1841             else:  1842                 self.writeline("if (!__ISNULL(__tmp_exc.arg)) __Throw(__tmp_exc);")  1843   1844         self.indent -= 1  1845         self.writeline("}")  1846   1847     def process_while_node(self, n):  1848   1849         "Process the given while node 'n'."  1850   1851         self.writeline("while (1)")  1852         self.writeline("{")  1853         self.indent += 1  1854         test = self.process_structure_node(n.test)  1855   1856         # Emit the loop termination condition unless "while <true value>" is  1857         # indicated.  1858   1859         if not (isinstance(test, PredefinedConstantRef) and test.value):  1860   1861             # Emit a negated test of the continuation condition.  1862   1863             self.start_if(True, self.make_negation(test))  1864             if n.else_:  1865                 self.process_structure_node(n.else_)  1866             self.writestmt("break;")  1867             self.end_if()  1868   1869         in_conditional = self.in_conditional  1870         self.in_conditional = True  1871         self.process_structure_node(n.body)  1872         self.in_conditional = in_conditional  1873   1874         self.indent -= 1  1875         self.writeline("}")  1876         print >>self.out  1877   1878     # Special variable usage.  1879   1880     def get_temp_path(self):  1881   1882         """  1883         Return the appropriate namespace path for temporary names in the current  1884         namespace.  1885         """  1886   1887         if self.in_function:  1888             return self.get_namespace_path()  1889         else:  1890             return self.name  1891   1892     def record_temp(self, name):  1893   1894         """  1895         Record the use of the temporary 'name' in the current namespace. At the  1896         class or module level, the temporary name is associated with the module,  1897         since the variable will then be allocated in the module's own main  1898         program.  1899         """  1900   1901         path = self.get_temp_path()  1902   1903         init_item(self.temp_usage, path, list)  1904         self.temp_usage[path].append(name)  1905   1906     def remove_temps(self, names):  1907   1908         """  1909         Remove 'names' from temporary storage allocations, each instance  1910         removing each request for storage.  1911         """  1912   1913         path = self.get_temp_path()  1914   1915         for name in names:  1916             if self.uses_temp(path, name):  1917                 self.temp_usage[path].remove(name)  1918   1919     def uses_temp(self, path, name):  1920   1921         """  1922         Return whether the given namespace 'path' employs a temporary variable  1923         with the given 'name'. Note that 'path' should only be a module or a  1924         function or method, not a class.  1925         """  1926   1927         return self.temp_usage.has_key(path) and name in self.temp_usage[path]  1928   1929     def make_negation(self, expr):  1930   1931         "Return a negated form of 'expr'."  1932   1933         result = NegationResult(expr)  1934   1935         # Negation discards the temporary results of its operand.  1936   1937         temps = expr.discards_temporary()  1938         if temps:  1939             self.remove_temps(temps)  1940   1941         return result  1942   1943     # Output generation.  1944   1945     def start_output(self):  1946   1947         "Write the declarations at the top of each source file."  1948   1949         print >>self.out, """\  1950 #include "types.h"  1951 #include "exceptions.h"  1952 #include "ops.h"  1953 #include "progconsts.h"  1954 #include "progops.h"  1955 #include "progtypes.h"  1956 #include "main.h"  1957 """  1958   1959     def start_unit(self):  1960   1961         "Record output within a generated function for later use."  1962   1963         self.out = StringIO()  1964   1965     def end_unit(self):  1966   1967         "Restore the output stream."  1968   1969         out = self.out  1970         self.out = self.out_toplevel  1971         return out  1972   1973     def flush_unit(self, name, out):  1974   1975         "Add declarations and generated code."  1976   1977         self.write_temporaries(name)  1978         print >>self.out  1979         out.seek(0)  1980         self.out.write(out.read())  1981   1982     def start_module(self):  1983   1984         "Write the start of each module's main function."  1985   1986         print >>self.out, "void __main_%s()" % encode_path(self.name)  1987         print >>self.out, "{"  1988         self.indent += 1  1989   1990         # Define temporary variables, excluded from the module structure itself.  1991   1992         tempnames = []  1993   1994         for n in self.importer.all_module_attrs[self.name]:  1995             if n.startswith("$t"):  1996                 tempnames.append(encode_path(n))  1997   1998         if tempnames:  1999             tempnames.sort()  2000             self.writeline("__attr %s;" % ", ".join(tempnames))  2001   2002         self.start_unit()  2003   2004     def end_module(self):  2005   2006         "End each module by closing its main function."  2007   2008         out = self.end_unit()  2009         self.flush_unit(self.name, out)  2010   2011         self.indent -= 1  2012         print >>self.out, "}"  2013   2014     def start_function(self, name):  2015   2016         "Start the function having the given 'name'."  2017   2018         self.indent += 1  2019   2020         self.start_unit()  2021   2022     def end_function(self, name):  2023   2024         "End the function having the given 'name'."  2025   2026         out = self.end_unit()  2027   2028         # Write the signature at the top indentation level.  2029   2030         self.indent -= 1  2031         self.write_parameters(name)  2032         print >>self.out, "{"  2033   2034         # Obtain local names from parameters.  2035   2036         parameters = self.importer.function_parameters[name]  2037         locals = self.importer.function_locals[name].keys()  2038         names = []  2039         volatile_names = []  2040   2041         for n in locals:  2042   2043             # Filter out special names and parameters. Note that self is a local  2044             # regardless of whether it originally appeared in the parameters or  2045             # not.  2046   2047             if n.startswith("$l") or n in parameters or n == "self":  2048                 continue  2049             if n in self.volatile_locals:  2050                 volatile_names.append(encode_path(n))  2051             else:  2052                 names.append(encode_path(n))  2053   2054         # Emit required local names at the function indentation level.  2055   2056         self.indent += 1  2057   2058         if names:  2059             names.sort()  2060             self.writeline("__attr %s;" % ", ".join(names))  2061   2062         if volatile_names:  2063             volatile_names.sort()  2064             self.writeline("volatile __attr %s;" % ", ".join(volatile_names))  2065   2066         self.flush_unit(name, out)  2067   2068         self.indent -= 1  2069         print >>self.out, "}"  2070         print >>self.out  2071   2072     def write_parameters(self, name):  2073   2074         """  2075         For the function having the given 'name', write definitions of  2076         parameters found in the arguments array.  2077         """  2078   2079         # Generate any self reference.  2080   2081         l = []  2082   2083         if self.is_method(name):  2084             l.append("__attr self")  2085         else:  2086             l.append("__attr __self")  2087   2088         # Generate aliases for the parameters.  2089   2090         for parameter in self.importer.function_parameters[name]:  2091             l.append("%s__attr %s" % (  2092                 parameter in self.volatile_locals and "volatile " or "",  2093                 encode_path(parameter)))  2094   2095         self.writeline("__attr %s(%s)" % (  2096             encode_function_pointer(name), ", ".join(l)))  2097   2098     def write_temporaries(self, name):  2099   2100         "Write temporary storage employed by 'name'."  2101   2102         # Provide space for the given number of targets.  2103   2104         targets = self.max_function_target  2105   2106         if self.uses_temp(name, "__tmp_targets"):  2107             self.writeline("__attr __tmp_targets[%d];" % targets)  2108   2109         index = self.max_context_index  2110   2111         if self.uses_temp(name, "__tmp_contexts"):  2112             self.writeline("__attr __tmp_contexts[%d];" % index)  2113   2114         # Add temporary variable usage details.  2115   2116         if self.uses_temp(name, "__tmp_private_context"):  2117             self.writeline("__attr __tmp_private_context;")  2118         if self.uses_temp(name, "__tmp_value"):  2119             self.writeline("__attr __tmp_value;")  2120         if self.uses_temp(name, "__tmp_target_value"):  2121             self.writeline("__attr __tmp_target_value;")  2122         if self.uses_temp(name, "__tmp_result"):  2123             self.writeline("__attr __tmp_result;")  2124   2125         module = self.importer.get_module(self.name)  2126   2127         if name in module.exception_namespaces:  2128             self.writeline("__exc __tmp_exc;")  2129   2130     def start_if(self, first, test_ref):  2131         statement = "%sif" % (not first and "else " or "")  2132   2133         # Consume logical results directly.  2134   2135         if isinstance(test_ref, LogicalResult):  2136             self.writeline("%s %s" % (statement, test_ref.apply_test()))  2137             temps = test_ref.discards_temporary()  2138             if temps:  2139                 self.remove_temps(temps)  2140         else:  2141             self.writeline("%s (__BOOL(%s))" % (statement, test_ref))  2142   2143         self.writeline("{")  2144         self.indent += 1  2145   2146     def end_if(self):  2147         self.indent -= 1  2148         self.writeline("}")  2149   2150     def start_else(self):  2151         self.writeline("else")  2152         self.writeline("{")  2153         self.indent += 1  2154   2155     def end_else(self):  2156         self.indent -= 1  2157         self.writeline("}")  2158   2159     def statement(self, expr):  2160         s = str(expr)  2161         if s:  2162             self.writestmt("%s;" % s)  2163   2164     def statements(self, results):  2165         for result in results:  2166             self.statement(result)  2167   2168     def writeline(self, s):  2169         print >>self.out, "%s%s" % (self.pad(), self.indenttext(s, self.indent + 1))  2170   2171     def writestmt(self, s):  2172         self.writeline(s)  2173   2174     def write_comment(self, s):  2175         self.writestmt("/* %s */" % s)  2176   2177     def pad(self, extra=0):  2178         return (self.indent + extra) * self.tabstop  2179   2180     def indenttext(self, s, levels):  2181         lines = s.split("\n")  2182         out = [lines[0]]  2183         for line in lines[1:]:  2184             out.append(levels * self.tabstop + line)  2185             if line.endswith("("):  2186                 levels += 1  2187             elif line.startswith(")"):  2188                 levels -= 1  2189         return "\n".join(out)  2190   2191 # vim: tabstop=4 expandtab shiftwidth=4