1.1 --- a/micropython/__init__.py Mon Nov 16 00:34:47 2009 +0100
1.2 +++ b/micropython/__init__.py Sun Nov 22 04:15:05 2009 +0100
1.3 @@ -22,12 +22,10 @@
1.4
1.5 --------
1.6
1.7 -To use this module, an importer should be constructed and the load_from_file
1.8 -method used. Here, the standard path for module searching is employed:
1.9 +To use this module, an importer should be constructed. Here, the standard path
1.10 +for module searching is employed:
1.11
1.12 importer = Importer(sys.path)
1.13 -importer.load_from_file(filename)
1.14 -importer.vacuum()
1.15
1.16 To generate programs, the above importer should be supplied in the
1.17 initialisation of a program instance, and then various methods are called:
1.18 @@ -98,6 +96,14 @@
1.19
1.20 objtable = self.get_object_table()
1.21 paramtable = self.get_parameter_table()
1.22 +
1.23 + # Optimise and regenerate the object table.
1.24 +
1.25 + self.importer.vacuum(objtable)
1.26 + objtable = self.get_object_table(reset=1)
1.27 +
1.28 + # Finalise the importer.
1.29 +
1.30 self.importer.finalise()
1.31
1.32 self.code = []
1.33 @@ -243,12 +249,11 @@
1.34 self.code_location = self.importer.modules["__main__"].code_location
1.35 return self.raw_code
1.36
1.37 - def get_object_table(self):
1.38 + def get_object_table(self, reset=0):
1.39
1.40 "Return a table with details of attributes for classes and modules."
1.41
1.42 - if self.objtable is None:
1.43 - self.importer.vacuum()
1.44 + if self.objtable is None or reset:
1.45
1.46 t = self.objtable = micropython.table.ObjectTable()
1.47 for module in self.importer.get_modules():
1.48 @@ -331,6 +336,10 @@
1.49 "NotImplemented" : NotImplemented
1.50 }
1.51
1.52 + names_always_used = [
1.53 + "bool", "__init__", "__call__", "__bool__", "__builtins__", "__main__"
1.54 + ]
1.55 +
1.56 def __init__(self, path=None, verbose=0, optimisations=None):
1.57
1.58 """
1.59 @@ -358,11 +367,9 @@
1.60 self.constant_list = None # cache for constants
1.61 self.init_predefined_constants()
1.62
1.63 - # Name records (used to track actual use of names).
1.64 - # Include names which may not be explicitly used in programs.
1.65 - # NOTE: Potentially declare these when inspecting.
1.66 + # Attribute usage.
1.67
1.68 - self.names_used = None
1.69 + self.attributes_used = None
1.70 self.name_references = {}
1.71
1.72 # Status information.
1.73 @@ -384,13 +391,17 @@
1.74
1.75 # General maintenance.
1.76
1.77 - def vacuum(self):
1.78 + def vacuum(self, objtable):
1.79
1.80 "Tidy up the modules."
1.81
1.82 if self.vacuumed:
1.83 return
1.84
1.85 + # Complete the list of attribute names used in the program.
1.86 +
1.87 + self.collect_attributes(objtable)
1.88 +
1.89 for name, module in self.modules.items():
1.90 if module.loaded:
1.91 module.vacuum()
1.92 @@ -401,13 +412,11 @@
1.93
1.94 def finalise(self):
1.95
1.96 - "Finalise the program."
1.97 + "Finalise the program (which should have been vacuumed first)."
1.98
1.99 if self.finalised:
1.100 return
1.101
1.102 - self.vacuum()
1.103 -
1.104 for module in self.get_modules():
1.105 module.finalise()
1.106
1.107 @@ -424,24 +433,73 @@
1.108
1.109 if not self.name_references.has_key(from_name):
1.110 self.name_references[from_name] = set()
1.111 - self.name_references[from_name].add(name)
1.112 + self.name_references[from_name].add((name,))
1.113 +
1.114 + def use_names(self, names, from_name):
1.115 +
1.116 + """
1.117 + Register the given 'names' as being used in the program from within an
1.118 + object with the specified 'from_name'.
1.119 + """
1.120 +
1.121 + if not self.name_references.has_key(from_name):
1.122 + self.name_references[from_name] = set()
1.123 + self.name_references[from_name].add(names)
1.124 +
1.125 + def uses_attribute(self, obj, name):
1.126
1.127 - def uses_name(self, name):
1.128 + """
1.129 + Return whether the attribute of object 'obj' having the given 'name' is
1.130 + used as an attribute in the program.
1.131 + """
1.132 +
1.133 + return name in self.attributes_used.get(obj.full_name(), [])
1.134 +
1.135 + def use_attribute(self, objname, name):
1.136
1.137 - "Return whether the given 'name' is used."
1.138 + """
1.139 + Indicate that in the object with the given 'objname', the attribute of
1.140 + the given 'name' is used.
1.141 + """
1.142 +
1.143 + if not self.attributes_used.has_key(objname):
1.144 + self.attributes_used[objname] = set()
1.145 + self.attributes_used[objname].add(name)
1.146
1.147 - if self.names_used is None:
1.148 - self.names_used = set(["bool", "__init__", "__call__", "__bool__", "__builtins__", "__main__"])
1.149 - self._collect_names("__builtins__")
1.150 - self._collect_names("__main__")
1.151 + def collect_attributes(self, objtable):
1.152 +
1.153 + "Collect attribute references for the entire program."
1.154 +
1.155 + if self.attributes_used is None:
1.156 +
1.157 + # Include names which may not be explicitly used in programs.
1.158 + # NOTE: Potentially declare these when inspecting.
1.159 +
1.160 + self.attributes_used = {}
1.161 + for name in self.names_always_used:
1.162 + for objname in objtable.all_possible_objects([name]):
1.163 + self.use_attribute(objname, name)
1.164 +
1.165 + # Start with the "root" modules, finding referenced objects.
1.166
1.167 - return name in self.names_used
1.168 + self._collect_attributes("__builtins__", objtable)
1.169 + self._collect_attributes("__main__", objtable)
1.170 +
1.171 + def _collect_attributes(self, from_name, objtable):
1.172
1.173 - def _collect_names(self, from_name):
1.174 - for name in self.name_references.get(from_name, []):
1.175 - if name not in self.names_used:
1.176 - self.names_used.add(name)
1.177 - self._collect_names(name)
1.178 + """
1.179 + Given an object called 'from_name', find all names referenced from such
1.180 + an object according to the register of names.
1.181 + """
1.182 +
1.183 + if self.attributes_used.has_key(from_name):
1.184 + return
1.185 +
1.186 + for names in self.name_references.get(from_name, []):
1.187 + for objname in objtable.all_possible_objects(names):
1.188 + for name in names:
1.189 + self.use_attribute(objname, name)
1.190 + self._collect_attributes(objname + "." + name, objtable)
1.191
1.192 # Constant accounting.
1.193