# HG changeset patch # User Paul Boddie # Date 1298154595 -3600 # Node ID 53332d0be6aca3d4d39a9c4bd13adef33d728381 # Parent 9c6deab845e033e3d5dd7b0be7982be06b340be9 Added __class__ attribute locations to constants and statically generated lists and tuples. Changed the RSVP machine and library to use common definitions for object data offsets and primitive object sizes. Changed the isinstance implementation to make use of changes to the __class__ attribute on classes and instances. diff -r 9c6deab845e0 -r 53332d0be6ac lib/builtins.py --- a/lib/builtins.py Sat Jan 29 21:07:27 2011 +0100 +++ b/lib/builtins.py Sat Feb 19 23:29:55 2011 +0100 @@ -460,15 +460,14 @@ # NOTE: CPython insists on tuples, but any sequence might be considered # NOTE: acceptable. - # NOTE: tuple.__class__ is tuple in micropython! - if cls_or_tuple is not tuple and cls_or_tuple.__class__ is tuple: + if _isinstance(cls_or_tuple, tuple): for cls in cls_or_tuple: - if _isinstance(obj, cls): + if obj.__class__ is cls or _isinstance(obj, cls): return True return False else: - return _isinstance(obj, cls_or_tuple) + return obj.__class__ is cls_or_tuple or _isinstance(obj, cls_or_tuple) def issubclass(obj, cls_or_tuple): pass @@ -610,7 +609,6 @@ # Special implementation functions. def _isinstance(obj, cls): pass - def _print(dest, *args): pass def _printnl(dest, *args): pass diff -r 9c6deab845e0 -r 53332d0be6ac micropython/rsvp.py --- a/micropython/rsvp.py Sat Jan 29 21:07:27 2011 +0100 +++ b/micropython/rsvp.py Sat Feb 19 23:29:55 2011 +0100 @@ -149,19 +149,34 @@ def set_location(self, location, with_builtins): location = RSVPObject.set_location(self, location, with_builtins) - return location + len(self.raw_data()) + + # Include the __class__ attribute in the size. + + return location + 1 + len(self.raw_data()) def as_raw(self, objtable, paramtable, with_builtins): item = self.item - # NOTE: Need class details! + classcode = objtable.as_list().get_code(item.value_type_name()) + attrcode = objtable.get_index(item.value_type_name()) return [ DataObject( - objtable.as_list().get_code(item.value_type_name()), - objtable.get_index(item.value_type_name()), # is instance + classcode, + attrcode, # is instance None, item.value_type_name(), - 1 # size + 3 # size (header plus __class__ plus data) + ), + + # The __class__ attribute for instances. + + DataValue( + PlaceholderContext, + item.location ) + + # NOTE: The RSVP library needs changing if more attributes are added + # NOTE: here. + ] + self.raw_data() def raw_data(self): diff -r 9c6deab845e0 -r 53332d0be6ac micropython/trans.py --- a/micropython/trans.py Sat Jan 29 21:07:27 2011 +0100 +++ b/micropython/trans.py Sat Feb 19 23:29:55 2011 +0100 @@ -1379,9 +1379,15 @@ "Make a tuple using the given program 'node'." - self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes)) + # Reserve space for __class__ plus the elements themselves. + + self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes) + 1) temp = self.get_temp() - self._populateSequence(temp, node) + + # Store using 1-based index values, since __class__ should be at position 0. + + self._populateSequence(temp, node, 1) + self.new_op(temp) self.discard_temp(temp) @@ -1397,7 +1403,9 @@ self.new_op(temp) self.record_value() - self.make_instance(self.get_builtin_class("list", node), 1) + # Reserve space for __class__ plus _elements (the fragment reference). + + self.make_instance(self.get_builtin_class("list", node), 2) list_temp = self.get_temp() self.new_op(list_temp) self.new_op(StoreAttr(Attr(0, None, None))) @@ -1408,7 +1416,7 @@ self.discard_temp(temp) self.discard_temp(list_temp) - def _populateSequence(self, temp, node): + def _populateSequence(self, temp, node, offset=0): """ Populate a sequence using the given 'temp' reference and program 'node'. @@ -1418,7 +1426,7 @@ self.dispatch(n) self.record_value() self.new_op(temp) - self.new_op(StoreAttr(Attr(i, None, None))) + self.new_op(StoreAttr(Attr(i + offset, None, None))) self.set_source() self.discard_value() diff -r 9c6deab845e0 -r 53332d0be6ac rsvp.py --- a/rsvp.py Sat Jan 29 21:07:27 2011 +0100 +++ b/rsvp.py Sat Feb 19 23:29:55 2011 +0100 @@ -298,7 +298,7 @@ value = self.load(attr_location) if value is not None: - content = self.load(value.ref + 1) + content = self.load(value.ref + Library.instance_data_offset) print label, expected, content success = success and (int(expected) == content) else: diff -r 9c6deab845e0 -r 53332d0be6ac rsvplib.py --- a/rsvplib.py Sat Jan 29 21:07:27 2011 +0100 +++ b/rsvplib.py Sat Feb 19 23:29:55 2011 +0100 @@ -26,6 +26,11 @@ "Native function implementations." + # NOTE: These attributes need changing if the instance layout changes. + + instance_data_offset = 2 + instance_size = 3 + def __init__(self, machine, constants): """ @@ -77,22 +82,20 @@ if not (self.machine._CheckInstance(left_value.ref, self.int_class) and self.machine._CheckInstance(right_value.ref, self.int_class)): - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) + self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) return self.machine.RaiseException() - # NOTE: Assume single location for data. - - left_data = left_value.ref + 1 - right_data = right_value.ref + 1 + left_data = left_value.ref + self.instance_data_offset + right_data = right_value.ref + self.instance_data_offset # Make a new object. - addr = self.machine._MakeObject(2, self.int_instance) + addr = self.machine._MakeObject(self.instance_size, self.int_instance) # Store the result. # NOTE: The data is considered ready to use. - self.machine.save(addr + 1, op(self.machine.load(left_data), self.machine.load(right_data))) + self.machine.save(addr + self.instance_data_offset, op(self.machine.load(left_data), self.machine.load(right_data))) # Return the new object. # Introduce object as context for the new object. @@ -118,10 +121,8 @@ self.machine.result = DataValue(notimpl, notimpl) return - # NOTE: Assume single location for data. - - left_data = left_value.ref + 1 - right_data = right_value.ref + 1 + left_data = left_value.ref + self.instance_data_offset + right_data = right_value.ref + self.instance_data_offset # Test the data. # NOTE: The data is considered ready to use. @@ -199,12 +200,10 @@ # Test operand suitability. if not self.machine._CheckInstance(left_value.ref, self.int_class): - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) + self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) return self.machine.RaiseException() - # NOTE: Assume single location for data. - - left_data = left_value.ref + 1 + left_data = left_value.ref + self.instance_data_offset # Test the data. # NOTE: The data is considered ready to use. @@ -224,21 +223,19 @@ # Test operand suitability. if not self.machine._CheckInstance(left_value.ref, self.int_class): - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance) + self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) return self.machine.RaiseException() - # NOTE: Assume single location for data. - - left_data = left_value.ref + 1 + left_data = left_value.ref + self.instance_data_offset # Make a new object. - addr = self.machine._MakeObject(2, self.int_instance) + addr = self.machine._MakeObject(self.instance_size, self.int_instance) # Store the result. # NOTE: The data is considered ready to use. - self.machine.save(addr + 1, -self.machine.load(left_data)) + self.machine.save(addr + self.instance_data_offset, -self.machine.load(left_data)) # Return the new object. # Introduce object as context for the new object. @@ -270,7 +267,7 @@ # Complete the list instance by saving the fragment reference. # NOTE: This requires an attribute in the list structure. - addr = list_value.ref + 1 + addr = list_value.ref + self.instance_data_offset self.machine.save(addr, DataValue(None, new_fragment)) def builtins_list_get_single_item(self): @@ -285,26 +282,25 @@ obj_value = self.frame_stack[frame] # Get the fragment address. - # NOTE: Assume single location for header. - fragment = self.machine.load(obj_value.ref + 1) + fragment = self.machine.load(obj_value.ref + self.instance_data_offset) # Get the fragment header. header = self.machine.load(fragment.ref) nelements = header.occupied_size - 1 - # NOTE: Assume single location for data and header. + # Get the item position. - item_pos = self.machine.load(item_value.ref + 1) + item_pos = self.machine.load(item_value.ref + self.instance_data_offset) if not self._check_index(item_pos, nelements): - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance) + self.machine.exception = self.machine._MakeObject(self.instance_size, self.index_error_instance) return self.machine.RaiseException() - # NOTE: Assume single location for header. + # Get the item itself. - self.machine.result = self.machine.load(fragment.ref + 1 + item_pos) + self.machine.result = self.machine.load(fragment.ref + self.instance_data_offset + item_pos) def builtins_list_len(self): frame = self.local_sp_stack[-1] @@ -314,9 +310,8 @@ obj_value = self.frame_stack[frame] # Get the fragment address. - # NOTE: Assume single location for header. - fragment = self.machine.load(obj_value.ref + 1) + fragment = self.machine.load(obj_value.ref + self.instance_data_offset) # Get the fragment header. @@ -325,12 +320,12 @@ # Make a new object. - addr = self.machine._MakeObject(2, self.int_instance) + addr = self.machine._MakeObject(self.instance_size, self.int_instance) # Store the result. # NOTE: The data is considered ready to use. - self.machine.save(addr + 1, nelements) + self.machine.save(addr + self.instance_data_offset, nelements) # Return the new object. # Introduce object as context for the new object. @@ -349,9 +344,8 @@ obj_value = self.frame_stack[frame] # Get the fragment address. - # NOTE: Assume single location for header. - fragment = self.machine.load(obj_value.ref + 1) + fragment = self.machine.load(obj_value.ref + self.instance_data_offset) # Get the fragment header. @@ -379,7 +373,7 @@ # Set the new fragment in the object. # NOTE: The old fragment could be deallocated. - self.machine.save(obj_value.ref + 1, DataValue(None, new_fragment)) + self.machine.save(obj_value.ref + self.instance_data_offset, DataValue(None, new_fragment)) def builtins_tuple_len(self): frame = self.local_sp_stack[-1] @@ -389,19 +383,18 @@ obj_value = self.frame_stack[frame] # Get the header. - # NOTE: Assume single location for header. header = self.machine.load(obj_value.ref) - nelements = header.size - 1 + nelements = header.size - self.instance_data_offset # Make a new object. - addr = self.machine._MakeObject(2, self.int_instance) + addr = self.machine._MakeObject(self.instance_size, self.int_instance) # Store the result. # NOTE: The data is considered ready to use. - self.machine.save(addr + 1, nelements) + self.machine.save(addr + self.instance_data_offset, nelements) # Return the new object. # Introduce object as context for the new object. @@ -420,22 +413,21 @@ obj_value = self.frame_stack[frame] # Get the header. - # NOTE: Assume single location for header. header = self.machine.load(obj_value.ref) - nelements = header.size - 1 + nelements = header.size - self.instance_data_offset # NOTE: Assume single location for data and header. - item_pos = self.machine.load(item_value.ref + 1) + item_pos = self.machine.load(item_value.ref + self.instance_data_offset) if not self._check_index(item_pos, nelements): - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance) + self.machine.exception = self.machine._MakeObject(self.instance_size, self.index_error_instance) return self.machine.RaiseException() - # NOTE: Assume single location for header. + # Get the item. - self.machine.result = self.machine.load(obj_value.ref + 1 + item_pos) + self.machine.result = self.machine.load(obj_value.ref + self.instance_data_offset + item_pos) def builtins_object_init(self): pass