# HG changeset patch # User Paul Boddie # Date 1247271669 -7200 # Node ID d99bfad0babf48a7d7be327109c1e407c0ff79de # Parent 3a02c37d4489a55534d89cbe721ad4a7d84b376d Introduce a mapping of unit names to names used in order to provide a better level of tracing of units actually employed in programs. diff -r 3a02c37d4489 -r d99bfad0babf micropython/__init__.py --- a/micropython/__init__.py Sat Jul 11 01:18:53 2009 +0200 +++ b/micropython/__init__.py Sat Jul 11 02:21:09 2009 +0200 @@ -446,7 +446,8 @@ # Include names which may not be explicitly used in programs. # NOTE: Potentially declare these when inspecting. - self.names_used = set(["__init__", "__call__", "__bool__"]) + self.names_used = None + self.name_references = {} # Status information. @@ -498,11 +499,32 @@ # Name accounting. - def use_name(self, name): + def use_name(self, name, from_name): + + """ + Register the given 'name' as being used in the program from within an + object with the specified 'from_name'. + """ + + if not self.name_references.has_key(from_name): + self.name_references[from_name] = set() + self.name_references[from_name].add(name) + + def uses_name(self, name): - "Register the given 'name' as being used in the program." + "Return whether the given 'name' is used." + + if self.names_used is None: + self.names_used = set(["__init__", "__call__", "__bool__"]) + self._collect_names("__main__") - self.names_used.add(name) + return name in self.names_used + + def _collect_names(self, from_name): + for name in self.name_references.get(from_name, []): + if name not in self.names_used: + self.names_used.add(name) + self._collect_names(name) # Constant accounting. diff -r 3a02c37d4489 -r d99bfad0babf micropython/inspect.py --- a/micropython/inspect.py Sat Jul 11 01:18:53 2009 +0200 +++ b/micropython/inspect.py Sat Jul 11 02:21:09 2009 +0200 @@ -228,7 +228,7 @@ # particular attribute and are unreferenced. if obj_was_removed and isinstance(attr.get_value(), Function) and attr.get_value().is_method() or \ - name not in self.importer.names_used and \ + not self.importer.uses_name(name) and \ attr.assignments == 1 and isinstance(attr.get_value(), Function) and \ attr.get_value().is_method() and not attr.get_value().referenced: @@ -317,6 +317,13 @@ return (self.namespaces[-1:] or [self])[0] + def use_name(self, name): + + "Use the given 'name' within the current namespace/unit." + + unit = self.get_parent() + self.importer.use_name(name, unit.name) + # Visitor methods. def default(self, node, *args): @@ -340,7 +347,7 @@ "Accounting method for the unary operator 'node'." method = unary_methods[node.__class__.__name__] - self.importer.use_name(method) + self.use_name(method) return self.OP(node) def _visitBinary(self, node): @@ -348,8 +355,8 @@ "Accounting method for the binary operator 'node'." left_method, right_method = binary_methods[node.__class__.__name__] - self.importer.use_name(left_method) - self.importer.use_name(right_method) + self.use_name(left_method) + self.use_name(right_method) return self.OP(node) def _visitFunction(self, node, name): @@ -454,7 +461,7 @@ # Declare names which will be used by generated code. - self.importer.use_name("__getitem__") + self.use_name("__getitem__") # Process the assignment. @@ -474,9 +481,9 @@ # Accounting. aug_method, (left_method, right_method) = augassign_methods[node.op] - self.importer.use_name(aug_method) - self.importer.use_name(left_method) - self.importer.use_name(right_method) + self.use_name(aug_method) + self.use_name(left_method) + self.use_name(right_method) # Process the assignment. @@ -567,10 +574,10 @@ op_name, next_node = op methods = comparison_methods[op_name] if methods is not None: - self.importer.use_name(methods[0]) - self.importer.use_name(methods[1]) + self.use_name(methods[0]) + self.use_name(methods[1]) elif op_name.endswith("in"): - self.importer.use_name("__contains__") + self.use_name("__contains__") return self.OP(node) @@ -602,8 +609,8 @@ # Declare names which will be used by generated code. - self.importer.use_name("__iter__") - self.importer.use_name("next") + self.use_name("__iter__") + self.use_name("next") # Enter the loop. @@ -676,7 +683,7 @@ if attr is not None: attr.set_referenced() - self.importer.use_name(attrname) + self.use_name(attrname) return attr @@ -762,7 +769,7 @@ if attr is not None: attr.set_referenced() - self.importer.use_name(name) + self.use_name(name) return attr @@ -796,7 +803,7 @@ visitSub = _visitBinary def visitSubscript(self, node): - self.importer.use_name("__getitem__") + self.use_name("__getitem__") self.OP(node) def visitTryExcept(self, node):