# HG changeset patch # User Paul Boddie # Date 1219790613 -7200 # Node ID eb01c567dfeb139173c00a100a058afcfaf68596 # Parent 12c97a4d751cce45b28f0f0567cc70771aa5132f Added descendants (and self) to the collection of attributes for each class, stored in the object table. Switched the "validator" stored in the tables to be the attribute index as opposed to the offset - this might help when eventually trying to encode and store such data in low memory environments. Employed a slightly better approach to populating the displacement lists generated for tables by adding rows in descending order of utilisation (ie. with most gaps or empty entries last). Added a simple visualisation function in the test program for viewing raw table data. diff -r 12c97a4d751c -r eb01c567dfeb micropython/__init__.py --- a/micropython/__init__.py Mon Aug 25 02:04:10 2008 +0200 +++ b/micropython/__init__.py Wed Aug 27 00:43:33 2008 +0200 @@ -232,9 +232,16 @@ t = self.objtable = micropython.table.ObjectTable() for module in self.get_modules(): t.add(module.full_name(), module.module_attributes()) + + # Add class and instance attributes for all classes, together + # with descendant information. + for obj in module.all_objects: if isinstance(obj, micropython.inspect.Class): - t.add(obj.full_name(), obj.all_attributes()) + attributes = {obj.full_name() : obj} + attributes.update(obj.all_attributes()) + attributes.update(obj.all_descendants()) + t.add(obj.full_name(), attributes) return self.objtable diff -r 12c97a4d751c -r eb01c567dfeb micropython/data.py --- a/micropython/data.py Mon Aug 25 02:04:10 2008 +0200 +++ b/micropython/data.py Wed Aug 27 00:43:33 2008 +0200 @@ -457,6 +457,12 @@ def has_subclass(self, other): return other in self.descendants + def all_descendants(self): + d = {} + for cls in self.descendants: + d[cls.full_name()] = cls + return d + "Return the attribute names provided by this class only." class_attribute_names = NamespaceDict.keys diff -r 12c97a4d751c -r eb01c567dfeb micropython/table.py --- a/micropython/table.py Mon Aug 25 02:04:10 2008 +0200 +++ b/micropython/table.py Wed Aug 27 00:43:33 2008 +0200 @@ -20,6 +20,7 @@ """ from micropython.common import * +from micropython.data import * class List: @@ -55,8 +56,8 @@ element = self.displaced[obj_offset + attr_index] if element is not None: - offset, details = element - if offset == obj_offset: + index, details = element + if index == attr_index: return details return None @@ -126,11 +127,14 @@ for i in xrange(0, offset + len(attributes) - len_displaced): self.displaced.append(None) - # Record the offset and attribute details in the list. + # Record the attribute details in the list. for i, attr in enumerate(attributes): if attr is not None: - self.displaced[offset+i] = offset, attr + + # Each entry is of the form (attribute number, attribute). + + self.displaced[offset+i] = i, attr # Image production. @@ -152,7 +156,12 @@ "An object list." def entry_as_raw(self, entry): - offset, attr = entry + attr_index, attr = entry + + # Support descendants. + + if isinstance(attr, Class): + return attr_index if attr.parent is not None: location = attr.parent.location or 0 @@ -163,9 +172,9 @@ else: position = None # NOTE: Should fix unpositioned attributes. - # Class offset/code, attribute type, context instance override flag, location/position. + # Attribute index/code, attribute type, context instance override flag, location/position. - return (offset, attr.is_class_attribute(), attr.defined_within_hierarchy(), position) + return (attr_index, attr.is_class_attribute(), attr.defined_within_hierarchy(), position) class ParameterList(List): @@ -295,7 +304,18 @@ # Visit each row of the matrix. + matrix_by_usage = [] + size = len(self.attributes) + + # Add rows in descending order of utilisation. + for objname, attributes in self.as_matrix().items(): + matrix_by_usage.append((size - attributes.count(None), objname, attributes)) + + matrix_by_usage.sort() + matrix_by_usage.reverse() + + for usage, objname, attributes in matrix_by_usage: self.displaced_list.add(objname, attributes) return self.displaced_list diff -r 12c97a4d751c -r eb01c567dfeb rsvp.py --- a/rsvp.py Mon Aug 25 02:04:10 2008 +0200 +++ b/rsvp.py Wed Aug 27 00:43:33 2008 +0200 @@ -253,8 +253,8 @@ context, ref = self.value classcode, attrcode, codeaddr, codedetails = self.load(ref) element = self.objtable[classcode + self.operand] - found_code, class_attr, replace_context, offset = element - if found_code == classcode: + attr_index, class_attr, replace_context, offset = element + if attr_index == self.operand: if class_attr: loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute if replace_context: @@ -271,8 +271,8 @@ context, ref = self.value classcode, attrcode, codeaddr, codedetails = self.load(ref) element = self.objtable[classcode + self.operand] - found_code, class_attr, replace_context, offset = element - if found_code == classcode: + attr_index, class_attr, replace_context, offset = element + if attr_index == self.operand: if class_attr: # NOTE: This should cause an attribute or type error. # Class attributes cannot be changed at run-time. @@ -302,8 +302,8 @@ frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame classcode, attrcode, codeaddr, codedetails = self.load(ref) element = self.objtable[classcode + self.operand] - found_code, offset = element - if found_code == classcode: + attr_index, offset = element + if attr_index == self.operand: self.frame_stack[frame + offset] = self.value else: # NOTE: This should cause an argument error. @@ -349,11 +349,17 @@ def CheckSelf(self): context, ref = self.value target_context, target_ref = self.source + + # Load the details of the proposed context and the target's context. + classcode, attrcode, codeaddr, codedetails = self.load(ref) target_classcode, target_attrcode, target_codeaddr, target_codedetails = self.load(target_context) + + # Find the table entry for the descendant. + element = self.objtable[target_classcode + attrcode] - found_code, class_attr, replace_context, offset = element - if found_code == target_classcode: + attr_index, class_attr, replace_context, offset = element + if attr_index == attrcode: self.status = 1 else: self.status = 0 diff -r 12c97a4d751c -r eb01c567dfeb test.py --- a/test.py Mon Aug 25 02:04:10 2008 +0200 +++ b/test.py Wed Aug 27 00:43:33 2008 +0200 @@ -21,6 +21,12 @@ for i, x in enumerate(code): print i, x +def show_table_usage(raw_table, slice_size=100): + for x in xrange(0, len(raw_table), slice_size): + table_slice = raw_table[x:x+slice_size] + print "%6d" % (len(table_slice) - table_slice.count(None)), \ + "".join(entry and "#" or "_" for entry in table_slice) + def machine(importer): rc = raw(importer.code) rm = rsvp.RSVPMachine(rc)