micropython

micropython/__init__.py

442:13aae946513b
2011-07-05 Paul Boddie Introduced Instance() in place of None as a result and for the value of the active expression where no definitive object can be deduced. Made all Instance values compare equal to each other in order to avoid duplication in sets. Improved Constant comparisons. Fixed assignment counting where many values are provided in a single assignment. Added inspection support for conditional expressions (since they are used in the standard library).
     1 #!/usr/bin/env python     2      3 """     4 The micropython package for processing Python source code. The code originates     5 from the simplify package but has had various details related to that package     6 removed.     7      8 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Paul Boddie <paul@boddie.org.uk>     9     10 This program is free software; you can redistribute it and/or modify it under    11 the terms of the GNU General Public License as published by the Free Software    12 Foundation; either version 3 of the License, or (at your option) any later    13 version.    14     15 This program is distributed in the hope that it will be useful, but WITHOUT    16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    17 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    18 details.    19     20 You should have received a copy of the GNU General Public License along with    21 this program.  If not, see <http://www.gnu.org/licenses/>.    22     23 --------    24     25 To use this module, an importer should be constructed. Here, the standard path    26 for module searching is employed:    27     28 importer = Importer(sys.path)    29     30 To generate programs, the above importer should be supplied in the    31 initialisation of a program instance, and then various methods are called:    32     33 program = Program(importer)    34 image = program.get_raw_image()    35     36 Such importer and program objects are the most convenient mechanism through    37 which the functionality of the micropython package may be accessed.    38 """    39     40 from micropython.common import *    41 import micropython.ast    42 import micropython.data    43 import micropython.opt    44 import micropython.inspect    45 import micropython.table    46 import os    47     48 try:    49     set    50 except NameError:    51     from sets import Set as set    52     53 class Program:    54     55     "This class supports the generation of a program image."    56     57     supported_optimisations = micropython.opt.Optimiser.supported_optimisations    58     59     def __init__(self, importer, optimisations=None):    60     61         """    62         Initialise the program representation with an 'importer' which is able    63         to locate and load Python modules.    64     65         The optional 'optimisations' cause certain techniques to be used in    66         reducing program size and improving program efficiency.    67         """    68     69         self.importer = importer    70         self.optimisations = optimisations or set()    71     72         # Remember the tables once generated.    73     74         self.objtable = None    75         self.paramtable = None    76     77         # Main program information.    78     79         self.code = None    80         self.code_location = None    81     82     def get_importer(self):    83         return self.importer    84     85     # Access to finalised program information.    86     87     def finalise(self):    88     89         "Finalise the program."    90     91         # Need the tables to finalise.    92     93         objtable = self.get_object_table()    94         self.get_parameter_table()    95     96         self.importer.vacuum(objtable)    97     98         # Now remove unneeded things from the tables.    99    100         objtable = self.get_object_table(reset=1)   101         self.get_parameter_table(reset=1)   102    103         self.importer.finalise(objtable)   104    105     def get_image(self, with_builtins=0):   106    107         """   108         Return the program image including built-in objects if 'with_builtins'   109         is specified and set to a true value.   110         """   111    112         if self.code is not None:   113             return self.code   114    115         # Optimise and regenerate the object table.   116    117         self.finalise()   118         self.code = []   119    120         # Append constants to the image.   121    122         for const in self.importer.constants():   123             self.code.append(const)   124    125         last_module = self.importer.modules_ordered[-1]   126    127         for module in self.importer.modules_ordered:   128             suppress_builtins = not with_builtins and module.name in ("__builtins__", "native")   129    130             # Position the module in the image and make a translation.   131    132             trans = micropython.ast.Translation(module, self)   133    134             # Add header details.   135    136             self.code.append(module)   137    138             # Append module attributes to the image.   139    140             attributes = module.module_attributes()   141             self.code += module.attributes_as_list()   142    143             # Append classes and functions to the image.   144    145             for obj in module.all_objects:   146                 if isinstance(obj, micropython.data.Class):   147    148                     # Add header details.   149    150                     self.code.append(obj)   151    152                     # Append class attributes to the image.   153    154                     attributes = obj.class_attributes()   155                     self.code += obj.attributes_as_list()   156    157                     # Omit built-in function code where requested.   158    159                     if suppress_builtins and obj.astnode.doc is None:   160                         continue   161    162                     # Generate the instantiator/initialiser.   163                     # Append the function code to the image.   164    165                     code = trans.get_instantiator_code(obj)   166                     self.code += code   167    168                     # Class-level code is generated separately at the module   169                     # level, and the code location is set within the code   170                     # generation process for the module.   171    172                 elif isinstance(obj, micropython.data.Function):   173    174                     # Add header details.   175    176                     self.code.append(obj)   177    178                     # Append any default values to the image.   179                     # Only do this for functions which are not dynamic.   180    181                     if not obj.is_dynamic():   182                         self.code += obj.default_attrs   183    184                     # Omit built-in function code where requested.   185    186                     if suppress_builtins and obj.astnode.doc is None:   187                         pass   188    189                     # Append the function code to the image.   190    191                     else:   192                         code = trans.get_code(obj)   193                         self.code += code   194    195             # Omit built-in module code where requested.   196    197             if suppress_builtins:   198                 pass   199    200             # Append the module top-level code to the image.   201    202             else:   203                 code = trans.get_module_code()   204                 self.code += code   205    206         return self.code   207    208     def get_raw_image(self, architecture=None, with_builtins=0):   209    210         "Return the raw image representation of the program."   211    212         architecture = architecture or micropython.rsvp   213    214         self.get_image(with_builtins)   215    216         objtable = self.get_object_table()   217         paramtable = self.get_parameter_table()   218    219         # Position the objects.   220    221         pos = 0   222    223         for item in self.code:   224             arch_item = architecture.get_object(item)   225    226             # Get the raw version for the architecture.   227    228             if arch_item is not None:   229                 pos = arch_item.set_location(pos, objtable, with_builtins)   230             else:   231                 pos += 1   232    233         # Generate the raw code.   234    235         self.raw_code = []   236    237         for item in self.code:   238             arch_item = architecture.get_object(item)   239    240             # Get the raw version for the architecture.   241    242             if arch_item is not None:   243                 self.raw_code += arch_item.as_raw(objtable, paramtable, with_builtins)   244                 arch_item.finalise_location(with_builtins)   245             else:   246                 self.raw_code.append(item)   247    248         # Fix the module locations.   249    250         for module in self.importer.modules_ordered:   251    252             if not with_builtins and module.name in ("__builtins__", "native"):   253                 continue   254    255             module.code_location = module.blocks[0].location   256    257         self.code_location = self.importer.modules["__main__"].code_location   258         return self.raw_code   259    260     def get_object_table(self, reset=0):   261    262         "Return a table with details of attributes for classes and modules."   263    264         if self.objtable is None or reset:   265    266             t = self.objtable = micropython.table.ObjectTable()   267             for module in self.importer.get_modules():   268    269                 # Add module attributes and module identity information.   270    271                 full_name = module.full_name()   272                 attributes = {full_name : module}   273                 attributes.update(module.module_attributes())   274                 t.add(full_name, attributes)   275    276                 # Add class and instance attributes for all classes, together   277                 # with descendant information.   278    279                 for obj in module.all_objects:   280                     if isinstance(obj, micropython.data.Class):   281    282                         # Prevent ambiguous classes.   283    284                         full_name = obj.full_name()   285    286                         #name = obj.name   287                         #if module.has_key(name) and module[name].defines_ambiguous_class():   288                         #    raise TableGenerationError, "Class %r in module %r is ambiguously defined." % (name, module.full_name())   289    290                         # Define a table entry for the class.   291    292                         attributes = {full_name : obj}   293                         attributes.update(obj.all_attributes())   294                         attributes.update(obj.all_descendants())   295                         t.add(full_name, attributes)   296    297         return self.objtable   298    299     def get_parameter_table(self, reset=0):   300    301         "Return a table with details of parameters for functions and methods."   302    303         # Need the object table to get at class details.   304    305         if self.paramtable is None or reset:   306             t = self.paramtable = micropython.table.ParameterTable()   307    308             # Visit each module, getting function and method details.   309    310             for module in self.importer.get_modules():   311                 for obj in module.all_objects:   312                     if isinstance(obj, micropython.data.Function):   313                         t.add(obj.full_name(), obj.parameters())   314    315                     # Classes are callable, too.   316                     # Take details of the appropriate __init__ method to make an   317                     # entry for an instantiation function for the class.   318    319                     elif isinstance(obj, micropython.data.Class):   320                         t.add(obj.get_instantiator().full_name(), obj.get_instantiator().parameters())   321    322             # Filter out all parameter table entries not referenced by keyword   323             # arguments.   324    325             keyword_names = set()   326    327             for module in self.importer.get_modules():   328                 keyword_names.update(module.keyword_names)   329    330             for function_name, parameters in t.table.items():   331                 for name in parameters.keys():   332                     if name in keyword_names:   333                         break   334                 else:   335                     del t.table[function_name]   336    337         return self.paramtable   338    339 class Importer:   340    341     "An import machine, searching for and loading modules."   342    343     predefined_constants = {   344         "None" : None,   345         "True" : True,   346         "False" : False,   347         #"Ellipsis" : Ellipsis,   348         "NotImplemented" : NotImplemented   349         }   350    351     names_always_used = [   352         "bool", "__call__", "__bool__"   353         ]   354    355     def __init__(self, path=None, verbose=0, optimisations=None):   356    357         """   358         Initialise the importer with the given search 'path' - a list of   359         directories to search for Python modules.   360    361         The optional 'verbose' parameter causes output concerning the activities   362         of the object to be produced if set to a true value (not the default).   363    364         The optional 'optimisations' cause certain techniques to be used in   365         reducing program size and improving program efficiency.   366         """   367    368         self.path = path or [os.getcwd()]   369         self.verbose = verbose   370         self.optimisations = optimisations or set()   371    372         self.modules = {}   373         self.modules_ordered = []   374         self.loading = set()   375    376         # Constant records.   377    378         self.constant_values = {}   379         self.constants_used = set()   380         self.constant_references = {}   381         self.init_predefined_constants()   382    383         # Attribute usage.   384    385         self.attributes_used = set()   386         self.name_references = {}   387         self.specific_name_references = {}   388    389         # Attribute coverage calculated during collection.   390    391         self.inferred_name_references = {}   392    393         # Attribute coverage status during collection.   394    395         self.attribute_users_visited = set()   396         self.attributes_to_visit = {}   397    398         # Status information.   399    400         self.vacuumed = 0   401         self.finalised = 0   402    403     def get_modules(self):   404    405         "Return all modules known to the importer."   406    407         return self.modules.values()   408    409     def get_module(self, name):   410    411         "Return the module with the given 'name'."   412    413         return self.modules[name]   414    415     # General maintenance.   416    417     def vacuum(self, objtable):   418    419         "Tidy up the modules."   420    421         if self.vacuumed:   422             return   423    424         # Complete the list of attribute names used in the program.   425    426         self.collect_attributes(objtable)   427    428         for name, module in self.modules.items():   429             if module.loaded:   430                 module.vacuum()   431             else:   432                 del self.modules[name]   433    434         self.vacuumed = 1   435    436     def finalise(self, objtable):   437    438         "Finalise the program (which should have been vacuumed first)."   439    440         if self.finalised:   441             return   442    443         # Reset any previously compiled information.   444    445         for module in self.get_modules():   446             module.unfinalise()   447    448         # Prepare module information again.   449    450         for module in self.get_modules():   451             module.finalise(objtable)   452    453         self.finalised = 1   454    455     # Name accounting.   456    457     def use_name(self, name, from_name, value=None):   458    459         """   460         Register the given 'name' as being used in the program from within an   461         object with the specified 'from_name'. If the optional 'value' is given,   462         note an assignment.   463         """   464    465         if not self.name_references.has_key(from_name):   466             self.name_references[from_name] = set()   467    468         attrnames = ObjectSet([name])   469         usage = (attrnames,)   470         self.name_references[from_name].add((None, None, usage))   471    472     def use_names(self, user, name, usage, from_name):   473    474         """   475         For the given attribute 'user' (which may be None if no specific user is   476         given), register for the given 'name' the given attribute 'usage'   477         (combinations of attribute names), noting the scope of this usage as   478         being the program object with the specified 'from_name'.   479         """   480    481         if not self.name_references.has_key(from_name):   482             self.name_references[from_name] = set()   483    484         self.name_references[from_name].add((user, name, usage))   485    486     def use_specific_name(self, objname, attrname, from_name):   487    488         """   489         Register the given 'objname' (for an object) whose 'attrname' is being   490         used in the program from within an object with the specified   491         'from_name'.   492         """   493    494         if not self.specific_name_references.has_key(from_name):   495             self.specific_name_references[from_name] = set()   496         self.specific_name_references[from_name].add((objname, attrname))   497    498     # Name accounting products.   499    500     def uses_attribute(self, objname, name):   501    502         """   503         Return whether the attribute of the object with the given 'objname'   504         having the given 'name' is used as an attribute in the program.   505         """   506    507         return (objname + "." + name) in self.attributes_used   508    509     def use_attribute(self, objname, name):   510    511         """   512         Indicate that in the object with the given 'objname', the attribute of   513         the given 'name' is used.   514         """   515    516         self.attributes_used.add(objname + "." + name)   517    518     def use_object(self, objname):   519    520         "Indicate that the object with the given 'objname' is used."   521    522         self.attributes_used.add(objname)   523    524     def collect_attributes(self, objtable):   525    526         "Collect attribute references for the entire program."   527    528         # Include names which may not be explicitly used in programs.   529         # NOTE: Potentially declare these when inspecting.   530    531         for attrname in self.names_always_used:   532             for objname in objtable.all_possible_objects([attrname]):   533    534                 # Record attributes of objects for potential visiting.   535    536                 self.add_attribute_to_visit(objname, attrname)   537    538         # Visit all modules, since some may employ initialisation code which has   539         # some kind of side-effect.   540    541         for name in self.modules.keys():   542             self._collect_attributes(name, objtable)   543    544     def add_attribute_to_visit(self, objname, attrname):   545    546         """   547         Queue an attribute of the object with the given 'objname', having the   548         given 'attrname', to the list for potential visiting if the specified   549         object is actually referenced.   550         """   551    552         if not self.attributes_to_visit.has_key(objname):   553             self.attributes_to_visit[objname] = set()   554         self.attributes_to_visit[objname].add(attrname)   555    556     def _collect_attributes_from(self, from_name, objname, attrname, objtable):   557    558         """   559         Record the association between 'from_name' and the attribute of   560         'objname' with the given 'attrname'. Then collect attributes for the   561         referenced attribute using 'objtable'.   562         """   563    564         if not self.inferred_name_references.has_key(from_name):   565             self.inferred_name_references[from_name] = set()   566    567         self.inferred_name_references[from_name].add((objname, attrname))   568         self._collect_attributes(objname + "." + attrname, objtable)   569    570     def _collect_attributes(self, from_name, objtable):   571    572         """   573         Given an object called 'from_name', find all names referenced from such   574         an object according to the register of names, using 'objtable' to infer   575         types.   576         """   577    578         if from_name in self.attribute_users_visited:   579             return   580    581         self.attribute_users_visited.add(from_name)   582    583         # Get constant references.   584    585         for const in self.constant_references.get(from_name, []):   586             self.constants_used.add(const)   587    588         # The getattr function is a special case: it can potentially reference   589         # any known attribute. Since accessor attributes must be known   590         # constants, the intersection of known constants and attributes is used   591         # to build a set of objects that might be referenced by getattr.   592    593         if from_name == "__builtins__.getattr":   594             all_attributes = set(objtable.attribute_names())   595             all_string_constants = set([const.get_value() for const in self.constants() if const.value_type_name() == "__builtins__.str"])   596             all_attribute_constants = all_attributes.intersection(all_string_constants)   597    598             # Get the types supporting each attribute and visit the referenced   599             # objects.   600    601             all_objtypes = set()   602    603             for attrname in all_attribute_constants:   604                 objtypes = objtable.any_possible_objects_plus_status([attrname])   605                 all_objtypes.update(objtypes)   606    607             # Attribute assignment does not take place, so an empty list of   608             # values is given.   609    610             self._collect_attributes_for_types(from_name, objtable, all_objtypes,   611                 [{attrname : []} for attrname in all_attribute_constants])   612    613         # Get name references and find possible objects which support such   614         # combinations of attribute names.   615    616         for user, name, usage in self.name_references.get(from_name, []):   617    618             # Using all attribute names for a particular name, attempt to get   619             # specific object types.   620    621             all_objtypes = get_object_types_for_usage(usage, objtable, name, from_name)   622    623             # Investigate the object types.   624    625             self._collect_attributes_for_types(from_name, objtable, all_objtypes, usage)   626    627         # Get specific name references and visit the referenced objects.   628    629         for objname, attrname in self.specific_name_references.get(from_name, []):   630             self.use_attribute(objname, attrname)   631             self._collect_attributes_from(from_name, objname, attrname, objtable)   632    633         # Where the object has an __init__ attribute, assume that it is an   634         # initialiser which is called at some point, and collect attributes used   635         # in this initialiser.   636    637         if "__init__" in objtable.table.get(from_name, []):   638             self.use_attribute(from_name, "__init__")   639             self._collect_attributes_from(from_name, from_name, "__init__", objtable)   640    641         # Visit attributes on this object that were queued in case of the object   642         # being referenced.   643    644         attributes_to_visit = self.attributes_to_visit.get(from_name, [])   645    646         if attributes_to_visit:   647             del self.attributes_to_visit[from_name]   648    649             for attrname in attributes_to_visit:   650                 self.use_attribute(from_name, attrname)   651                 self._collect_attributes_from(from_name, from_name, attrname, objtable)   652    653     def _collect_attributes_for_types(self, from_name, objtable, objtypes, usage):   654    655         """   656         For the unit known as 'from_name' and using the 'objtable' to validate   657         each attribute, identify and attempt to visit attributes found for each   658         of the suggested object types given by 'objtypes' and the 'usage'   659         provided.   660         """   661    662         for objname, is_static in objtypes:   663             for attrnames in usage:   664                 for attrname, attrvalues in attrnames.items():   665    666                     # Test for the presence of an attribute on the suggested   667                     # object type.   668    669                     try:   670                         attr = objtable.access(objname, attrname)   671                     except TableError:   672                         #print "Warning: object type %r does not support attribute %r" % (objname, attrname)   673                         continue   674    675                     # Get the real identity of the attribute in order to   676                     # properly collect usage from it.   677    678                     parent = attr.parent   679                     if parent is None:   680                         continue   681                     elif isinstance(parent, micropython.data.Instance):   682                         parentname = objname   683                     else:   684                         parentname = parent.full_name()   685    686                     # Test for assignment.   687    688                     if attrvalues:   689    690                         # Instance-related accesses may involve any type   691                         # supporting the attribute.   692                         # NOTE: Here, an instance actually represents any kind   693                         # NOTE: of object.   694    695                         if isinstance(parent, micropython.data.Instance):   696                             for attrvalue in attrvalues:   697                                 for name in objtable.any_possible_objects([attrname]):   698                                     parent = objtable.access(name, name)   699                                     if not parent.instance_attributes().has_key(attrname):   700                                         parent.set(attrname, attrvalue, 0)   701                         else:   702                             for attrvalue in attrvalues:   703                                 parent.set(attrname, attrvalue, 0)   704    705                     # Visit attributes of objects known to be used.   706    707                     if parentname in self.attributes_used:   708                         self.use_attribute(parentname, attrname)   709                         self._collect_attributes_from(from_name, parentname, attrname, objtable)   710    711                     # Record attributes of other objects for potential visiting.   712    713                     else:   714                         self.add_attribute_to_visit(parentname, attrname)   715    716     # Constant accounting.   717    718     def use_constant(self, const, from_name):   719    720         """   721         Register the given 'const' as being used in the program from within an   722         object with the specified 'from_name'.   723         """   724    725         if not self.constant_references.has_key(from_name):   726             self.constant_references[from_name] = set()   727    728         self.constant_references[from_name].add(const)   729    730     def init_predefined_constants(self):   731    732         "Ensure the predefined constants."   733    734         for name, value in self.predefined_constants.items():   735             self.constants_used.add(self.make_constant(value))   736    737     def get_predefined_constant(self, name):   738    739         "Return the predefined constant for the given 'name'."   740    741         return self.make_constant(self.predefined_constants[name])   742    743     def get_constant(self, value):   744    745         "Return a constant for the given 'value'."   746    747         const = micropython.data.Const(value)   748         return self.constant_values[const]   749    750     def get_constant_type_name(self, value):   751    752         "Return the type name for the given constant 'value'."   753    754         return value.__class__.__name__   755    756     def make_constant(self, value):   757    758         "Make and return a constant for the given 'value'."   759    760         # Make a constant object and return it.   761    762         const = micropython.data.Const(value)   763         if not self.constant_values.has_key(const):   764             self.constant_values[const] = const   765         return self.constant_values[const]   766    767     def constants(self):   768    769         "Return a list of constants."   770    771         return self.constants_used   772    773     # Import methods.   774    775     def find_in_path(self, name):   776    777         """   778         Find the given module 'name' in the search path, returning None where no   779         such module could be found, or a 2-tuple from the 'find' method   780         otherwise.   781         """   782    783         for d in self.path:   784             m = self.find(d, name)   785             if m: return m   786         return None   787    788     def find(self, d, name):   789    790         """   791         In the directory 'd', find the given module 'name', where 'name' can   792         either refer to a single file module or to a package. Return None if the   793         'name' cannot be associated with either a file or a package directory,   794         or a 2-tuple from '_find_package' or '_find_module' otherwise.   795         """   796    797         m = self._find_package(d, name)   798         if m: return m   799         m = self._find_module(d, name)   800         if m: return m   801         return None   802    803     def _find_module(self, d, name):   804    805         """   806         In the directory 'd', find the given module 'name', returning None where   807         no suitable file exists in the directory, or a 2-tuple consisting of   808         None (indicating that no package directory is involved) and a filename   809         indicating the location of the module.   810         """   811    812         name_py = name + os.extsep + "py"   813         filename = self._find_file(d, name_py)   814         if filename:   815             return None, filename   816         return None   817    818     def _find_package(self, d, name):   819    820         """   821         In the directory 'd', find the given package 'name', returning None   822         where no suitable package directory exists, or a 2-tuple consisting of   823         a directory (indicating the location of the package directory itself)   824         and a filename indicating the location of the __init__.py module which   825         declares the package's top-level contents.   826         """   827    828         filename = self._find_file(d, name)   829         if filename:   830             init_py = "__init__" + os.path.extsep + "py"   831             init_py_filename = self._find_file(filename, init_py)   832             if init_py_filename:   833                 return filename, init_py_filename   834         return None   835    836     def _find_file(self, d, filename):   837    838         """   839         Return the filename obtained when searching the directory 'd' for the   840         given 'filename', or None if no actual file exists for the filename.   841         """   842    843         filename = os.path.join(d, filename)   844         if os.path.exists(filename):   845             return filename   846         else:   847             return None   848    849     def load(self, name, return_leaf=0):   850    851         """   852         Load the module or package with the given 'name'. Return an object   853         referencing the loaded module or package, or None if no such module or   854         package exists.   855         """   856    857         if return_leaf:   858             name_for_return = name   859         else:   860             name_for_return = name.split(".")[0]   861    862         if self.modules.has_key(name) and self.modules[name].loaded:   863             #print "Cached (%s)" % name   864             return self.modules[name_for_return]   865    866         if self.verbose:   867             print "Loading", name   868    869         # Split the name into path components, and try to find the uppermost in   870         # the search path.   871    872         path = name.split(".")   873         m = self.find_in_path(path[0])   874         if not m:   875             if self.verbose:   876                 print "Not found (%s)" % path[0]   877             return None # NOTE: Import error.   878         d, filename = m   879    880         # Either acquire a reference to an already-imported module, or load the   881         # module from a file.   882    883         top = module = self.load_from_file(filename, path[0])   884    885         # For hierarchical names, traverse each path component...   886    887         if len(path) > 1:   888             if not d:   889                 if self.verbose:   890                     print "No package (%s)" % filename   891                 return None # NOTE: Import error (package not found).   892             else:   893                 self.add_submodules(d, module)   894    895             path_so_far = path[:1]   896             for p in path[1:]:   897                 path_so_far.append(p)   898    899                 # Find the package or module concerned.   900    901                 m = self.find(d, p)   902                 if not m:   903                     if self.verbose:   904                         print "Not found (%s)" % p   905                     return None # NOTE: Import error.   906                 d, filename = m   907                 module_name = ".".join(path_so_far)   908    909                 # Either reference an imported module or load one from a file.   910    911                 submodule = self.load_from_file(filename, module_name)   912    913                 if d:   914                     self.add_submodules(d, module)   915    916                 # Store the submodule within its parent module.   917    918                 module.set_module(p, submodule)   919                 module = submodule   920    921         # Return either the deepest or the uppermost module.   922    923         if return_leaf:   924             return module   925         else:   926             return top   927    928     def load_from_file(self, name, module_name=None):   929    930         """   931         Load the module with the given 'name' (which may be a full module path).   932         """   933    934         if module_name is None:   935             module_name = "__main__"   936    937         module = self.add_module(module_name)   938         if not module.loaded and module not in self.loading:   939             self.loading.add(module)   940             #print "Parsing", name   941             module.parse(name)   942             #print "Done", name   943             self.loading.remove(module)   944             module.loaded = 1   945    946         # Record the module.   947    948         self.use_object(module.full_name())   949         #print "Loaded", module_name, "with namespace", module.namespace.keys()   950         return module   951    952     def add_module(self, module_name):   953    954         """   955         Return the module with the given 'module_name', adding a new module   956         object if one does not already exist.   957         """   958    959         if not self.modules.has_key(module_name):   960             self.modules[module_name] = module = micropython.inspect.InspectedModule(module_name, self)   961             self.modules_ordered.append(module)   962         else:   963             module = self.modules[module_name]   964         return module   965    966     def add_submodules(self, pathname, module):   967    968         """   969         Work around insufficient __all__ declarations and examine the directory   970         with the given 'pathname', adding submodules to the given 'module'.   971         """   972    973         for filename in os.listdir(pathname):   974             submodule, ext = os.path.splitext(filename)   975             if ext not in ("", ".py"):   976                 continue   977             module.set_module(submodule, self.add_module(module.name + "." + submodule))   978    979 # vim: tabstop=4 expandtab shiftwidth=4