# HG changeset patch # User Paul Boddie # Date 1341068797 -7200 # Node ID 205ff83aa4f68f374f12df882542225546e5d928 # Parent 6a3dabe25ca2ac85b4b43e848096ce918812c36f Introduced missing support for module code invocation upon first import. diff -r 6a3dabe25ca2 -r 205ff83aa4f6 micropython/__init__.py --- a/micropython/__init__.py Sat Jun 30 00:15:09 2012 +0200 +++ b/micropython/__init__.py Sat Jun 30 17:06:37 2012 +0200 @@ -254,8 +254,9 @@ # Get the raw version for the architecture. if arch_item is not None: + arch_item.finalise_location(with_builtins) self.raw_code += arch_item.as_raw(objtable, paramtable, with_builtins) - arch_item.finalise_location(with_builtins) + arch_item.finalise_body_location(with_builtins) else: self.raw_code.append(item) @@ -266,8 +267,6 @@ if not with_builtins and module.name in ("__builtins__", "native"): continue - module.code_location = module.blocks[0].location - self.code_location = self.importer.modules["__main__"].code_location return self.raw_code @@ -415,6 +414,10 @@ self.modules_ordered = [] self.loading = set() + # Importers responsible for initially importing modules. + + self.importers = {} + # Constant records. self.constant_values = {} @@ -948,12 +951,16 @@ else: return None - def load(self, name, return_leaf=0): + def load(self, name, return_leaf=0, importer=None): """ Load the module or package with the given 'name'. Return an object referencing the loaded module or package, or None if no such module or package exists. + + If the given 'importer' is specified, it will be associated with the + imported module if it is responsible for importing the module for the + first time. """ if return_leaf: @@ -961,7 +968,7 @@ else: name_for_return = name.split(".")[0] - if self.modules.has_key(name) and self.modules[name].loaded: + if self.modules.has_key(name): #print >>sys.stderr, "Cached (%s)" % name return self.modules[name_for_return] @@ -982,7 +989,7 @@ # Either acquire a reference to an already-imported module, or load the # module from a file. - top = module = self.load_from_file(filename, path[0]) + top = module = self.load_from_file(filename, path[0], importer) # For hierarchical names, traverse each path component... @@ -1010,7 +1017,7 @@ # Either reference an imported module or load one from a file. - submodule = self.load_from_file(filename, module_name) + submodule = self.load_from_file(filename, module_name, importer) if d: self.add_submodules(d, module) @@ -1032,10 +1039,14 @@ else: return top - def load_from_file(self, name, module_name=None): + def load_from_file(self, name, module_name=None, importer=None): """ Load the module with the given 'name' (which may be a full module path). + + If the given 'importer' is specified, it will be associated with the + imported module if it is responsible for importing the module for the + first time. """ if module_name is None: @@ -1052,6 +1063,13 @@ self.loading.remove(module) module.loaded = 1 + # Record each module as imported by any importer. + + if importer: + if not self.importers.has_key(importer): + self.importers[importer] = [] + self.importers[importer].append(module) + # Record the module. self.use_object(module.full_name()) diff -r 6a3dabe25ca2 -r 205ff83aa4f6 micropython/ast.py --- a/micropython/ast.py Sat Jun 30 00:15:09 2012 +0200 +++ b/micropython/ast.py Sat Jun 30 17:06:37 2012 +0200 @@ -106,7 +106,12 @@ if self.module.name == "__main__": self.set_block(handler_block) self.new_op(PopHandler(1)) - self.new_op(Return()) + else: + self.new_op(DropFrame()) + + # All modules return if invoked. + + self.new_op(Return()) self.drop_exception_unit() self.unit.temp_usage = self.max_temp_position + 1 @@ -155,7 +160,7 @@ self.new_op(LoadFunction(init_method)) self.new_op(LoadCallable()) - self.new_op(JumpInFrame()) + self.new_op(JumpWithFrame()) # Store the object as the result. @@ -614,7 +619,20 @@ def visitDecorators(self, node): raise TranslationNotImplementedError("Decorators") - def visitFrom(self, node): pass + def visitFrom(self, node): + + """ + Although imported code already resides in any generated image, the + code must be invoked. + """ + + modules = self.importer.importers.get(node) + if modules: + for module in modules: + self.new_op(MakeFrame(0)) + self.new_op(LoadConst(module)) + self.new_op(LoadCallable()) + self.new_op(JumpWithFrame()) def visitFunction(self, node): if not used_by_unit(node): @@ -641,7 +659,7 @@ def visitGlobal(self, node): pass - def visitImport(self, node): pass + visitImport = visitFrom def visitKeyword(self, node): pass diff -r 6a3dabe25ca2 -r 205ff83aa4f6 micropython/inspect.py --- a/micropython/inspect.py Sat Jun 30 00:15:09 2012 +0200 +++ b/micropython/inspect.py Sat Jun 30 17:06:37 2012 +0200 @@ -991,7 +991,7 @@ self.resume_broken_branches() def visitFrom(self, node): - module = self.importer.load(node.modname, 1) + module = self.importer.load(node.modname, 1, importer=node) if module and not module.loaded: print >>sys.stderr, "Warning: a circular import of %s is being attempted in %s" % (node.modname, self.full_name()) @@ -1005,7 +1005,7 @@ # Missing names may refer to submodules. if not module.has_key(name): - submodule = self.importer.load(node.modname + "." + name, 1) + submodule = self.importer.load(node.modname + "." + name, 1, importer=node) if submodule: if not submodule.loaded: print >>sys.stderr, "Warning: a circular import of %s.%s is being attempted in %s" % ( @@ -1020,7 +1020,7 @@ self.store(alias or name, attr) self.use_specific_attribute(module.full_name(), name) if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: - self.importer.load(attr.get_value().name) + self.importer.load(attr.get_value().name, importer=node) continue # Support the import of names from missing modules. @@ -1034,7 +1034,7 @@ self.store(n, attr) self.use_specific_attribute(module.full_name(), n) if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: - self.importer.load(attr.get_value().name) + self.importer.load(attr.get_value().name, importer=node) def visitFunction(self, node): return self._visitFunction(node, node.name) @@ -1106,10 +1106,10 @@ def visitImport(self, node): for name, alias in node.names: if alias is not None: - module = self.importer.load(name, 1) or UnresolvedName(None, name, self) + module = self.importer.load(name, 1, importer=node) or UnresolvedName(None, name, self) self.store(alias, module) else: - module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self) + module = self.importer.load(name, importer=node) or UnresolvedName(None, name.split(".")[0], self) self.store(name.split(".")[0], module) visitInvert = _visitUnary diff -r 6a3dabe25ca2 -r 205ff83aa4f6 micropython/raw.py --- a/micropython/raw.py Sat Jun 30 00:15:09 2012 +0200 +++ b/micropython/raw.py Sat Jun 30 17:06:37 2012 +0200 @@ -3,7 +3,7 @@ """ Classes used to help with the generation of raw image data. -Copyright (C) 2009, 2010, 2011 Paul Boddie +Copyright (C) 2009, 2010, 2011, 2012 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,6 +33,9 @@ def finalise_location(self, with_builtins): pass + def finalise_body_location(self, with_builtins): + pass + def is_generated(self, with_builtins): return with_builtins or self.item.module.name not in ("__builtins__", "native") or self.item.astnode.doc is not None diff -r 6a3dabe25ca2 -r 205ff83aa4f6 micropython/rsvp.py --- a/micropython/rsvp.py Sat Jun 30 00:15:09 2012 +0200 +++ b/micropython/rsvp.py Sat Jun 30 17:06:37 2012 +0200 @@ -3,7 +3,7 @@ """ RSVP instruction and serialisation classes. -Copyright (C) 2007, 2008, 2009, 2010, 2011 Paul Boddie +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -87,7 +87,7 @@ return RSVPObject.set_location(self, location + 1, objtable, with_builtins) - def finalise_location(self, with_builtins): + def finalise_body_location(self, with_builtins): self._finalise_location(with_builtins) def as_raw(self, objtable, paramtable, with_builtins): @@ -235,7 +235,7 @@ return location - def finalise_location(self, with_builtins): + def finalise_body_location(self, with_builtins): self._finalise_location(with_builtins) def as_raw(self, objtable, paramtable, with_builtins): @@ -256,13 +256,18 @@ "A wrapper for modules." + def finalise_location(self, with_builtins): + item = self.item + if item.blocks: + item.code_location = item.blocks[0].location + def as_raw(self, objtable, paramtable, with_builtins): item = self.item return [ DataObject( objtable.as_list().get_code(item.full_name()), None, # modules treated like classes - None, + item.code_location, item.full_name(), len(item.module_attributes()) + 1 # size ) @@ -409,7 +414,7 @@ class TargetInstruction(Instruction): - "An instruction loading the address of an invocation target." + "An instruction loading the address of a direct invocation target." def format_operand(self): return Instruction.format_operand(self) + ["name=%r" % name(self.attr)] diff -r 6a3dabe25ca2 -r 205ff83aa4f6 tests/class_init_code.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/class_init_code.py Sat Jun 30 17:06:37 2012 +0200 @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +class C: + x = 1 + 2 + +result_3 = C.x + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 6a3dabe25ca2 -r 205ff83aa4f6 tests/initialised/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/initialised/__init__.py Sat Jun 30 17:06:37 2012 +0200 @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +x = 100 + 20 + 3 + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 6a3dabe25ca2 -r 205ff83aa4f6 tests/module_init.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/module_init.py Sat Jun 30 17:06:37 2012 +0200 @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +import initialised + +result_123 = initialised.x + +# vim: tabstop=4 expandtab shiftwidth=4