Lichen

inspector.py

710:0c0c79505672
2017-03-12 Paul Boddie Merged changes from the default branch. return-value-definition
     1 #!/usr/bin/env python     2      3 """     4 Inspect and obtain module structure.     5      6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013,     7               2014, 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>     8      9 This program is free software; you can redistribute it and/or modify it under    10 the terms of the GNU General Public License as published by the Free Software    11 Foundation; either version 3 of the License, or (at your option) any later    12 version.    13     14 This program is distributed in the hope that it will be useful, but WITHOUT    15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    16 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    17 details.    18     19 You should have received a copy of the GNU General Public License along with    20 this program.  If not, see <http://www.gnu.org/licenses/>.    21 """    22     23 from branching import BranchTracker    24 from common import CommonModule, get_argnames, init_item, predefined_constants    25 from modules import BasicModule, CacheWritingModule, InspectionNaming    26 from errors import InspectError    27 from referencing import Reference    28 from resolving import NameResolving    29 from results import AccessRef, InstanceRef, InvocationRef, LiteralSequenceRef, \    30                     LocalNameRef, NameRef, ResolvedNameRef, VariableRef    31 import compiler    32 import sys    33     34 class InspectedModule(BasicModule, CacheWritingModule, NameResolving, InspectionNaming):    35     36     "A module inspector."    37     38     def __init__(self, name, importer):    39     40         "Initialise the module with basic details."    41     42         BasicModule.__init__(self, name, importer)    43     44         self.in_class = False    45         self.in_conditional = False    46     47         # Accesses to global attributes.    48     49         self.global_attr_accesses = {}    50     51         # Usage tracking.    52     53         self.trackers = []    54         self.attr_accessor_branches = {}    55     56     def __repr__(self):    57         return "InspectedModule(%r, %r)" % (self.name, self.importer)    58     59     # Principal methods.    60     61     def parse(self, filename):    62     63         "Parse the file having the given 'filename'."    64     65         self.parse_file(filename)    66     67         # Inspect the module.    68     69         self.start_tracking_in_module()    70     71         # Detect and record imports and globals declared in the module.    72     73         self.process_structure(self.astnode)    74     75         # Set the class of the module after the definition has occurred.    76     77         ref = self.get_builtin("module")    78         self.set_name("__class__", ref)    79         self.set_name("__name__", self.get_constant("string", self.name).reference())    80         self.set_name("__file__", self.get_constant("string", filename).reference())    81     82         # Reserve a constant for the encoding.    83     84         if self.encoding:    85             self.get_constant("string", self.encoding)    86     87         # Get module-level attribute usage details.    88     89         self.stop_tracking_in_module()    90     91         # Collect external name references.    92     93         self.collect_names()    94     95     def complete(self):    96     97         "Complete the module inspection."    98     99         # Resolve names not definitively mapped to objects.   100    101         self.resolve()   102    103         # Propagate to the importer information needed in subsequent activities.   104    105         self.propagate()   106    107     # Accessory methods.   108    109     def collect_names(self):   110    111         "Collect the names used by each scope."   112    113         for path in self.names_used.keys():   114             self.collect_names_for_path(path)   115    116     def collect_names_for_path(self, path):   117    118         """   119         Collect the names used by the given 'path'. These are propagated to the   120         importer in advance of any dependency resolution.   121         """   122    123         names = self.names_used.get(path)   124         if not names:   125             return   126    127         in_function = self.function_locals.has_key(path)   128    129         for name in names:   130             if in_function and name in self.function_locals[path]:   131                 continue   132    133             key = "%s.%s" % (path, name)   134    135             # Find local definitions (within dynamic namespaces).   136    137             ref = self.get_resolved_object(key)   138             if ref:   139                 self.set_name_reference(key, ref)   140                 continue   141    142             # Find global.   143    144             ref = self.get_global(name)   145             if ref:   146                 self.set_name_reference(key, ref)   147                 continue   148    149             # Find presumed built-in definitions.   150    151             ref = self.get_builtin(name)   152             self.set_name_reference(key, ref)   153    154     def set_name_reference(self, path, ref):   155    156         "Map the given name 'path' to 'ref'."   157    158         self.importer.all_name_references[path] = self.name_references[path] = ref   159    160     # Module structure traversal.   161    162     def process_structure_node(self, n):   163    164         "Process the individual node 'n'."   165    166         path = self.get_namespace_path()   167    168         # Module global detection.   169    170         if isinstance(n, compiler.ast.Global):   171             self.process_global_node(n)   172    173         # Module import declarations.   174    175         elif isinstance(n, compiler.ast.From):   176             self.process_from_node(n)   177    178         elif isinstance(n, compiler.ast.Import):   179             self.process_import_node(n)   180    181         # Nodes using operator module functions.   182    183         elif isinstance(n, compiler.ast.Operator):   184             return self.process_operator_node(n)   185    186         elif isinstance(n, compiler.ast.AugAssign):   187             self.process_augassign_node(n)   188    189         elif isinstance(n, compiler.ast.Compare):   190             return self.process_compare_node(n)   191    192         elif isinstance(n, compiler.ast.Slice):   193             return self.process_slice_node(n)   194    195         elif isinstance(n, compiler.ast.Sliceobj):   196             return self.process_sliceobj_node(n)   197    198         elif isinstance(n, compiler.ast.Subscript):   199             return self.process_subscript_node(n)   200    201         # Namespaces within modules.   202    203         elif isinstance(n, compiler.ast.Class):   204             self.process_class_node(n)   205    206         elif isinstance(n, compiler.ast.Function):   207             self.process_function_node(n, n.name)   208    209         elif isinstance(n, compiler.ast.Lambda):   210             return self.process_lambda_node(n)   211    212         # Assignments.   213    214         elif isinstance(n, compiler.ast.Assign):   215    216             # Handle each assignment node.   217    218             for node in n.nodes:   219                 self.process_assignment_node(node, n.expr)   220    221         # Assignments within non-Assign nodes.   222    223         elif isinstance(n, compiler.ast.AssName):   224             raise InspectError("Name assignment appearing outside assignment statement.", path, n)   225    226         elif isinstance(n, compiler.ast.AssAttr):   227             raise InspectError("Attribute assignment appearing outside assignment statement.", path, n)   228    229         # Accesses.   230    231         elif isinstance(n, compiler.ast.Getattr):   232             return self.process_attribute_access(n)   233    234         # Name recording for later testing.   235    236         elif isinstance(n, compiler.ast.Name):   237             return self.process_name_node(n)   238    239         # Conditional statement tracking.   240    241         elif isinstance(n, compiler.ast.For):   242             self.process_for_node(n)   243    244         elif isinstance(n, compiler.ast.While):   245             self.process_while_node(n)   246    247         elif isinstance(n, compiler.ast.If):   248             self.process_if_node(n)   249    250         elif isinstance(n, (compiler.ast.And, compiler.ast.Or)):   251             return self.process_logical_node(n)   252    253         # Exception control-flow tracking.   254    255         elif isinstance(n, compiler.ast.TryExcept):   256             self.process_try_node(n)   257    258         elif isinstance(n, compiler.ast.TryFinally):   259             self.process_try_finally_node(n)   260    261         # Control-flow modification statements.   262    263         elif isinstance(n, compiler.ast.Break):   264             self.trackers[-1].suspend_broken_branch()   265    266         elif isinstance(n, compiler.ast.Continue):   267             self.trackers[-1].suspend_continuing_branch()   268    269         elif isinstance(n, compiler.ast.Raise):   270             self.process_structure(n)   271             self.trackers[-1].abandon_branch()   272    273         elif isinstance(n, compiler.ast.Return):   274             self.record_return_value(self.process_structure_node(n.value))   275             self.trackers[-1].abandon_returning_branch()   276    277         # Print statements.   278    279         elif isinstance(n, (compiler.ast.Print, compiler.ast.Printnl)):   280             self.process_print_node(n)   281    282         # Invocations.   283    284         elif isinstance(n, compiler.ast.CallFunc):   285             return self.process_invocation_node(n)   286    287         # Constant usage.   288    289         elif isinstance(n, compiler.ast.Const):   290             return self.get_literal_instance(n)   291    292         elif isinstance(n, compiler.ast.Dict):   293             return self.get_literal_instance(n, "dict")   294    295         elif isinstance(n, compiler.ast.List):   296             return self.get_literal_instance(n, "list")   297    298         elif isinstance(n, compiler.ast.Tuple):   299             return self.get_literal_instance(n, "tuple")   300    301         # All other nodes are processed depth-first.   302    303         else:   304             self.process_structure(n)   305    306         # By default, no expression details are returned.   307    308         return None   309    310     # Specific node handling.   311    312     def process_assignment_node(self, n, expr):   313    314         "Process the individual node 'n' to be assigned the contents of 'expr'."   315    316         # Names and attributes are assigned the entire expression.   317    318         if isinstance(n, compiler.ast.AssName):   319             if n.name == "self":   320                 raise InspectError("Redefinition of self is not allowed.", self.get_namespace_path(), n)   321    322             name_ref = expr and self.process_structure_node(expr)   323    324             # Name assignments populate either function namespaces or the   325             # general namespace hierarchy.   326    327             self.assign_general_local(n.name, name_ref)   328    329             # Record usage of the name.   330    331             self.record_name(n.name)   332    333         elif isinstance(n, compiler.ast.AssAttr):   334             if expr:   335                 expr = self.process_structure_node(expr)   336    337             in_assignment = self.in_assignment   338             self.in_assignment = True   339             self.process_attribute_access(n)   340             self.in_assignment = in_assignment   341    342         # Lists and tuples are matched against the expression and their   343         # items assigned to expression items.   344    345         elif isinstance(n, (compiler.ast.AssList, compiler.ast.AssTuple)):   346             self.process_assignment_node_items(n, expr)   347    348         # Slices and subscripts are permitted within assignment nodes.   349    350         elif isinstance(n, compiler.ast.Slice):   351             self.process_slice_node(n, expr)   352    353         elif isinstance(n, compiler.ast.Subscript):   354             self.process_subscript_node(n, expr)   355    356     def process_attribute_access(self, n):   357    358         "Process the given attribute access node 'n'."   359    360         # Obtain any completed chain and return the reference to it.   361    362         name_ref = self.process_attribute_chain(n)   363    364         if self.have_access_expression(n):   365             return name_ref   366    367         # Where the start of the chain of attributes has been reached, determine   368         # the complete access.   369    370         # Given a non-access node, this chain can be handled in its entirety,   371         # either being name-based and thus an access rooted on a name, or being   372         # based on some other node and thus an anonymous access of some kind.   373    374         path = self.get_namespace_path()   375    376         # Start with the the full attribute chain.   377    378         remaining = self.attrs   379         attrnames = ".".join(remaining)   380    381         # If the accessor cannot be identified, or where attributes   382         # remain in an attribute chain, record the anonymous accesses.   383    384         if not isinstance(name_ref, NameRef): # includes ResolvedNameRef   385    386             init_item(self.attr_accesses, path, set)   387             self.attr_accesses[path].add(attrnames)   388    389             self.record_access_details(None, attrnames, self.in_assignment,   390                 self.in_invocation)   391             del self.attrs[0]   392             return   393    394         # Name-based accesses will handle the first attribute in a   395         # chain.   396    397         else:   398             attrname = remaining[0]   399    400             # Attribute assignments are used to identify instance attributes.   401    402             if isinstance(n, compiler.ast.AssAttr) and \   403                 self.in_class and self.in_function and n.expr.name == "self":   404    405                 self.set_instance_attr(attrname)   406    407             # Record attribute usage using any name local to this namespace,   408             # if assigned in the namespace, or using an external name   409             # (presently just globals within classes).   410    411             name = self.get_name_for_tracking(name_ref.name, name_ref)   412             tracker = self.trackers[-1]   413    414             immediate_access = len(self.attrs) == 1   415             assignment = immediate_access and isinstance(n, compiler.ast.AssAttr)   416    417             # Record global-based chains for subsequent resolution.   418    419             if name_ref.is_global_name():   420                 self.record_global_access_details(name, attrnames)   421    422             # Make sure the name is being tracked: global names will not   423             # already be initialised in a branch and must be added   424             # explicitly.   425    426             if not tracker.have_name(name):   427                 tracker.assign_names([name])   428                 if self.in_function:   429                     self.scope_globals[path].add(name)   430    431             # Record attribute usage in the tracker, and record the branch   432             # information for the access.   433    434             branches = tracker.use_attribute(name, attrname,   435                 self.in_invocation is not None, assignment)   436    437             if not branches:   438                 raise InspectError("Name %s is accessed using %s before an assignment." % (   439                     name, attrname), path, n)   440    441             self.record_branches_for_access(branches, name, attrnames)   442             access_number = self.record_access_details(name, attrnames,   443                 self.in_assignment, self.in_invocation)   444    445             del self.attrs[0]   446             return AccessRef(name, attrnames, access_number)   447    448     def process_class_node(self, n):   449    450         "Process the given class node 'n'."   451    452         path = self.get_namespace_path()   453    454         # To avoid notions of class "versions" where the same definition   455         # might be parameterised with different state and be referenced   456         # elsewhere (as base classes, for example), classes in functions or   457         # conditions are forbidden.   458    459         if self.in_function or self.in_conditional:   460             print >>sys.stderr, "In %s, class %s in function or conditional statement ignored." % (   461                 path, n.name)   462             return   463    464         # Resolve base classes.   465    466         bases = []   467    468         for base in n.bases:   469             base_class = self.get_class(base)   470    471             if not base_class:   472                 print >>sys.stderr, "In %s, class %s has unidentifiable base class: %s" % (   473                     path, n.name, base)   474                 return   475             else:   476                 bases.append(base_class)   477    478         # Detect conflicting definitions. Such definitions cause conflicts in   479         # the storage of namespace-related information.   480    481         class_name = self.get_object_path(n.name)   482         ref = self.get_object(class_name, defer=False)   483    484         if ref and ref.static():   485             raise InspectError("Multiple definitions for the same name are not permitted.", class_name, n)   486    487         # Record bases for the class and retain the class name.   488         # Note that the function class does not inherit from the object class.   489    490         if not bases and class_name != "__builtins__.core.object" and \   491                          class_name != "__builtins__.core.function":   492    493             ref = self.get_object("__builtins__.object")   494             bases.append(ref)   495    496         self.importer.classes[class_name] = self.classes[class_name] = bases   497         self.importer.subclasses[class_name] = set()   498         self.scope_globals[class_name] = set()   499    500         # Set the definition before entering the namespace rather than   501         # afterwards because methods may reference it. In normal Python,   502         # a class is not accessible until the definition is complete, but   503         # methods can generally reference it since upon being called the   504         # class will already exist.   505    506         self.set_definition(n.name, "<class>")   507    508         in_class = self.in_class   509         self.in_class = class_name   510         self.set_instance_attr("__class__", Reference("<class>", class_name))   511         self.enter_namespace(n.name)   512    513         # Do not provide the special instantiator attributes on the function   514         # class. Function instances provide these attributes.   515    516         if class_name != "__builtins__.core.function":   517    518             self.set_name("__fn__") # special instantiator attribute   519             self.set_name("__args__") # special instantiator attribute   520    521         # Provide leafname, parent and context attributes.   522    523         parent, leafname = class_name.rsplit(".", 1)   524         self.set_name("__name__", self.get_constant("string", leafname).reference())   525    526         if class_name != "__builtins__.core.function":   527             self.set_name("__parent__")   528    529         self.process_structure_node(n.code)   530         self.exit_namespace()   531         self.in_class = in_class   532    533     def process_from_node(self, n):   534    535         "Process the given node 'n', importing from another module."   536    537         path = self.get_namespace_path()   538    539         module_name, names = self.get_module_name(n)   540         if module_name == self.name:   541             raise InspectError("Cannot import from the current module.", path, n)   542    543         self.queue_module(module_name)   544    545         # Attempt to obtain the referenced objects.   546    547         for name, alias in n.names:   548             if name == "*":   549                 raise InspectError("Only explicitly specified names can be imported from modules.", path, n)   550    551             # Explicit names.   552    553             ref = self.import_name_from_module(name, module_name)   554             value = ResolvedNameRef(alias or name, ref)   555             self.set_general_local(alias or name, value)   556    557     def process_function_node(self, n, name):   558    559         """   560         Process the given function or lambda node 'n' with the given 'name'.   561         """   562    563         is_lambda = isinstance(n, compiler.ast.Lambda)   564    565         # Where a function is declared conditionally, use a separate name for   566         # the definition, and assign the definition to the stated name.   567    568         if (self.in_conditional or self.in_function) and not is_lambda:   569             original_name = name   570             name = self.get_lambda_name()   571         else:   572             original_name = None   573    574         # Detect conflicting definitions. Such definitions cause conflicts in   575         # the storage of namespace-related information.   576    577         function_name = self.get_object_path(name)   578         ref = self.get_object(function_name, defer=False)   579    580         if ref and ref.static():   581             raise InspectError("Multiple definitions for the same name are not permitted.", function_name, n)   582    583         # Initialise argument and local records.   584    585         argnames = get_argnames(n.argnames)   586         is_method = self.in_class and not self.in_function   587    588         # Remove explicit "self" from method parameters.   589    590         if is_method and argnames and argnames[0] == "self":   591             del argnames[0]   592    593         # Copy and propagate the parameters.   594    595         self.importer.function_parameters[function_name] = \   596             self.function_parameters[function_name] = argnames[:]   597    598         # Define all arguments/parameters in the local namespace.   599    600         locals = \   601             self.importer.function_locals[function_name] = \   602             self.function_locals[function_name] = {}   603    604         # Insert "self" into method locals.   605    606         if is_method:   607             argnames.insert(0, "self")   608    609         # Define "self" in terms of the class if in a method.   610         # This does not diminish the need for type-narrowing in the deducer.   611    612         if argnames:   613             if self.in_class and not self.in_function and argnames[0] == "self":   614                 locals[argnames[0]] = Reference("<instance>", self.in_class)   615             else:   616                 locals[argnames[0]] = Reference("<var>")   617    618         for argname in argnames[1:]:   619             locals[argname] = Reference("<var>")   620    621         globals = self.scope_globals[function_name] = set()   622    623         # Process the defaults.   624    625         defaults = self.importer.function_defaults[function_name] = \   626                    self.function_defaults[function_name] = []   627    628         for argname, default in compiler.ast.get_defaults(n):   629             if default:   630    631                 # Obtain any reference for the default.   632    633                 name_ref = self.process_structure_node(default)   634                 defaults.append((argname, name_ref.is_name() and name_ref.reference() or Reference("<var>")))   635    636         # Reset conditional tracking to focus on the function contents.   637    638         in_conditional = self.in_conditional   639         self.in_conditional = False   640    641         in_function = self.in_function   642         self.in_function = function_name   643    644         self.enter_namespace(name)   645    646         # Define a leafname attribute value for the function instance.   647    648         ref = self.get_builtin_class("string")   649         self.reserve_constant(function_name, name, ref.get_origin())   650    651         # Track attribute usage within the namespace.   652    653         path = self.get_namespace_path()   654    655         self.start_tracking(locals)   656         self.process_structure_node(n.code)   657         returns_value = self.stop_tracking()   658    659         # Record any null result.   660    661         is_initialiser = is_method and name == "__init__"   662    663         if not returns_value and not is_initialiser:   664             self.record_return_value(ResolvedNameRef("None", self.get_builtin("None")))   665    666         # Exit to the parent.   667    668         self.exit_namespace()   669    670         # Update flags.   671    672         self.in_function = in_function   673         self.in_conditional = in_conditional   674    675         # Define the function using the appropriate name.   676    677         self.set_definition(name, "<function>")   678    679         # Where a function is set conditionally, assign the name.   680    681         if original_name:   682             self.process_assignment_for_object(original_name, compiler.ast.Name(name))   683    684     def process_global_node(self, n):   685    686         """   687         Process the given "global" node 'n'.   688         """   689    690         path = self.get_namespace_path()   691    692         if path != self.name:   693             self.scope_globals[path].update(n.names)   694    695     def process_if_node(self, n):   696    697         """   698         Process the given "if" node 'n'.   699         """   700    701         tracker = self.trackers[-1]   702         tracker.new_branchpoint()   703    704         for test, body in n.tests:   705             self.process_structure_node(test)   706    707             tracker.new_branch()   708    709             in_conditional = self.in_conditional   710             self.in_conditional = True   711             self.process_structure_node(body)   712             self.in_conditional = in_conditional   713    714             tracker.shelve_branch()   715    716         # Maintain a branch for the else clause.   717    718         tracker.new_branch()   719         if n.else_:   720             self.process_structure_node(n.else_)   721         tracker.shelve_branch()   722    723         tracker.merge_branches()   724    725     def process_import_node(self, n):   726    727         "Process the given import node 'n'."   728    729         path = self.get_namespace_path()   730    731         # Load the mentioned module.   732    733         for name, alias in n.names:   734             if name == self.name:   735                 raise InspectError("Cannot import the current module.", path, n)   736    737             self.set_module(alias or name.split(".")[-1], name)   738             self.queue_module(name, True)   739    740     def process_invocation_node(self, n):   741    742         "Process the given invocation node 'n'."   743    744         path = self.get_namespace_path()   745    746         in_invocation = self.in_invocation   747         self.in_invocation = None   748    749         # Process the arguments.   750    751         keywords = set()   752    753         for arg in n.args:   754             self.process_structure_node(arg)   755             if isinstance(arg, compiler.ast.Keyword):   756                 keywords.add(arg.name)   757    758         keywords = list(keywords)   759         keywords.sort()   760    761         # Communicate to the invocation target expression that it forms the   762         # target of an invocation, potentially affecting attribute accesses.   763    764         self.in_invocation = len(n.args), keywords   765    766         # Process the expression, obtaining any identified reference.   767    768         name_ref = self.process_structure_node(n.node)   769         self.in_invocation = in_invocation   770    771         # Detect class invocations.   772    773         if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind("<class>"):   774             return InstanceRef(name_ref.reference().instance_of())   775    776         elif isinstance(name_ref, (NameRef, AccessRef)):   777             return InvocationRef(name_ref)   778    779         # Provide a general reference to indicate that something is produced   780         # by the invocation, useful for retaining assignment expression   781         # details.   782    783         return VariableRef()   784    785     def process_lambda_node(self, n):   786    787         "Process the given lambda node 'n'."   788    789         name = self.get_lambda_name()   790         self.process_function_node(n, name)   791    792         origin = self.get_object_path(name)   793    794         if self.function_defaults.get(origin):   795             return None   796         else:   797             return ResolvedNameRef(name, Reference("<function>", origin))   798    799     def process_logical_node(self, n):   800    801         "Process the given operator node 'n'."   802    803         self.process_operator_chain(n.nodes, self.process_structure_node)   804    805     def process_name_node(self, n):   806    807         "Process the given name node 'n'."   808    809         path = self.get_namespace_path()   810    811         # Find predefined constant names before anything else.   812    813         if n.name in predefined_constants:   814             ref = self.get_builtin(n.name)   815             value = ResolvedNameRef(n.name, ref)   816             return value   817    818         # Special names that have already been identified.   819    820         if n.name.startswith("$"):   821             value = self.get_special(n.name)   822             if value:   823                 return value   824    825         # Special case for operator functions introduced through code   826         # transformations.   827    828         if n.name.startswith("$op"):   829    830             # Obtain the location of the actual function defined in the operator   831             # package.   832    833             op = n.name[len("$op"):]   834    835             # Attempt to get a reference.   836    837             ref = self.import_name_from_module(op, "operator")   838    839             # Record the imported name and provide the resolved name reference.   840    841             value = ResolvedNameRef(n.name, ref)   842             self.set_special(n.name, value)   843             return value   844    845         # Special case for print operations.   846    847         elif n.name.startswith("$print"):   848    849             # Attempt to get a reference.   850    851             ref = self.get_builtin("print_")   852    853             # Record the imported name and provide the resolved name reference.   854    855             value = ResolvedNameRef(n.name, ref)   856             self.set_special(n.name, value)   857             return value   858    859         # Test for self usage, which is only allowed in methods.   860    861         if n.name == "self" and not (self.in_function and self.in_class):   862             raise InspectError("Use of self is only allowed in methods.", path, n)   863    864         # Record usage of the name.   865    866         self.record_name(n.name)   867    868         # Search for unknown names in non-function scopes immediately.   869         # External names in functions are resolved later.   870    871         ref = self.find_name(n.name)   872         if ref:   873             self.record_name_access(n.name, True)   874             return ResolvedNameRef(n.name, ref, is_global=True)   875    876         # Explicitly-declared global names.   877    878         elif self.in_function and n.name in self.scope_globals[path]:   879             self.record_name_access(n.name, True)   880             return NameRef(n.name, is_global=True)   881    882         # Examine other names.   883    884         else:   885    886             # Check local names.   887    888             access_number = self.record_name_access(n.name)   889    890             # Local name.   891    892             if access_number is not None:   893                 return LocalNameRef(n.name, access_number)   894    895             # Possible global or built-in name.   896    897             else:   898                 self.record_name_access(n.name, True)   899                 return NameRef(n.name, is_global=True)   900    901     def record_name_access(self, name, is_global=False):   902    903         """   904         Record an access involving 'name' if the name is being tracked, using   905         'is_global' to indicate whether the name is global.   906         """   907    908         name = self.get_name_for_tracking(name, is_global=is_global)   909         branches = self.trackers[-1].tracking_name(name)   910         if branches:   911             self.record_branches_for_access(branches, name, None)   912             return self.record_access_details(name, None, None, None)   913         return None   914    915     def process_operator_chain(self, nodes, fn):   916    917         """   918         Process the given chain of 'nodes', applying 'fn' to each node or item.   919         Each node starts a new conditional region, effectively making a deeply-   920         nested collection of if-like statements.   921         """   922    923         tracker = self.trackers[-1]   924    925         for item in nodes:   926             tracker.new_branchpoint()   927             tracker.new_branch()   928             fn(item)   929    930         for item in nodes[:-1]:   931             tracker.shelve_branch()   932             tracker.new_branch()   933             tracker.shelve_branch()   934             tracker.merge_branches()   935    936         tracker.shelve_branch()   937         tracker.merge_branches()   938    939     def process_try_node(self, n):   940    941         """   942         Process the given "try...except" node 'n'.   943         """   944    945         self.record_exception_handler()   946    947         tracker = self.trackers[-1]   948         tracker.new_branchpoint()   949    950         self.process_structure_node(n.body)   951    952         for name, var, handler in n.handlers:   953             if name is not None:   954                 self.process_structure_node(name)   955    956             # Any abandoned branches from the body can now be resumed in a new   957             # branch.   958    959             tracker.resume_abandoned_branches()   960    961             # Establish the local for the handler.   962    963             if var is not None:   964                 self.process_assignment_node(var, None)   965             if handler is not None:   966                 self.process_structure_node(handler)   967    968             tracker.shelve_branch()   969    970         # The else clause maintains the usage from the body but without the   971         # abandoned branches since they would never lead to the else clause   972         # being executed.   973    974         if n.else_:   975             tracker.new_branch()   976             self.process_structure_node(n.else_)   977             tracker.shelve_branch()   978    979         # Without an else clause, a null branch propagates the successful   980         # outcome.   981    982         else:   983             tracker.new_branch()   984             tracker.shelve_branch()   985    986         tracker.merge_branches()   987    988     def process_try_finally_node(self, n):   989    990         """   991         Process the given "try...finally" node 'n'.   992         """   993    994         self.record_exception_handler()   995    996         tracker = self.trackers[-1]   997         self.process_structure_node(n.body)   998    999         # Any abandoned branches from the body can now be resumed.  1000   1001         branches = tracker.resume_all_abandoned_branches()  1002         self.process_structure_node(n.final)  1003   1004         # At the end of the finally clause, abandoned branches are discarded.  1005   1006         tracker.restore_active_branches(branches)  1007   1008     def process_while_node(self, n):  1009   1010         "Process the given while node 'n'."  1011   1012         tracker = self.trackers[-1]  1013         tracker.new_branchpoint(loop_node=True)  1014   1015         # Evaluate any test or iterator outside the loop.  1016   1017         self.process_structure_node(n.test)  1018   1019         # Propagate attribute usage to branches.  1020   1021         tracker.new_branch(loop_node=True)  1022   1023         # Enter the loop.  1024   1025         in_conditional = self.in_conditional  1026         self.in_conditional = True  1027         self.process_structure_node(n.body)  1028         self.in_conditional = in_conditional  1029   1030         # Continuing branches are resumed before any test.  1031   1032         tracker.resume_continuing_branches()  1033   1034         # Evaluate any continuation test within the body.  1035   1036         self.process_structure_node(n.test)  1037   1038         tracker.shelve_branch(loop_node=True)  1039   1040         # Support the non-looping condition.  1041   1042         tracker.new_branch()  1043         tracker.shelve_branch()  1044   1045         tracker.merge_branches()  1046   1047         # Evaluate any else clause outside branches.  1048   1049         if n.else_:  1050             self.process_structure_node(n.else_)  1051   1052         # Connect broken branches to the code after any loop.  1053   1054         tracker.resume_broken_branches()  1055   1056     # Branch tracking methods.  1057   1058     def start_tracking(self, names):  1059   1060         """  1061         Start tracking attribute usage for names in the current namespace,  1062         immediately registering the given 'names'.  1063         """  1064   1065         path = self.get_namespace_path()  1066         parent = self.trackers[-1]  1067         tracker = BranchTracker()  1068         self.trackers.append(tracker)  1069   1070         # Record the given names established as new branches.  1071   1072         tracker.assign_names(names)  1073   1074     def assign_name(self, name, name_ref):  1075   1076         "Assign to 'name' the given 'name_ref' in the current namespace."  1077   1078         name = self.get_name_for_tracking(name)  1079         self.trackers[-1].assign_names([name], [name_ref])  1080   1081     def stop_tracking(self):  1082   1083         """  1084         Stop tracking attribute usage, recording computed usage for the current  1085         namespace. Indicate whether a value is always returned from the  1086         namespace.  1087         """  1088   1089         path = self.get_namespace_path()  1090         tracker = self.trackers.pop()  1091         self.record_assignments_for_access(tracker)  1092   1093         self.attr_usage[path] = tracker.get_all_usage()  1094         self.name_initialisers[path] = tracker.get_all_values()  1095   1096         return tracker.returns_value()  1097   1098     def start_tracking_in_module(self):  1099   1100         "Start tracking attribute usage in the module."  1101   1102         tracker = BranchTracker()  1103         self.trackers.append(tracker)  1104   1105     def stop_tracking_in_module(self):  1106   1107         "Stop tracking attribute usage in the module."  1108   1109         tracker = self.trackers[0]  1110         self.record_assignments_for_access(tracker)  1111         self.attr_usage[self.name] = tracker.get_all_usage()  1112         self.name_initialisers[self.name] = tracker.get_all_values()  1113   1114     def record_assignments_for_access(self, tracker):  1115   1116         """  1117         For the current path, use the given 'tracker' to record assignment  1118         version information for attribute accesses.  1119         """  1120   1121         path = self.get_path_for_access()  1122   1123         if not self.attr_accessor_branches.has_key(path):  1124             return  1125   1126         init_item(self.attr_accessors, path, dict)  1127         attr_accessors = self.attr_accessors[path]  1128   1129         # Obtain the branches applying during each access.  1130   1131         for access, all_branches in self.attr_accessor_branches[path].items():  1132             name, attrnames = access  1133             init_item(attr_accessors, access, list)  1134   1135             # Obtain the assignments applying to each branch.  1136   1137             for branches in all_branches:  1138                 positions = tracker.get_assignment_positions_for_branches(name, branches)  1139   1140                 # Detect missing name information.  1141   1142                 if None in positions:  1143                     globals = self.global_attr_accesses.get(path)  1144                     accesses = globals and globals.get(name)  1145                     if not accesses:  1146                         print >>sys.stderr, "In %s, %s may not be defined when used." % (  1147                             self.get_namespace_path(), name)  1148                     positions.remove(None)  1149   1150                 attr_accessors[access].append(positions)  1151   1152     def record_branches_for_access(self, branches, name, attrnames):  1153   1154         """  1155         Record the given 'branches' for an access involving the given 'name' and  1156         'attrnames'.  1157         """  1158   1159         access = name, attrnames  1160         path = self.get_path_for_access()  1161   1162         init_item(self.attr_accessor_branches, path, dict)  1163         attr_accessor_branches = self.attr_accessor_branches[path]  1164   1165         init_item(attr_accessor_branches, access, list)  1166         attr_accessor_branches[access].append(branches)  1167   1168     def record_access_details(self, name, attrnames, assignment, invocation):  1169   1170         """  1171         For the given 'name' and 'attrnames', record an access indicating  1172         whether an 'assignment' or an 'invocation' is occurring.  1173   1174         These details correspond to accesses otherwise recorded by the attribute  1175         accessor and attribute access dictionaries.  1176         """  1177   1178         access = name, attrnames  1179         path = self.get_path_for_access()  1180   1181         init_item(self.attr_access_modifiers, path, dict)  1182         init_item(self.attr_access_modifiers[path], access, list)  1183   1184         access_number = len(self.attr_access_modifiers[path][access])  1185         self.attr_access_modifiers[path][access].append((assignment, invocation))  1186         return access_number  1187   1188     def record_global_access_details(self, name, attrnames):  1189   1190         """  1191         Record details of a global access via the given 'name' involving the  1192         indicated 'attrnames'.  1193         """  1194   1195         path = self.get_namespace_path()  1196   1197         init_item(self.global_attr_accesses, path, dict)  1198         init_item(self.global_attr_accesses[path], name, set)  1199         self.global_attr_accesses[path][name].add(attrnames)  1200   1201     # Namespace modification.  1202   1203     def record_name(self, name):  1204   1205         "Record the use of 'name' in a namespace."  1206   1207         path = self.get_namespace_path()  1208         init_item(self.names_used, path, set)  1209         self.names_used[path].add(name)  1210   1211     def set_module(self, name, module_name):  1212   1213         """  1214         Set a module in the current namespace using the given 'name' associated  1215         with the corresponding 'module_name'.  1216         """  1217   1218         if name:  1219             self.set_general_local(name, Reference("<module>", module_name))  1220   1221     def set_definition(self, name, kind):  1222   1223         """  1224         Set the definition having the given 'name' and 'kind'.  1225   1226         Definitions are set in the static namespace hierarchy, but they can also  1227         be recorded for function locals.  1228         """  1229   1230         if self.is_global(name):  1231             print >>sys.stderr, "In %s, %s is defined as being global." % (  1232                 self.get_namespace_path(), name)  1233   1234         path = self.get_object_path(name)  1235         self.set_object(path, kind)  1236   1237         ref = self.get_object(path)  1238         if ref.get_kind() == "<var>":  1239             print >>sys.stderr, "In %s, %s is defined more than once." % (  1240                 self.get_namespace_path(), name)  1241   1242         if not self.is_global(name) and self.in_function:  1243             self.set_function_local(name, ref)  1244   1245     def set_function_local(self, name, ref=None):  1246   1247         "Set the local with the given 'name' and optional 'ref'."  1248   1249         locals = self.function_locals[self.get_namespace_path()]  1250         multiple = not ref or locals.has_key(name) and locals[name] != ref  1251         locals[name] = multiple and Reference("<var>") or ref  1252   1253     def assign_general_local(self, name, name_ref):  1254   1255         """  1256         Set for 'name' the given 'name_ref', recording the name for attribute  1257         usage tracking.  1258         """  1259   1260         self.set_general_local(name, name_ref)  1261         self.assign_name(name, name_ref)  1262   1263     def set_general_local(self, name, value=None):  1264   1265         """  1266         Set the 'name' with optional 'value' in any kind of local namespace,  1267         where the 'value' should be a reference if specified.  1268         """  1269   1270         init_value = self.get_initialising_value(value)  1271   1272         # Module global names.  1273   1274         if self.is_global(name):  1275             path = self.get_global_path(name)  1276             self.set_object(path, init_value)  1277   1278         # Function local names.  1279   1280         elif self.in_function:  1281             path = self.get_object_path(name)  1282             self.set_function_local(name, init_value)  1283   1284         # Other namespaces (classes).  1285   1286         else:  1287             path = self.get_object_path(name)  1288             self.set_name(name, init_value)  1289   1290     def set_name(self, name, ref=None):  1291   1292         "Attach the 'name' with optional 'ref' to the current namespace."  1293   1294         self.set_object(self.get_object_path(name), ref)  1295   1296     def set_instance_attr(self, name, ref=None):  1297   1298         """  1299         Add an instance attribute of the given 'name' to the current class,  1300         using the optional 'ref'.  1301         """  1302   1303         self._set_instance_attr(self.in_class, name, ref)  1304   1305     def _set_instance_attr(self, path, name, ref=None):  1306   1307         init_item(self.instance_attrs, path, set)  1308         self.instance_attrs[path].add(name)  1309   1310         if ref:  1311             init_item(self.instance_attr_constants, path, dict)  1312             self.instance_attr_constants[path][name] = ref  1313   1314     def get_initialising_value(self, value):  1315   1316         "Return a suitable initialiser reference for 'value'."  1317   1318         # Includes LiteralSequenceRef, ResolvedNameRef...  1319   1320         if isinstance(value, (NameRef, AccessRef, InstanceRef)):  1321             return value.reference()  1322   1323         # In general, invocations do not produce known results. However, the  1324         # name initialisers are resolved once a module has been inspected.  1325   1326         elif isinstance(value, InvocationRef):  1327             return value.reference()  1328   1329         # Variable references are unknown results.  1330   1331         elif isinstance(value, VariableRef):  1332             return value.reference()  1333   1334         else:  1335             return value  1336   1337     # Static, program-relative naming.  1338   1339     def find_name(self, name):  1340   1341         """  1342         Return the qualified name for the given 'name' used in the current  1343         non-function namespace.  1344         """  1345   1346         path = self.get_namespace_path()  1347         ref = None  1348   1349         if not self.in_function and name not in predefined_constants:  1350             if self.in_class:  1351                 ref = self.get_object(self.get_object_path(name), False)  1352             if not ref:  1353                 ref = self.get_global_or_builtin(name)  1354   1355         return ref  1356   1357     def get_class(self, node):  1358   1359         """  1360         Use the given 'node' to obtain the identity of a class. Return a  1361         reference for the class. Unresolved dependencies are permitted and must  1362         be resolved later.  1363         """  1364   1365         ref = self._get_class(node)  1366         return ref.has_kind(["<class>", "<depends>"]) and ref or None  1367   1368     def _get_class(self, node):  1369   1370         """  1371         Use the given 'node' to find a class definition. Return a reference to  1372         the class.  1373         """  1374   1375         if isinstance(node, compiler.ast.Getattr):  1376   1377             # Obtain the identity of the access target.  1378   1379             ref = self._get_class(node.expr)  1380   1381             # Where the target is a class or module, obtain the identity of the  1382             # attribute.  1383   1384             if ref.has_kind(["<function>", "<var>"]):  1385                 return None  1386             else:  1387                 attrname = "%s.%s" % (ref.get_origin(), node.attrname)  1388                 return self.get_object(attrname)  1389   1390         # Names can be module-level or built-in.  1391   1392         elif isinstance(node, compiler.ast.Name):  1393   1394             # Record usage of the name and attempt to identify it.  1395   1396             self.record_name(node.name)  1397             return self.find_name(node.name)  1398         else:  1399             return None  1400   1401     def get_constant(self, name, value):  1402   1403         "Return a constant reference for the given type 'name' and 'value'."  1404   1405         ref = self.get_builtin_class(name)  1406         return self.get_constant_reference(ref, value)  1407   1408     def get_literal_instance(self, n, name=None):  1409   1410         """  1411         For node 'n', return a reference to an instance of 'name', or if 'name'  1412         is not specified, deduce the type from the value.  1413         """  1414   1415         # Handle stray None constants (Sliceobj seems to produce them).  1416   1417         if name == "NoneType":  1418             return self.process_name_node(compiler.ast.Name("None"))  1419   1420         # Obtain the details of the literal itself.  1421         # An alias to the type is generated for sequences.  1422   1423         if name in ("dict", "list", "tuple"):  1424             ref = self.get_builtin_class(name)  1425             self.set_special_literal(name, ref)  1426             return self.process_literal_sequence_node(n, name, ref, LiteralSequenceRef)  1427   1428         # Constant values are independently recorded.  1429   1430         else:  1431             value, typename, encoding = self.get_constant_value(n.value, n.literals)  1432             ref = self.get_builtin_class(typename)  1433             return self.get_constant_reference(ref, value, encoding)  1434   1435     # Special names.  1436   1437     def get_special(self, name):  1438   1439         "Return any stored value for the given special 'name'."  1440   1441         value = self.special.get(name)  1442         if value:  1443             ref, paths = value  1444         else:  1445             ref = None  1446         return ref  1447   1448     def set_special(self, name, value):  1449   1450         """  1451         Set a special 'name' that merely tracks the use of an implicit object  1452         'value'.  1453         """  1454   1455         if not self.special.has_key(name):  1456             paths = set()  1457             self.special[name] = value, paths  1458         else:  1459             _ref, paths = self.special[name]  1460   1461         paths.add(self.get_namespace_path())  1462   1463     def set_special_literal(self, name, ref):  1464   1465         """  1466         Set a special name for the literal type 'name' having type 'ref'. Such  1467         special names provide a way of referring to literal object types.  1468         """  1469   1470         literal_name = "$L%s" % name  1471         value = ResolvedNameRef(literal_name, ref)  1472         self.set_special(literal_name, value)  1473   1474     # Exceptions.  1475   1476     def record_exception_handler(self):  1477   1478         "Record the current namespace as employing an exception handler."  1479   1480         self.exception_namespaces.add(self.get_namespace_path())  1481   1482     # Return values.  1483   1484     def record_return_value(self, expr):  1485   1486         "Record the given return 'expr'."  1487   1488         path = self.get_namespace_path()  1489         init_item(self.return_values, path, set)  1490         self.return_values[path].add(expr)  1491   1492 # vim: tabstop=4 expandtab shiftwidth=4