1.1 --- a/micropython/__init__.py Sat Nov 08 23:11:45 2008 +0100
1.2 +++ b/micropython/__init__.py Mon Nov 10 21:38:58 2008 +0100
1.3 @@ -95,14 +95,20 @@
1.4 self.init_predefined_constants()
1.5
1.6 # Name records (used to track actual use of names).
1.7 + # Include names which may not be explicitly used in programs.
1.8
1.9 - self.names_used = set()
1.10 + self.names_used = set(["__init__"])
1.11
1.12 # Main program information.
1.13
1.14 self.code = None
1.15 self.code_location = None
1.16
1.17 + # Status information.
1.18 +
1.19 + self.vacuumed = 0
1.20 + self.finalised = 0
1.21 +
1.22 # Name accounting.
1.23
1.24 def use_name(self, name):
1.25 @@ -156,25 +162,30 @@
1.26
1.27 "Tidy up the modules."
1.28
1.29 + if self.vacuumed:
1.30 + return
1.31 +
1.32 for name, module in self.modules.items():
1.33 if module.loaded:
1.34 module.vacuum()
1.35 else:
1.36 del self.modules[name]
1.37
1.38 + self.vacuumed = 1
1.39 +
1.40 def finalise(self):
1.41
1.42 "Finalise the program."
1.43
1.44 - for module in self.get_modules():
1.45 + if self.finalised:
1.46 + return
1.47
1.48 - # Fix the attributes.
1.49 + self.vacuum()
1.50
1.51 - module.finalise_attributes()
1.52 + for module in self.get_modules():
1.53 + module.finalise()
1.54
1.55 - for obj in module.all_objects:
1.56 - if isinstance(obj, (micropython.inspect.Class, micropython.inspect.Function)):
1.57 - obj.finalise_attributes()
1.58 + self.finalised = 1
1.59
1.60 # Access to finalised program information.
1.61
1.62 @@ -307,6 +318,8 @@
1.63 "Return a table with details of attributes for classes and modules."
1.64
1.65 if self.objtable is None:
1.66 + self.vacuum()
1.67 +
1.68 t = self.objtable = micropython.table.ObjectTable()
1.69 for module in self.get_modules():
1.70 t.add(module.full_name(), module.module_attributes())
2.1 --- a/micropython/ast.py Sat Nov 08 23:11:45 2008 +0100
2.2 +++ b/micropython/ast.py Mon Nov 10 21:38:58 2008 +0100
2.3 @@ -1668,7 +1668,7 @@
2.4 def visitFrom(self, node): pass
2.5
2.6 def visitFunction(self, node):
2.7 - if not node.unit.referenced and not node.unit.is_method():
2.8 + if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)):
2.9 return
2.10
2.11 # Only store the name when visiting this node from outside.
3.1 --- a/micropython/data.py Sat Nov 08 23:11:45 2008 +0100
3.2 +++ b/micropython/data.py Mon Nov 10 21:38:58 2008 +0100
3.3 @@ -490,7 +490,6 @@
3.4
3.5 "Return class attributes provided by this class only."
3.6
3.7 - self.finalise_class_attributes()
3.8 return dict(self)
3.9
3.10 def all_class_attribute_names(self):
4.1 --- a/micropython/inspect.py Sat Nov 08 23:11:45 2008 +0100
4.2 +++ b/micropython/inspect.py Mon Nov 10 21:38:58 2008 +0100
4.3 @@ -137,24 +137,27 @@
4.4
4.5 def vacuum(self):
4.6
4.7 - "Vacuum the module namespace, removing unloaded module references."
4.8 + """
4.9 + Vacuum the module namespace, removing unreferenced objects and unused
4.10 + names.
4.11 + """
4.12
4.13 for name, value in self.items():
4.14
4.15 - if isinstance(value, Attr):
4.16 - attr_value = value.value
4.17 + if self.should_optimise_unused_objects():
4.18
4.19 - # Remove non-loaded modules.
4.20 + # Remove unused names.
4.21
4.22 - if isinstance(attr_value, Module) and not attr_value.loaded:
4.23 + if name not in self.importer.names_used:
4.24 del self[name]
4.25
4.26 - # Remove unreferenced names.
4.27 + # Remove entries for unreferenced objects.
4.28 # This, due to the nature of the referenced attribute, assumes
4.29 # that only explicitly mentioned classes and functions are
4.30 # employed in the final program.
4.31
4.32 - elif self.should_optimise_unused_objects():
4.33 + elif isinstance(value, Attr):
4.34 + attr_value = value.value
4.35
4.36 # Only remove entries for classes and functions, not methods.
4.37
4.38 @@ -169,7 +172,7 @@
4.39
4.40 # Complain about globals not initialised at the module level.
4.41
4.42 - elif isinstance(value, Global):
4.43 + if isinstance(value, Global):
4.44 print "Warning: global %r in module %r not initialised at the module level." % (name, self.name)
4.45
4.46 # Remove unreferenced objects.
4.47 @@ -179,10 +182,38 @@
4.48 all_objects = list(self.all_objects)
4.49
4.50 for obj in all_objects:
4.51 +
4.52 + # Only remove entries for classes and functions, not methods.
4.53 +
4.54 if (isinstance(obj, Function) and not obj.is_method() or
4.55 isinstance(obj, Class)) and not obj.referenced:
4.56 +
4.57 self.all_objects.remove(obj)
4.58
4.59 + # Remove unused entries from classes plus associated methods.
4.60 +
4.61 + if isinstance(obj, Class):
4.62 + for name, attr in obj.class_attributes().items():
4.63 +
4.64 + if name not in self.importer.names_used:
4.65 + del obj[name]
4.66 +
4.67 + # Methods can only be deleted if they are the only
4.68 + # assigned object to the class and are unreferenced.
4.69 +
4.70 + if attr.assignments == 1 and isinstance(attr.value, Function) and \
4.71 + attr.value.is_method() and not attr.value.referenced:
4.72 +
4.73 + self.all_objects.remove(attr.value)
4.74 +
4.75 + def finalise(self):
4.76 +
4.77 + "Finalise the module."
4.78 +
4.79 + for obj in self.all_objects:
4.80 + if isinstance(obj, (Class, Function)):
4.81 + obj.finalise_attributes()
4.82 +
4.83 def add_object(self, obj, any_scope=0):
4.84
4.85 """
5.1 --- a/test.py Sat Nov 08 23:11:45 2008 +0100
5.2 +++ b/test.py Mon Nov 10 21:38:58 2008 +0100
5.3 @@ -82,7 +82,6 @@
5.4 if "-tb" in args:
5.5 raise
5.6 else:
5.7 - i.vacuum()
5.8 ot = i.get_object_table()
5.9 pt = i.get_parameter_table()
5.10