# HG changeset patch # User Paul Boddie # Date 1226349538 -3600 # Node ID 13861cd5d24547327bea64ba2e2add95c0202a20 # Parent 06a8cc27a08a626a60fade7629d656fa38112a29 Added status flags to the Importer, ensuring that certain operations (vacuum and finalise) are performed before other operations. Removed an explicit vacuum call from the test program. Modified the code generation condition for functions, depending on whether they have been referenced in a program. Removed attribute finalisation in Class when class attributes are requested since such details may be requested before finalisation. Changed the InspectedModule vacuum method, removing the redundant deletion of module names, instead relying on the master list of attribute/global names used in a program. Added class namespace vacuuming using the master names list and referencing information. Added a finalise method to the InspectedModule class. diff -r 06a8cc27a08a -r 13861cd5d245 micropython/__init__.py --- a/micropython/__init__.py Sat Nov 08 23:11:45 2008 +0100 +++ b/micropython/__init__.py Mon Nov 10 21:38:58 2008 +0100 @@ -95,14 +95,20 @@ self.init_predefined_constants() # Name records (used to track actual use of names). + # Include names which may not be explicitly used in programs. - self.names_used = set() + self.names_used = set(["__init__"]) # Main program information. self.code = None self.code_location = None + # Status information. + + self.vacuumed = 0 + self.finalised = 0 + # Name accounting. def use_name(self, name): @@ -156,25 +162,30 @@ "Tidy up the modules." + if self.vacuumed: + return + for name, module in self.modules.items(): if module.loaded: module.vacuum() else: del self.modules[name] + self.vacuumed = 1 + def finalise(self): "Finalise the program." - for module in self.get_modules(): + if self.finalised: + return - # Fix the attributes. + self.vacuum() - module.finalise_attributes() + for module in self.get_modules(): + module.finalise() - for obj in module.all_objects: - if isinstance(obj, (micropython.inspect.Class, micropython.inspect.Function)): - obj.finalise_attributes() + self.finalised = 1 # Access to finalised program information. @@ -307,6 +318,8 @@ "Return a table with details of attributes for classes and modules." if self.objtable is None: + self.vacuum() + t = self.objtable = micropython.table.ObjectTable() for module in self.get_modules(): t.add(module.full_name(), module.module_attributes()) diff -r 06a8cc27a08a -r 13861cd5d245 micropython/ast.py --- a/micropython/ast.py Sat Nov 08 23:11:45 2008 +0100 +++ b/micropython/ast.py Mon Nov 10 21:38:58 2008 +0100 @@ -1668,7 +1668,7 @@ def visitFrom(self, node): pass def visitFunction(self, node): - if not node.unit.referenced and not node.unit.is_method(): + if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)): return # Only store the name when visiting this node from outside. diff -r 06a8cc27a08a -r 13861cd5d245 micropython/data.py --- a/micropython/data.py Sat Nov 08 23:11:45 2008 +0100 +++ b/micropython/data.py Mon Nov 10 21:38:58 2008 +0100 @@ -490,7 +490,6 @@ "Return class attributes provided by this class only." - self.finalise_class_attributes() return dict(self) def all_class_attribute_names(self): diff -r 06a8cc27a08a -r 13861cd5d245 micropython/inspect.py --- a/micropython/inspect.py Sat Nov 08 23:11:45 2008 +0100 +++ b/micropython/inspect.py Mon Nov 10 21:38:58 2008 +0100 @@ -137,24 +137,27 @@ def vacuum(self): - "Vacuum the module namespace, removing unloaded module references." + """ + Vacuum the module namespace, removing unreferenced objects and unused + names. + """ for name, value in self.items(): - if isinstance(value, Attr): - attr_value = value.value + if self.should_optimise_unused_objects(): - # Remove non-loaded modules. + # Remove unused names. - if isinstance(attr_value, Module) and not attr_value.loaded: + if name not in self.importer.names_used: del self[name] - # Remove unreferenced names. + # Remove entries for unreferenced objects. # This, due to the nature of the referenced attribute, assumes # that only explicitly mentioned classes and functions are # employed in the final program. - elif self.should_optimise_unused_objects(): + elif isinstance(value, Attr): + attr_value = value.value # Only remove entries for classes and functions, not methods. @@ -169,7 +172,7 @@ # Complain about globals not initialised at the module level. - elif isinstance(value, Global): + if isinstance(value, Global): print "Warning: global %r in module %r not initialised at the module level." % (name, self.name) # Remove unreferenced objects. @@ -179,10 +182,38 @@ all_objects = list(self.all_objects) for obj in all_objects: + + # Only remove entries for classes and functions, not methods. + if (isinstance(obj, Function) and not obj.is_method() or isinstance(obj, Class)) and not obj.referenced: + self.all_objects.remove(obj) + # Remove unused entries from classes plus associated methods. + + if isinstance(obj, Class): + for name, attr in obj.class_attributes().items(): + + if name not in self.importer.names_used: + del obj[name] + + # Methods can only be deleted if they are the only + # assigned object to the class and are unreferenced. + + if attr.assignments == 1 and isinstance(attr.value, Function) and \ + attr.value.is_method() and not attr.value.referenced: + + self.all_objects.remove(attr.value) + + def finalise(self): + + "Finalise the module." + + for obj in self.all_objects: + if isinstance(obj, (Class, Function)): + obj.finalise_attributes() + def add_object(self, obj, any_scope=0): """ diff -r 06a8cc27a08a -r 13861cd5d245 test.py --- a/test.py Sat Nov 08 23:11:45 2008 +0100 +++ b/test.py Mon Nov 10 21:38:58 2008 +0100 @@ -82,7 +82,6 @@ if "-tb" in args: raise else: - i.vacuum() ot = i.get_object_table() pt = i.get_parameter_table()