# HG changeset patch # User Paul Boddie # Date 1202520957 -3600 # Node ID 850db0ec0ccfcd323ca458e70ca775d11db8332a # Parent 5d8f34d7ce7fb70927985e8de1fb1514dab537b2 Fixed NamespaceDict handling of global name assignments. Changed the image layout, employing the new NamespaceDict.to_list method to acquire attributes in order. Made InspectError instances carry more information so that they can be used at the top level of a program. Improved string representations of instances. Added notes about module header structures. diff -r 5d8f34d7ce7f -r 850db0ec0ccf README.txt --- a/README.txt Wed Feb 06 01:28:11 2008 +0100 +++ b/README.txt Sat Feb 09 02:35:57 2008 +0100 @@ -78,7 +78,19 @@ function reference function reference reference -Here, the code reference would lead to code for the function. +Here, the code reference would lead to code for the function. Note that the +function locals are completely distinct from this structure and are not +comparable to attributes. + +For modules, the invocation reference would point to the start of the +module's code: + +Module m: + + 0 1 2 3 4 + code for m code module type attribute ... + reference reference (global) + reference Invocation Operation -------------------- diff -r 5d8f34d7ce7f -r 850db0ec0ccf micropython/__init__.py --- a/micropython/__init__.py Wed Feb 06 01:28:11 2008 +0100 +++ b/micropython/__init__.py Sat Feb 09 02:35:57 2008 +0100 @@ -42,6 +42,8 @@ except NameError: from sets import Set as set +InspectError = micropython.inspect.InspectError + class Importer: "An import machine, searching for and loading modules." @@ -94,11 +96,6 @@ module.location = pos trans = micropython.ast.Translation(module, objtable, paramtable) - # Add header details. - - image.append(module) - pos += 1 - # Append constants to the image. for const in module.constants(): @@ -106,14 +103,16 @@ image.append(const) pos += 1 + # Add header details. + + image.append(module) + pos += 1 + # Append module attributes to the image. attributes = module.module_attributes() - - for name in module.module_attribute_names(): - attr = attributes[name] - image.append(attr) - pos += 1 + image += module.to_list(attributes) + pos += len(attributes.keys()) # Append classes and functions to the image. @@ -132,11 +131,8 @@ # Append class attributes to the image. attributes = obj.class_attributes() - - for name in obj.class_attribute_names(): - attr = attributes[name] - image.append(attr) - pos += 1 + image += module.to_list(attributes) + pos += len(attributes.keys()) # Append the class-level code to the image. # NOTE: An extra optimisation would involve @@ -145,7 +141,7 @@ # NOTE: methods and only other attribute-related code being # NOTE: generated here. - obj.code_location = obj.location = pos + obj.code_location = pos code = trans.get_code(obj) image += code pos += len(code) diff -r 5d8f34d7ce7f -r 850db0ec0ccf micropython/ast.py --- a/micropython/ast.py Wed Feb 06 01:28:11 2008 +0100 +++ b/micropython/ast.py Sat Feb 09 02:35:57 2008 +0100 @@ -134,9 +134,9 @@ return ASTVisitor.dispatch(self, node, *args) def _visitName(self, node, classes): - #print self.module.name, node.lineno name = node.name scope = self.get_scope(name) + #print self.module.name, node.lineno, name, scope NameInstruction, AttrInstruction = classes if scope == "local": diff -r 5d8f34d7ce7f -r 850db0ec0ccf micropython/inspect.py --- a/micropython/inspect.py Wed Feb 06 01:28:11 2008 +0100 +++ b/micropython/inspect.py Sat Feb 09 02:35:57 2008 +0100 @@ -56,7 +56,9 @@ "An inspection error." - pass + def __init__(self, node, message): + self.node = node + self.message = message class AtLeast: @@ -120,21 +122,18 @@ return self.namespace.get(name, default) def __setitem__(self, name, value): - - # Use a special method to access the namespace. - - if name not in self.globals: - self.set(name, value) - else: - self.global_namespace.set(name, value, 0) + self.set(name, value) def set(self, name, value, single_assignment=1): - attr = self._set(name, value) + if name in self.globals: + self.global_namespace.set(name, value, 0) + else: + attr = self._set(name, value) - # NOTE: Insist on assignments with known values. + # NOTE: Insist on assignments with known values. - if value is not None: - attr.update(value, single_assignment) + if value is not None: + attr.update(value, single_assignment) def set_module(self, name, value): attr = self._set(name, value) @@ -175,6 +174,12 @@ else: return None + def to_list(self, d): + l = [None] * len(d.keys()) + for attr in d.values(): + l[attr.position] = attr + return l + class Naming: "A mix-in providing naming conveniences." @@ -230,7 +235,10 @@ self.location = None def __repr__(self): - return "Const(%r, location=%r)" % (self.value, self.location) + if self.location is not None: + return "Const(%r, location=%r)" % (self.value, self.location) + else: + return "Const(%r)" % self.value def __eq__(self, other): return self.value == other.value @@ -264,7 +272,10 @@ self.code_location = None def __repr__(self): - return "Class(%r, %r, location=%r)" % (self.name, self.parent_name, self.location) + if self.location is not None: + return "Class(%r, %r, location=%r)" % (self.name, self.parent_name, self.location) + else: + return "Class(%r, %r)" % (self.name, self.parent_name) def add_base(self, base): self.bases.append(base) @@ -401,9 +412,14 @@ self[name] = None def __repr__(self): - return "Function(%r, %r, %r, %r, %r, location=%r)" % ( - self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar, self.location - ) + if self.location is not None: + return "Function(%r, %r, %r, %r, %r, location=%r)" % ( + self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar, self.location + ) + else: + return "Function(%r, %r, %r, %r, %r)" % ( + self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar + ) def make_global(self, name): if name not in self.argnames and not self.has_key(name): @@ -488,7 +504,10 @@ return self.name def __repr__(self): - return "Module(%r, location=%r)" % (self.name, self.location) + if self.location is not None: + return "Module(%r, location=%r)" % (self.name, self.location) + else: + return "Module(%r)" % self.name # Attribute methods. @@ -666,15 +685,19 @@ print "Class %r in %r is not global: ignored." % (node.name, self) else: cls = Class(node.name, self.get_parent().full_name(), self, node) + + # Visit the base class expressions, attempting to find concrete + # definitions of classes. + for base in node.bases: expr = self.dispatch(base) if isinstance(expr, Attr): if expr.assignments != 1: - print "Base class %r for class %r in %r may not be constant." % (base, cls, self) + raise InspectError(node, "Base class %r for %r in %r is not constant." % (base, cls, self)) else: cls.add_base(expr.value) else: # if expr is None: - raise InspectError, "Base class %r for class %r in %r is not found: it may be hidden in some way." % (base, cls, self) + raise InspectError(node, "Base class %r for %r in %r is not found: it may be hidden in some way." % (base, cls, self)) # Make a back reference from the node for code generation. @@ -722,7 +745,7 @@ def visitFrom(self, node): if self.importer is None: - raise InspectError, "Please use the micropython.Importer class for code which uses the 'from' statement." + raise InspectError(node, "Please use the micropython.Importer class for code which uses the 'from' statement.") module = self.importer.load(node.modname, 1) @@ -803,6 +826,9 @@ if self.namespaces: for name in node.names: self.namespaces[-1].make_global(name) + + # Record a global entry for the name in the module. + if not self.has_key(name): self[name] = Global() @@ -817,7 +843,7 @@ def visitImport(self, node): if self.importer is None: - raise InspectError, "Please use the micropython.Importer class for code which uses the 'import' statement." + raise InspectError(node, "Please use the micropython.Importer class for code which uses the 'import' statement.") for name, alias in node.names: if alias is not None: diff -r 5d8f34d7ce7f -r 850db0ec0ccf test.py --- a/test.py Wed Feb 06 01:28:11 2008 +0100 +++ b/test.py Sat Feb 09 02:35:57 2008 +0100 @@ -8,13 +8,18 @@ print i, x i = micropython.Importer(sys.path, "-v" in sys.argv) -if len(sys.argv) < 2: - m = i.load("micropython") - #m = i.load_from_file("micropython/__init__.py") +try: + if len(sys.argv) < 2: + m = i.load("micropython") + #m = i.load_from_file("micropython/__init__.py") + else: + m = i.load_from_file(sys.argv[1]) +except micropython.InspectError, exc: + print "At line", exc.node.lineno, "the following error occurred:" + print exc.message else: - m = i.load_from_file(sys.argv[1]) -i.vacuum() -ot = i.get_object_table() -pt = i.get_parameter_table() + i.vacuum() + ot = i.get_object_table() + pt = i.get_parameter_table() # vim: tabstop=4 expandtab shiftwidth=4