1.1 --- a/micropython/__init__.py Sun Jul 12 03:28:40 2009 +0200
1.2 +++ b/micropython/__init__.py Sun Jul 12 03:31:48 2009 +0200
1.3 @@ -515,7 +515,8 @@
1.4 "Return whether the given 'name' is used."
1.5
1.6 if self.names_used is None:
1.7 - self.names_used = set(["__init__", "__call__", "__bool__"])
1.8 + self.names_used = set(["bool", "__init__", "__call__", "__bool__", "__builtins__", "__main__"])
1.9 + self._collect_names("__builtins__")
1.10 self._collect_names("__main__")
1.11
1.12 return name in self.names_used
1.13 @@ -548,17 +549,18 @@
1.14 const = micropython.data.Const(value)
1.15 return self.constant_values[const]
1.16
1.17 + def get_constant_type_name(self, value):
1.18 + return value.__class__.__name__
1.19 +
1.20 def make_constant(self, value):
1.21
1.22 "Make and return a constant for the given 'value'."
1.23
1.24 # Ensure the presence of the constant's type.
1.25
1.26 - name = value.__class__.__name__
1.27 + name = self.get_constant_type_name(value)
1.28 if self.modules.has_key("__builtins__"):
1.29 attr = self.modules["__builtins__"].get(name)
1.30 - if attr is not None:
1.31 - attr.set_referenced()
1.32
1.33 # Make a constant object and return it.
1.34
2.1 --- a/micropython/ast.py Sun Jul 12 03:28:40 2009 +0200
2.2 +++ b/micropython/ast.py Sun Jul 12 03:31:48 2009 +0200
2.3 @@ -546,7 +546,7 @@
2.4 self.discard_temp(temp2)
2.5
2.6 def visitClass(self, node):
2.7 - if not node.unit.referenced:
2.8 + if not node.unit.parent.has_key(node.unit.name):
2.9 return
2.10
2.11 # Store the name.
2.12 @@ -569,7 +569,7 @@
2.13 def visitFrom(self, node): pass
2.14
2.15 def visitFunction(self, node):
2.16 - if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)):
2.17 + if not node.unit.parent.has_key(node.unit.name):
2.18 return
2.19
2.20 # Only store the name when visiting this node from outside.
3.1 --- a/micropython/data.py Sun Jul 12 03:28:40 2009 +0200
3.2 +++ b/micropython/data.py Sun Jul 12 03:31:48 2009 +0200
3.3 @@ -291,17 +291,6 @@
3.4 # Number of assignments per name.
3.5
3.6 self.assignments = None
3.7 - self.referenced = 0
3.8 -
3.9 - def set_referenced(self):
3.10 -
3.11 - "Indicate that the contents are referenced via a namespace."
3.12 -
3.13 - self.referenced = 1
3.14 -
3.15 - for value in self.get_values():
3.16 - if value is not None:
3.17 - value.set_referenced()
3.18
3.19 def get_contexts(self):
3.20 return [c for (c, v) in self.context_values]
3.21 @@ -343,13 +332,6 @@
3.22 else:
3.23 self.assignments += AtLeast(1)
3.24
3.25 - # Communicate referencing information.
3.26 -
3.27 - if self.referenced:
3.28 - for context, value in context_values:
3.29 - if value is not None:
3.30 - value.set_referenced()
3.31 -
3.32 self.context_values.update(context_values)
3.33
3.34 def is_static_attribute(self):
3.35 @@ -466,15 +448,11 @@
3.36
3.37 def __init__(self):
3.38 self.parent = None
3.39 - self.referenced = 0
3.40
3.41 # Image generation details.
3.42
3.43 self.location = None
3.44
3.45 - def set_referenced(self):
3.46 - self.referenced = 1
3.47 -
3.48 def __repr__(self):
3.49 return "Instance()"
3.50
3.51 @@ -552,7 +530,6 @@
3.52 self.name = name
3.53 self.parent = parent
3.54 self.astnode = node
3.55 - self.referenced = 0
3.56
3.57 # Superclasses, descendants and attributes.
3.58
3.59 @@ -592,9 +569,6 @@
3.60
3.61 self.set("__class__", self)
3.62
3.63 - def set_referenced(self):
3.64 - self.referenced = 1
3.65 -
3.66 def __repr__(self):
3.67 if self.location is not None:
3.68 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location)
3.69 @@ -954,7 +928,6 @@
3.70 self.has_star = has_star
3.71 self.has_dstar = has_dstar
3.72 self.astnode = node
3.73 - self.referenced = 0
3.74
3.75 # For lambda functions with defaults, add a context argument.
3.76
3.77 @@ -1000,9 +973,6 @@
3.78 self.local_usage = 0
3.79 self.all_local_usage = 0
3.80
3.81 - def set_referenced(self):
3.82 - self.referenced = 1
3.83 -
3.84 def _add_parameters(self, argnames):
3.85 for name in argnames:
3.86 if isinstance(name, tuple):
3.87 @@ -1162,13 +1132,9 @@
3.88 self.name = name
3.89 self.parent_name = parent_name
3.90 self.parent = None
3.91 - self.referenced = 0
3.92
3.93 self.descendants = set()
3.94
3.95 - def set_referenced(self):
3.96 - self.referenced = 1
3.97 -
3.98 def add_descendant(self, cls):
3.99 self.descendants.add(cls)
3.100
3.101 @@ -1197,7 +1163,6 @@
3.102 NamespaceDict.__init__(self, self)
3.103 self.name = name
3.104 self.parent = None
3.105 - self.referenced = 0
3.106
3.107 # Original location details.
3.108
3.109 @@ -1223,9 +1188,6 @@
3.110 self.local_usage = 0
3.111 self.all_local_usage = 0
3.112
3.113 - def set_referenced(self):
3.114 - self.referenced = 1
3.115 -
3.116 def full_name(self):
3.117 return self.name
3.118
4.1 --- a/micropython/inspect.py Sun Jul 12 03:28:40 2009 +0200
4.2 +++ b/micropython/inspect.py Sun Jul 12 03:31:48 2009 +0200
4.3 @@ -176,67 +176,34 @@
4.4 names.
4.5 """
4.6
4.7 - # Remove unreferenced objects.
4.8 -
4.9 if self.should_optimise_unused_objects():
4.10 -
4.11 - for name, value in self.items():
4.12 -
4.13 - # Remove entries for unreferenced objects.
4.14 - # This, due to the nature of the referenced attribute, assumes
4.15 - # that only explicitly mentioned classes and functions are
4.16 - # employed in the final program.
4.17 -
4.18 - if isinstance(value, Attr):
4.19 -
4.20 - # Only remove entries for classes and functions, not methods.
4.21 -
4.22 - for attr_value in value.get_values():
4.23 - if (isinstance(attr_value, Function) and not attr_value.is_method() or
4.24 - isinstance(attr_value, Class)) and not attr_value.referenced:
4.25 - pass
4.26 - else:
4.27 - break
4.28 - else:
4.29 - del self[name]
4.30 + self.vacuum_object(self)
4.31
4.32 all_objects = list(self.all_objects)
4.33
4.34 for obj in all_objects:
4.35 -
4.36 - # Only remove entries for classes and functions, not methods.
4.37 -
4.38 - if (isinstance(obj, Function) and not obj.is_method() or
4.39 - isinstance(obj, Class)) and not obj.referenced:
4.40 + if isinstance(obj, Class):
4.41 + self.vacuum_object(obj)
4.42
4.43 - self.all_objects.remove(obj)
4.44 - obj_was_removed = 1
4.45 + def vacuum_object(self, obj, delete_all=0):
4.46
4.47 - else:
4.48 - obj_was_removed = 0
4.49 -
4.50 - # Remove unused entries from classes plus associated methods.
4.51 -
4.52 - if isinstance(obj, Class):
4.53 - for name, attr in obj.class_attributes().items():
4.54 + "Vacuum the given object 'obj'."
4.55
4.56 - # In removed classes, all explicitly defined methods can
4.57 - # be removed.
4.58 + for name, attr in obj.items():
4.59 + if delete_all or not self.importer.uses_name(name):
4.60 + del obj[name]
4.61 + if attr.assignments == 1:
4.62 + value = attr.get_value()
4.63
4.64 - # In other classes, methods can only be removed if they
4.65 - # are the only assigned object to the class for a
4.66 - # particular attribute and are unreferenced.
4.67 + # Delete any unambiguous attribute value.
4.68
4.69 - if obj_was_removed and isinstance(attr.get_value(), Function) and attr.get_value().is_method() or \
4.70 - not self.importer.uses_name(name) and \
4.71 - attr.assignments == 1 and isinstance(attr.get_value(), Function) and \
4.72 - attr.get_value().is_method() and not attr.get_value().referenced:
4.73 + if value is not obj and value in self.all_objects:
4.74 + self.all_objects.remove(value)
4.75
4.76 - method = attr.get_value()
4.77 + # Delete class contents.
4.78
4.79 - if method in self.all_objects:
4.80 - self.all_objects.remove(method)
4.81 - del obj[name]
4.82 + if isinstance(value, Class):
4.83 + self.vacuum_object(value, 1)
4.84
4.85 def finalise(self):
4.86
4.87 @@ -399,12 +366,6 @@
4.88 else:
4.89 self.store_lambda(function)
4.90
4.91 - # Lambda functions are always assumed to be referenced. This is
4.92 - # because other means of discovering the referencing of objects rely
4.93 - # on the original names inherent in the definition of those objects.
4.94 -
4.95 - function.set_referenced()
4.96 -
4.97 # Where defaults exist, an instance needs creating. Thus, it makes
4.98 # no sense to return a reference to the function here, since the
4.99 # recipient will not be referencing the function itself.
4.100 @@ -472,6 +433,7 @@
4.101
4.102 def visitAssName(self, node):
4.103 self.store(node.name, self.expr)
4.104 + self.use_name(node.name)
4.105 return None
4.106
4.107 visitAssTuple = visitAssList
4.108 @@ -585,6 +547,7 @@
4.109
4.110 # Register the constant, if necessary, returning the resulting object.
4.111
4.112 + self.use_name(self.importer.get_constant_type_name(node.value))
4.113 return self.importer.make_constant(node.value)
4.114
4.115 visitContinue = NOP
4.116 @@ -622,9 +585,6 @@
4.117 def visitFrom(self, node):
4.118 module = self.importer.load(node.modname, 1)
4.119
4.120 - if module is not None:
4.121 - module.set_referenced()
4.122 -
4.123 #if module is None:
4.124 # print "Warning:", node.modname, "not imported."
4.125
4.126 @@ -680,9 +640,6 @@
4.127
4.128 # Accounting.
4.129
4.130 - if attr is not None:
4.131 - attr.set_referenced()
4.132 -
4.133 self.use_name(attrname)
4.134
4.135 return attr
4.136 @@ -714,7 +671,6 @@
4.137 else:
4.138 module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self)
4.139 self.store(name.split(".")[0], module)
4.140 - module.set_referenced()
4.141
4.142 return None
4.143
4.144 @@ -727,6 +683,7 @@
4.145 return None
4.146
4.147 def visitLambda(self, node):
4.148 + self.use_name(None) # lambda functions have no names but are assumed to be invoked
4.149 return self._visitFunction(node, None)
4.150
4.151 visitLeftShift = _visitBinary
4.152 @@ -764,13 +721,7 @@
4.153 else:
4.154 attr = None
4.155
4.156 - # Accounting.
4.157 -
4.158 - if attr is not None:
4.159 - attr.set_referenced()
4.160 -
4.161 self.use_name(name)
4.162 -
4.163 return attr
4.164
4.165 visitNot = OP