1.1 --- a/micropython/inspect.py Sun Jul 12 03:28:40 2009 +0200
1.2 +++ b/micropython/inspect.py Sun Jul 12 03:31:48 2009 +0200
1.3 @@ -176,67 +176,34 @@
1.4 names.
1.5 """
1.6
1.7 - # Remove unreferenced objects.
1.8 -
1.9 if self.should_optimise_unused_objects():
1.10 -
1.11 - for name, value in self.items():
1.12 -
1.13 - # Remove entries for unreferenced objects.
1.14 - # This, due to the nature of the referenced attribute, assumes
1.15 - # that only explicitly mentioned classes and functions are
1.16 - # employed in the final program.
1.17 -
1.18 - if isinstance(value, Attr):
1.19 -
1.20 - # Only remove entries for classes and functions, not methods.
1.21 -
1.22 - for attr_value in value.get_values():
1.23 - if (isinstance(attr_value, Function) and not attr_value.is_method() or
1.24 - isinstance(attr_value, Class)) and not attr_value.referenced:
1.25 - pass
1.26 - else:
1.27 - break
1.28 - else:
1.29 - del self[name]
1.30 + self.vacuum_object(self)
1.31
1.32 all_objects = list(self.all_objects)
1.33
1.34 for obj in all_objects:
1.35 -
1.36 - # Only remove entries for classes and functions, not methods.
1.37 -
1.38 - if (isinstance(obj, Function) and not obj.is_method() or
1.39 - isinstance(obj, Class)) and not obj.referenced:
1.40 + if isinstance(obj, Class):
1.41 + self.vacuum_object(obj)
1.42
1.43 - self.all_objects.remove(obj)
1.44 - obj_was_removed = 1
1.45 + def vacuum_object(self, obj, delete_all=0):
1.46
1.47 - else:
1.48 - obj_was_removed = 0
1.49 -
1.50 - # Remove unused entries from classes plus associated methods.
1.51 -
1.52 - if isinstance(obj, Class):
1.53 - for name, attr in obj.class_attributes().items():
1.54 + "Vacuum the given object 'obj'."
1.55
1.56 - # In removed classes, all explicitly defined methods can
1.57 - # be removed.
1.58 + for name, attr in obj.items():
1.59 + if delete_all or not self.importer.uses_name(name):
1.60 + del obj[name]
1.61 + if attr.assignments == 1:
1.62 + value = attr.get_value()
1.63
1.64 - # In other classes, methods can only be removed if they
1.65 - # are the only assigned object to the class for a
1.66 - # particular attribute and are unreferenced.
1.67 + # Delete any unambiguous attribute value.
1.68
1.69 - if obj_was_removed and isinstance(attr.get_value(), Function) and attr.get_value().is_method() or \
1.70 - not self.importer.uses_name(name) and \
1.71 - attr.assignments == 1 and isinstance(attr.get_value(), Function) and \
1.72 - attr.get_value().is_method() and not attr.get_value().referenced:
1.73 + if value is not obj and value in self.all_objects:
1.74 + self.all_objects.remove(value)
1.75
1.76 - method = attr.get_value()
1.77 + # Delete class contents.
1.78
1.79 - if method in self.all_objects:
1.80 - self.all_objects.remove(method)
1.81 - del obj[name]
1.82 + if isinstance(value, Class):
1.83 + self.vacuum_object(value, 1)
1.84
1.85 def finalise(self):
1.86
1.87 @@ -399,12 +366,6 @@
1.88 else:
1.89 self.store_lambda(function)
1.90
1.91 - # Lambda functions are always assumed to be referenced. This is
1.92 - # because other means of discovering the referencing of objects rely
1.93 - # on the original names inherent in the definition of those objects.
1.94 -
1.95 - function.set_referenced()
1.96 -
1.97 # Where defaults exist, an instance needs creating. Thus, it makes
1.98 # no sense to return a reference to the function here, since the
1.99 # recipient will not be referencing the function itself.
1.100 @@ -472,6 +433,7 @@
1.101
1.102 def visitAssName(self, node):
1.103 self.store(node.name, self.expr)
1.104 + self.use_name(node.name)
1.105 return None
1.106
1.107 visitAssTuple = visitAssList
1.108 @@ -585,6 +547,7 @@
1.109
1.110 # Register the constant, if necessary, returning the resulting object.
1.111
1.112 + self.use_name(self.importer.get_constant_type_name(node.value))
1.113 return self.importer.make_constant(node.value)
1.114
1.115 visitContinue = NOP
1.116 @@ -622,9 +585,6 @@
1.117 def visitFrom(self, node):
1.118 module = self.importer.load(node.modname, 1)
1.119
1.120 - if module is not None:
1.121 - module.set_referenced()
1.122 -
1.123 #if module is None:
1.124 # print "Warning:", node.modname, "not imported."
1.125
1.126 @@ -680,9 +640,6 @@
1.127
1.128 # Accounting.
1.129
1.130 - if attr is not None:
1.131 - attr.set_referenced()
1.132 -
1.133 self.use_name(attrname)
1.134
1.135 return attr
1.136 @@ -714,7 +671,6 @@
1.137 else:
1.138 module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self)
1.139 self.store(name.split(".")[0], module)
1.140 - module.set_referenced()
1.141
1.142 return None
1.143
1.144 @@ -727,6 +683,7 @@
1.145 return None
1.146
1.147 def visitLambda(self, node):
1.148 + self.use_name(None) # lambda functions have no names but are assumed to be invoked
1.149 return self._visitFunction(node, None)
1.150
1.151 visitLeftShift = _visitBinary
1.152 @@ -764,13 +721,7 @@
1.153 else:
1.154 attr = None
1.155
1.156 - # Accounting.
1.157 -
1.158 - if attr is not None:
1.159 - attr.set_referenced()
1.160 -
1.161 self.use_name(name)
1.162 -
1.163 return attr
1.164
1.165 visitNot = OP