# HG changeset patch # User Paul Boddie # Date 1244837036 -7200 # Node ID 2a64685ab6dcacdca7a299f708d18520dbd55e1c # Parent edb8a3f00e899ce2771e0a00fcc2d2ba94fa9989 Fixed module attributes to behave like class attributes and officially be recognised as being statically positioned. Improved test coverage of module attributes. diff -r edb8a3f00e89 -r 2a64685ab6dc docs/concepts.txt --- a/docs/concepts.txt Mon Jun 08 00:49:37 2009 +0200 +++ b/docs/concepts.txt Fri Jun 12 22:03:56 2009 +0200 @@ -212,7 +212,10 @@ The locations stored in table/list elements are for instance attributes relative to the location of the instance, whereas those for class attributes and modules are absolute addresses (although these could also be changed to -object-relative locations). +object-relative locations). Thus, each occupied table cell has the following +structure: + + attrcode, uses-absolute-address, address (or location) Objects and Structures ====================== @@ -247,10 +250,12 @@ Used to test instances for membership of classes (or descendants of classes). -Since, in traditional Python, classes are only ever instances of the "type" -built-in class, support for testing such a relationship directly has been +Since, in traditional Python, classes are only ever instances of some generic +built-in type, support for testing such a relationship directly has been removed and the attrcode is not specified for classes: the presence of an -attrcode indicates that a given object is an instance. +attrcode indicates that a given object is an instance. In addition, support +has also been removed for testing modules in the same way, meaning that the +attrcode is also not specified for modules. See the "Testing Instance Compatibility with Classes (Attrcode)" section below for details of attrcodes. diff -r edb8a3f00e89 -r 2a64685ab6dc micropython/__init__.py --- a/micropython/__init__.py Mon Jun 08 00:49:37 2009 +0200 +++ b/micropython/__init__.py Fri Jun 12 22:03:56 2009 +0200 @@ -193,7 +193,7 @@ # Append the module top-level code to the image. else: - code = trans.get_module_code(final=(module is last_module)) + code = trans.get_module_code() self.code += code pos += len(code) diff -r edb8a3f00e89 -r 2a64685ab6dc micropython/ast.py --- a/micropython/ast.py Mon Jun 08 00:49:37 2009 +0200 +++ b/micropython/ast.py Fri Jun 12 22:03:56 2009 +0200 @@ -115,11 +115,10 @@ self.optimiser.reset() - def get_module_code(self, final=0): + def get_module_code(self): """ - Return the top-level module code including finalising code if 'final' is - set to a true value. + Return the top-level module code. """ self.unit = self.module @@ -133,7 +132,7 @@ # Finish off the translated program if appropriate. - if final: + if self.module.name == "__main__": self.new_op(Return()) self.unit.temp_usage = self.max_temp_position + 1 diff -r edb8a3f00e89 -r 2a64685ab6dc micropython/data.py --- a/micropython/data.py Mon Jun 08 00:49:37 2009 +0200 +++ b/micropython/data.py Fri Jun 12 22:03:56 2009 +0200 @@ -352,8 +352,14 @@ self.context_values.update(context_values) - def is_class_attribute(self): - return isinstance(self.parent, Class) + def is_static_attribute(self): + + """ + Return whether this attribute is defined on a fixed/static object such + as a class or a module. + """ + + return isinstance(self.parent, (Class, Module)) def defined_within_hierarchy(self): @@ -1222,7 +1228,7 @@ return [ DataObject( objtable.as_list().get_code(self.full_name()), - None, # NOTE: module name not used as an attribute, but should be instance + None, # modules treated like classes None, self.full_name(), len(self.module_attributes()) + 1 # size diff -r edb8a3f00e89 -r 2a64685ab6dc micropython/table.py --- a/micropython/table.py Mon Jun 08 00:49:37 2009 +0200 +++ b/micropython/table.py Fri Jun 12 22:03:56 2009 +0200 @@ -186,7 +186,7 @@ # Attribute index/code, attribute type, location/position. - return (attr_index, attr.is_class_attribute(), position) + return (attr_index, attr.is_static_attribute(), position) class ParameterList(List): diff -r edb8a3f00e89 -r 2a64685ab6dc rsvp.py --- a/rsvp.py Mon Jun 08 00:49:37 2009 +0200 +++ b/rsvp.py Fri Jun 12 22:03:56 2009 +0200 @@ -461,10 +461,10 @@ element = self.objlist[data.classcode + self.operand] if element is not None: - attr_index, class_attr, offset = element + attr_index, static_attr, offset = element if attr_index == self.operand: - if class_attr: - self.value = self.load(offset) # offset is address of class attribute + if static_attr: + self.value = self.load(offset) # offset is address of class/module attribute else: self.value = self.load(ref + offset) return @@ -480,11 +480,11 @@ element = self.objlist[data.classcode + self.operand] if element is not None: - attr_index, class_attr, offset = element + attr_index, static_attr, offset = element if attr_index == self.operand: - if class_attr: - loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute - if data.attrcode is None: # absent attrcode == class + if static_attr: + loaded_context, loaded_ref = self.load(offset) # offset is address of class/module attribute + if data.attrcode is None: # absent attrcode == class/module self.value = loaded_context, loaded_ref else: self.value = self._LoadAddressContextCond(loaded_context, loaded_ref, inst_ref) @@ -501,9 +501,9 @@ element = self.objlist[data.classcode + self.operand] if element is not None: - attr_index, class_attr, offset = element + attr_index, static_attr, offset = element if attr_index == self.operand: - if class_attr: + if static_attr: self.exception = self._MakeObject(2, self.type_error_instance) return self.RaiseException() else: @@ -715,7 +715,7 @@ # Insist on instance vs. class. - if data.attrcode is None: # absent attrcode == class + if data.attrcode is None: # absent attrcode == class/module return 0 if target_data.attrcode is not None: # present attrcode == instance @@ -726,7 +726,7 @@ element = self.objlist[target_data.classcode + data.attrcode] if element is not None: - attr_index, class_attr, offset = element + attr_index, static_attr, offset = element return attr_index == data.attrcode else: return 0 diff -r edb8a3f00e89 -r 2a64685ab6dc tests/failure/importer_module_attribute_assignment.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/importer_module_attribute_assignment.py Fri Jun 12 22:03:56 2009 +0200 @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import imported + +class C: # hack: make an attribute called y known to the system + y = None # hack: this prevents compilation errors with the statements + # hack: below + +n = None +n = imported +n.a = 1 # not detected due to reassignment of n +n.y = 2 # not detected due to reassignment of n +n.y = 3 # not detected due to reassignment of n + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r edb8a3f00e89 -r 2a64685ab6dc tests/importer.py --- a/tests/importer.py Mon Jun 08 00:49:37 2009 +0200 +++ b/tests/importer.py Fri Jun 12 22:03:56 2009 +0200 @@ -2,20 +2,10 @@ import imported -imported.attr # cannot assign to this +result_123 = imported.attr # cannot assign to this m = imported -imported.a # cannot assign to this -m.a # cannot assign to this (m is known) - -class C: # hack: make an attribute called y known to the system - y = None # hack: this prevents compilation errors with the statements - # hack: below - -n = None -n = imported -n.a = 1 # not detected due to reassignment of n -n.y = 2 # not detected due to reassignment of n -n.y = 3 # not detected due to reassignment of n +result1_10 = imported.a # can only read from the attribute, not replace it +result2_10 = m.a # can only read from the attribute (m is known) # vim: tabstop=4 expandtab shiftwidth=4 diff -r edb8a3f00e89 -r 2a64685ab6dc tests/importer_uncertain.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/importer_uncertain.py Fri Jun 12 22:03:56 2009 +0200 @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import imported + +m = None +m = imported + +result_123 = m.attr +result_10 = m.a + +# vim: tabstop=4 expandtab shiftwidth=4