Lichen

translator.py

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