# HG changeset patch # User Paul Boddie # Date 1193010287 -7200 # Node ID 24aa66f88d9becd84c078060b4af9fcd2f53d4fb # Parent 42ca98d76e087ed11fa56e871b4e05dd2f2ddeab Made separate methods for instance-only attributes and combined class plus instance attributes in Class. Simplified class attributes, mapping names to attribute objects themselves, rather than the origin (since the origin should be referenced in each object). Simplified module attributes, returning the plain module namespace. Added class name/attribute caching/stability. Added location details for classes, modules and functions along with support for generating program images (minus code generation). diff -r 42ca98d76e08 -r 24aa66f88d9b micropython/__init__.py --- a/micropython/__init__.py Sun Oct 21 23:54:45 2007 +0200 +++ b/micropython/__init__.py Mon Oct 22 01:44:47 2007 +0200 @@ -72,17 +72,53 @@ return self.modules.values() + def get_image(self): + + "Return a dictionary mapping modules to structures." + + image = [] + for module in self.get_modules(): + pos = len(image) + module.location = pos + attributes = module.module_attributes() + + for name in module.module_attribute_names(): + attr = attributes[name] + if isinstance(attr, (micropython.inspect.Class, micropython.inspect.Module, micropython.inspect.Function)): + image.append(attr) + else: + image.append(None) + pos += 1 + + for obj in module.all_objects: + if isinstance(obj, micropython.inspect.Class): + obj.location = pos + attributes = obj.class_attributes() + for name in obj.class_attribute_names(): + attr = attributes[name] + if isinstance(attr, (micropython.inspect.Class, micropython.inspect.Module, micropython.inspect.Function)): + image.append(attr) + else: + image.append(None) + pos += 1 + + # NOTE: Generate module and function code here. + + elif isinstance(obj, micropython.inspect.Function): + obj.location = pos + + return image + def get_object_table(self): "Return a table with details of attributes for classes and modules." t = micropython.table.Table() for module in self.get_modules(): + t.add(module.full_name(), module.module_attributes()) for obj in module.all_objects: if isinstance(obj, micropython.inspect.Class): - t.add(obj.full_name(), obj.instance_attributes()) - elif isinstance(obj, micropython.inspect.Module): - t.add(obj.full_name(), obj.module_attributes()) + t.add(obj.full_name(), obj.all_attributes()) return t def get_parameter_table(self): @@ -96,6 +132,8 @@ t.add(obj.full_name(), obj.parameters()) return t + # Import methods. + def find_in_path(self, name): """ diff -r 42ca98d76e08 -r 24aa66f88d9b micropython/inspect.py --- a/micropython/inspect.py Sun Oct 21 23:54:45 2007 +0200 +++ b/micropython/inspect.py Mon Oct 22 01:44:47 2007 +0200 @@ -67,27 +67,44 @@ self.parent_name = parent_name self.bases = [] self.namespace = {} - self.instattr = set() + self.instattr = set() # instance attributes self.instattr_names = [] # from instattr + self.classattr = None # cache for class_attributes + self.classattr_names = [] # from classattr + self.allattr = None # cache for all_attributes + self.allattr_names = [] # from allattr + + # Image generation details. + + self.location = None def add_base(self, base): self.bases.append(base) def __repr__(self): - return "Class(%r, %r)" % (self.name, self.parent_name) + return "Class(%r, %r, location=%r)" % (self.name, self.parent_name, self.location) + + def class_attribute_names(self): + + "Return the attribute names provided by the class." + + self.classattr_names = self.classattr_names or self.class_attributes().keys() + return self.classattr_names def class_attributes(self): "Return all class attributes, indicating the class which provides them." - attr = {} - reversed_bases = self.bases[:] - reversed_bases.reverse() - for cls in reversed_bases: - attr.update(cls.class_attributes()) - for name, value in self.namespace.items(): - attr[name] = self.full_name() - return attr + if self.classattr is None: + self.classattr = {} + reversed_bases = self.bases[:] + reversed_bases.reverse() + for cls in reversed_bases: + self.classattr.update(cls.class_attributes()) + for name, value in self.namespace.items(): + self.classattr[name] = value + + return self.classattr def instance_attribute_names(self): @@ -98,18 +115,34 @@ def instance_attributes(self): + "Return instance-only attributes for instances of this class." + + return self.instattr + + def all_attribute_names(self): + + """ + Return the names of all attributes provided by instances of this class. + """ + + self.allattr_names = self.allattr_names or self.all_attributes().keys() + return self.allattr_names + + def all_attributes(self): + """ Return all attributes for an instance, indicating either the class which provides them or that the instance itself provides them. """ - attr = {} - attr.update(self.class_attributes()) - for i, name in enumerate(self.instance_attribute_names()): - if attr.has_key(name): - print "Instance attribute %r in %r overrides class attribute." % (name, self) - attr[name] = i - return attr + if self.allattr is None: + self.allattr = {} + self.allattr.update(self.class_attributes()) + for i, name in enumerate(self.instance_attribute_names()): + if self.allattr.has_key(name): + print "Instance attribute %r in %r overrides class attribute." % (name, self) + self.allattr[name] = i + return self.allattr class Function(Naming): @@ -122,9 +155,13 @@ self.has_star = has_star self.has_dstar = has_dstar + # Image generation details. + + self.location = None + def __repr__(self): - return "Function(%r, %r, %r, %r, %r)" % ( - self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar + return "Function(%r, %r, %r, %r, %r, location=%r)" % ( + self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar, self.location ) def parameters(self): @@ -186,11 +223,21 @@ self.classes = [] self.module = None + # Image generation details. + + self.location = None + def parse(self, filename): + + "Parse the file having the given 'filename'." + module = compiler.parseFile(filename) self.process(module) def process(self, module): + + "Process the given 'module'." + self.module = module processed = self.dispatch(module) if self.namespace.has_key("__all__"): @@ -201,6 +248,9 @@ return processed def vacuum(self): + + "Vacuum the module namespace, removing unloaded module references." + for name, value in self.namespace.items(): if isinstance(value, Module) and not value.loaded: del self.namespace[name] @@ -209,7 +259,7 @@ return self.name def __repr__(self): - return "Module(%r)" % self.name + return "Module(%r, location=%r)" % (self.name, self.location) # Attribute methods. @@ -222,15 +272,9 @@ def module_attributes(self): - """ - Return a dictionary mapping module attributes to a position in the - module's namespace. - """ + "Return a dictionary mapping names to module attributes." - attributes = {} - for i, name in enumerate(self.module_attribute_names()): - attributes[name] = i - return attributes + return self.namespace # Namespace methods.