1.1 --- a/TO_DO.txt Sat Feb 26 01:12:25 2011 +0100
1.2 +++ b/TO_DO.txt Sun Feb 27 02:45:38 2011 +0100
1.3 @@ -2,9 +2,15 @@
1.4 is always defined, no shadowing may occur for the attribute exposing it at different
1.5 levels.
1.6
1.7 - The type class should be exposed as each class's __class__ attribute.
1.8 + The instance definition of __class__ should be stored in the object table.
1.9 +
1.10 + Each common definition for instances of a class shall be stored as the first
1.11 + attribute of each class.
1.12
1.13 - The object-relative definition of __class__ should be stored in the object table.
1.14 + Access to __class__ has to be detected and a special instruction (sequence)
1.15 + generated to handle the class/instance logic.
1.16 +
1.17 + The type class should be exposed as each class's __class__ attribute.
1.18
1.19 Note that object table information will not be able to reflect the class-type
1.20 relationship, but isinstance will need to check for instances and classes, anyway.
2.1 --- a/docs/concepts.txt Sat Feb 26 01:12:25 2011 +0100
2.2 +++ b/docs/concepts.txt Sun Feb 27 02:45:38 2011 +0100
2.3 @@ -192,8 +192,8 @@
2.4 A limitation of this representation is that instance attributes may not shadow
2.5 class attributes: if an attribute with a given name is not defined on an
2.6 instance, an attribute with the same name cannot be provided by the class of
2.7 -the instance or any superclass of the instance's class. The exception to this
2.8 -restriction is the __class__ attribute, as described below.
2.9 +the instance or any superclass of the instance's class. This impacts the
2.10 +provision of the __class__ attribute, as described below.
2.11
2.12 The table can be compacted using a representation known as a displacement
2.13 list (referred to as an object list in this context):
2.14 @@ -236,20 +236,30 @@
2.15 The __class__ Attribute
2.16 -----------------------
2.17
2.18 -The exception to the above general rules about relative locations and absolute
2.19 -addresses involves the __class__ attribute which is defined differently for
2.20 -each class and its instances. Since the table elements can only refer to a
2.21 -single absolute address, thus providing only a single value, such absolute
2.22 -references which are sufficient for most class attributes would not be
2.23 -appropriate for the __class__ attribute. Using a common object-relative
2.24 -location of 0 permits the first attribute to be accessed via an object address
2.25 -regardless of whether a class or instance is involved.
2.26 +In Python 2.x, at least with new-style classes, instances have __class__
2.27 +attributes which indicate the class from which they have been instantiated,
2.28 +whereas classes have __class__ attributes which reference the type class.
2.29 +With the object table, it is not possible to provide absolute addresses which
2.30 +can be used for both classes and instances, since this would result in classes
2.31 +and instances having the same class, and thus the class of a class would be
2.32 +the class itself.
2.33
2.34 -Obviously, this requires both classes and instances to retain an attribute
2.35 -location specifically to hold the value appropriate for each object type,
2.36 -whereas a scheme which omits the __class__ attribute on classes would be able
2.37 -to employ an absolute address in the table and maintain only a single address
2.38 -to refer to the class for all instances.
2.39 +One solution is to use object-relative values in the table so that referencing
2.40 +the __class__ attribute of an instance produces a value which can be combined
2.41 +with an instance's address to yield the address of the attribute, which itself
2.42 +refers to the instance's class, whereas referencing the __class__ attribute of
2.43 +a class produces a similar object-relative value that is combined with the
2.44 +class's address to yield the address of the attribute, which itself refers to
2.45 +the special type class.
2.46 +
2.47 +Obviously, the above solution requires both classes and instances to retain an
2.48 +attribute location specifically to hold the value appropriate for each object
2.49 +type, whereas a scheme which omits the __class__ attribute on classes would be
2.50 +able to employ an absolute address in the table and maintain only a single
2.51 +address to refer to the class for all instances. The only problem with not
2.52 +providing a sensible __class__ attribute entry for classes would be the need
2.53 +for special treatment of __class__ to prevent inappropriate consultation of
2.54 +the table for classes.
2.55
2.56 Comparing Tables as Matrices with Displacement Lists
2.57 ----------------------------------------------------
2.58 @@ -289,11 +299,11 @@
2.59
2.60 Header.................................................... Attributes.................
2.61
2.62 - Identifier Identifier Address Identifier Size Object Object ...
2.63 + Identifier Identifier Address Identifier Size Object ...
2.64
2.65 - 0 1 2 3 4 5 6 7
2.66 - classcode attrcode/ invocation funccode size __class__ attribute ...
2.67 - instance reference reference reference
2.68 + 0 1 2 3 4 5 6
2.69 + classcode attrcode/ invocation funccode size attribute ...
2.70 + instance reference reference
2.71 status
2.72
2.73 Classcode
2.74 @@ -358,41 +368,52 @@
2.75
2.76 Class C:
2.77
2.78 - 0 1 2 3 4 5 6 7
2.79 - classcode (unused) __new__ funccode size class type attribute ...
2.80 - for C reference for reference reference
2.81 + 0 1 2 3 4 5 6
2.82 + classcode (unused) __new__ funccode size attribute ...
2.83 + for C reference for reference
2.84 instantiator
2.85
2.86 Instance of C:
2.87
2.88 - 0 1 2 3 4 5 6 7
2.89 - classcode attrcode C.__call__ funccode size class C attribute ...
2.90 - for C for C reference for reference reference
2.91 + 0 1 2 3 4 5 6
2.92 + classcode attrcode C.__call__ funccode size attribute ...
2.93 + for C for C reference for reference
2.94 (if exists) C.__call__
2.95
2.96 Function f:
2.97
2.98 - 0 1 2 3 4 5 6 7
2.99 - classcode attrcode code funccode size class attribute ...
2.100 - for for reference function (default)
2.101 - function function reference reference
2.102 + 0 1 2 3 4 5 6
2.103 + classcode attrcode code funccode size attribute ...
2.104 + for for reference (default)
2.105 + function function reference
2.106
2.107 Module m:
2.108
2.109 - 0 1 2 3 4 5 6 7
2.110 - classcode attrcode (unused) (unused) (unused) module type attribute ...
2.111 - for m for m reference (global)
2.112 - reference
2.113 + 0 1 2 3 4 5 6
2.114 + classcode attrcode (unused) (unused) (unused) attribute ...
2.115 + for m for m (global)
2.116 + reference
2.117
2.118 The __class__ Attribute
2.119 -----------------------
2.120
2.121 -All objects support the __class__ attribute and this is illustrated above with
2.122 -the first attribute.
2.123 +All objects should support the __class__ attribute, and in most cases this is
2.124 +done using the object table, yielding a common address for all instances of a
2.125 +given class.
2.126 +
2.127 +Function: refers to the function class
2.128 +Instance: refers to the class instantiated to make the object
2.129 +
2.130 +The object table cannot support two definitions simultaneously for both
2.131 +instances and their classes. Consequently, __class__ access on classes must be
2.132 +tested for and a special result returned.
2.133
2.134 Class: refers to the type class (type.__class__ also refers to the type class)
2.135 -Function: refers to the function class
2.136 -Instance: refers to the class instantiated to make the object
2.137 +
2.138 +For convenience, the first attribute of a class will be the common __class__
2.139 +attribute for all its instances. As noted above, direct access to this
2.140 +attribute will not be possible for classes, and a constant result will be
2.141 +returned instead.
2.142
2.143 Lists and Tuples
2.144 ----------------
2.145 @@ -539,8 +560,6 @@
2.146 resulting instance, along with locations for the attributes of the instance.
2.147 Since the instance header contains data common to all instances of a class, a
2.148 template header is copied to the start of the newly reserved memory region.
2.149 -The __class__ attribute is also an essential part of instances, and this is
2.150 -also copied to the new memory region.
2.151
2.152 Register Usage
2.153 ==============
3.1 --- a/lib/builtins.py Sat Feb 26 01:12:25 2011 +0100
3.2 +++ b/lib/builtins.py Sun Feb 27 02:45:38 2011 +0100
3.3 @@ -619,8 +619,8 @@
3.4 function
3.5 AttributeError
3.6 #IndexError
3.7 -NoneType
3.8 -NotImplementedType
3.9 +#NoneType
3.10 +#NotImplementedType
3.11 #StopIteration
3.12 TypeError
3.13
3.14 @@ -628,6 +628,7 @@
3.15 #ellipsis
3.16 #list
3.17 tuple
3.18 +type
3.19 #xrange
3.20
3.21 # vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/micropython/common.py Sat Feb 26 01:12:25 2011 +0100
4.2 +++ b/micropython/common.py Sun Feb 27 02:45:38 2011 +0100
4.3 @@ -114,12 +114,13 @@
4.4
4.5 """
4.6 Given annotations made during the inspection process, return all possible
4.7 - types for a 'node' involved in attribute access, or return None if no
4.8 - annotations are available.
4.9 + type names and indications of static usage for a 'node' involved in
4.10 + attribute access.
4.11 """
4.12
4.13 + target_names = set()
4.14 +
4.15 if hasattr(node, "_attrusers"):
4.16 - target_names = set()
4.17
4.18 # Visit each attribute user.
4.19
4.20 @@ -130,12 +131,9 @@
4.21
4.22 for def_user in user._attrdefs or [user]:
4.23 for target_name, is_static in def_user._attrtypes.get(node._username, []):
4.24 - target_names.add(target_name)
4.25 + target_names.add((target_name, is_static))
4.26
4.27 - return target_names
4.28 -
4.29 - else:
4.30 - return None
4.31 + return target_names
4.32
4.33 def used_by_unit(node):
4.34
5.1 --- a/micropython/data.py Sat Feb 26 01:12:25 2011 +0100
5.2 +++ b/micropython/data.py Sun Feb 27 02:45:38 2011 +0100
5.3 @@ -958,7 +958,7 @@
5.4 as a class or a module.
5.5 """
5.6
5.7 - return isinstance(self.parent, (Class, Module)) and self.name != "__class__"
5.8 + return isinstance(self.parent, (Class, Module))
5.9
5.10 def defines_ambiguous_class(self):
5.11
5.12 @@ -1159,20 +1159,18 @@
5.13 self.local_usage = 0
5.14 self.all_local_usage = 0
5.15
5.16 - # Add __class__ attributes to this class and to instances of it.
5.17 -
5.18 - if self.parent is not None:
5.19 - self.initialise_class_attribute()
5.20 - self.add_instance_attribute("__class__")
5.21 + # Add an attribute to this class for use by instances.
5.22 +
5.23 + self.set("__class__", self)
5.24
5.25 def set_context(self, parent, module, node):
5.26 +
5.27 + "Set the 'parent', 'module' and 'node' of a class created in advance."
5.28 +
5.29 self.parent = parent
5.30 self.module = module
5.31 self.astnode = node
5.32
5.33 - self.initialise_class_attribute()
5.34 - self.add_instance_attribute("__class__")
5.35 -
5.36 def reset_caches(self):
5.37
5.38 "Reset the caches."
5.39 @@ -1398,13 +1396,7 @@
5.40 # instance.
5.41
5.42 for name in self.instattr:
5.43 -
5.44 - # Special case: __class__ has to be at position 0.
5.45 -
5.46 - if name == "__class__":
5.47 - instattr[name] = set([0])
5.48 - else:
5.49 - instattr[name] = set() # position not yet defined
5.50 + instattr[name] = set() # position not yet defined
5.51
5.52 reversed_bases = self.bases[:]
5.53 reversed_bases.reverse()
5.54 @@ -1498,8 +1490,8 @@
5.55 Return all attributes for an instance, indicating either the class which
5.56 provides them or that the instance itself provides them.
5.57
5.58 - Note that __class__ acts like an instance attribute for both instances
5.59 - and classes.
5.60 + Note that __class__ acts like a class attribute for both instances and
5.61 + classes, and must be able to convey distinct values.
5.62 """
5.63
5.64 if self.allattr is None:
5.65 @@ -1515,15 +1507,13 @@
5.66
5.67 "A special class for the type class."
5.68
5.69 - def initialise_class_attribute(self):
5.70 - self.set("__class__", self)
5.71 + pass
5.72
5.73 class CommonClass(Class):
5.74
5.75 "An inspected class."
5.76
5.77 - def initialise_class_attribute(self):
5.78 - self.set("__class__", type_class)
5.79 + pass
5.80
5.81 class Function(NamespaceDict, Naming, Constant):
5.82
6.1 --- a/micropython/inspect.py Sat Feb 26 01:12:25 2011 +0100
6.2 +++ b/micropython/inspect.py Sun Feb 27 02:45:38 2011 +0100
6.3 @@ -453,7 +453,13 @@
6.4 # Get the attribute and record its usage.
6.5
6.6 if isinstance(value, (Class, Module)):
6.7 - attr = value.get(attrname)
6.8 +
6.9 + # Check for class.__class__.
6.10 +
6.11 + if attrname == "__class__" and isinstance(value, Class):
6.12 + attr = type_class
6.13 + else:
6.14 + attr = value.get(attrname)
6.15 self.use_specific_attribute(value.full_name(), attrname)
6.16
6.17 elif isinstance(value, UnresolvedName):
7.1 --- a/micropython/opt.py Sat Feb 26 01:12:25 2011 +0100
7.2 +++ b/micropython/opt.py Sun Feb 27 02:45:38 2011 +0100
7.3 @@ -307,7 +307,7 @@
7.4
7.5 """
7.6 Where the object whose attribute is being accessed is constant, provide
7.7 - information about its full name.
7.8 + information about the object and its full name.
7.9 """
7.10
7.11 if self.should_optimise_constant_accessor() and self.have_constant_input():
7.12 @@ -323,11 +323,11 @@
7.13 if target is None:
7.14 return None # no clearly defined target
7.15 elif isinstance(target, Const):
7.16 - return target.value_type_name()
7.17 + return target, target.value_type_name()
7.18 elif isinstance(target, Instance):
7.19 return None # skip production of optimised code
7.20 else:
7.21 - return target.full_name()
7.22 + return target, target.full_name()
7.23
7.24 else:
7.25 return None
8.1 --- a/micropython/rsvp.py Sat Feb 26 01:12:25 2011 +0100
8.2 +++ b/micropython/rsvp.py Sun Feb 27 02:45:38 2011 +0100
8.3 @@ -85,7 +85,7 @@
8.4
8.5 # Include the instance template and __class__ attribute in the size.
8.6
8.7 - return RSVPObject.set_location(self, location + 2, with_builtins)
8.8 + return RSVPObject.set_location(self, location + 1, with_builtins)
8.9
8.10 def finalise_location(self, with_builtins):
8.11 self._finalise_location(with_builtins)
8.12 @@ -120,17 +120,10 @@
8.13 attrcode, # is instance
8.14 call_method_code_location,
8.15 item.full_name(),
8.16 - len(item.instance_attributes()) + 1, # size
8.17 + len(item.instance_attributes()), # size (excluding __class__)
8.18 call_method_funccode # funccode
8.19 ),
8.20
8.21 - # The __class__ attribute for instances.
8.22 -
8.23 - DataValue(
8.24 - PlaceholderContext,
8.25 - item.location
8.26 - ),
8.27 -
8.28 # Class...
8.29
8.30 DataObject(
8.31 @@ -149,33 +142,19 @@
8.32
8.33 def set_location(self, location, with_builtins):
8.34 location = RSVPObject.set_location(self, location, with_builtins)
8.35 -
8.36 - # Include the __class__ attribute in the size.
8.37 -
8.38 - return location + 1 + len(self.raw_data())
8.39 + return location + len(self.raw_data())
8.40
8.41 def as_raw(self, objtable, paramtable, with_builtins):
8.42 item = self.item
8.43 classcode = objtable.as_list().get_code(item.value_type_name())
8.44 attrcode = objtable.get_index(item.value_type_name())
8.45 - name_parts = item.value_type_name_parts()
8.46 - attr = objtable.access(*name_parts)
8.47 - cls = attr.get_value()
8.48 -
8.49 return [
8.50 DataObject(
8.51 classcode,
8.52 attrcode, # is instance
8.53 None,
8.54 item.value_type_name(),
8.55 - 3 # size (header plus __class__ plus data)
8.56 - ),
8.57 -
8.58 - # The __class__ attribute for instances.
8.59 -
8.60 - DataValue(
8.61 - PlaceholderContext,
8.62 - cls.location
8.63 + 2 # size (header plus data)
8.64 )
8.65
8.66 # NOTE: The RSVP library needs changing if more attributes are added
8.67 @@ -206,27 +185,23 @@
8.68 if not self.is_generated(with_builtins):
8.69 item.code_location = item.full_name()
8.70
8.71 - # Skip __class__ plus any defaults for static functions.
8.72 + # Skip any defaults for static functions.
8.73
8.74 elif not item.is_dynamic():
8.75 - item.code_location = location + 1 + len(item.defaults)
8.76 + item.code_location = location + len(item.defaults)
8.77
8.78 - # Skip __class__ plus any defaults for dynamic functions.
8.79 + # Skip any defaults for dynamic functions.
8.80
8.81 else:
8.82 - item.code_location = location + 1
8.83 + item.code_location = location
8.84
8.85 - # Include the __class__ attribute.
8.86 -
8.87 - return location + 1
8.88 + return location
8.89
8.90 def finalise_location(self, with_builtins):
8.91 self._finalise_location(with_builtins)
8.92
8.93 def as_raw(self, objtable, paramtable, with_builtins):
8.94 item = self.item
8.95 - attr = objtable.access("__builtins__", "function")
8.96 - cls = attr.get_value()
8.97 # NOTE: Need class and parameter details! Should arguably be an instance of types.FunctionType.
8.98 return [
8.99 DataObject(
8.100 @@ -236,13 +211,6 @@
8.101 "__builtins__.function",
8.102 len(item.defaults) + 1, # size (not accurate for lambda functions before instantiation)
8.103 paramtable.as_list().get_code(item.full_name()) # funccode
8.104 - ),
8.105 -
8.106 - # The __class__ attribute for functions.
8.107 -
8.108 - DataValue(
8.109 - PlaceholderContext,
8.110 - cls.location
8.111 )
8.112 ]
8.113
9.1 --- a/micropython/trans.py Sat Feb 26 01:12:25 2011 +0100
9.2 +++ b/micropython/trans.py Sun Feb 27 02:45:38 2011 +0100
9.3 @@ -49,7 +49,7 @@
9.4
9.5 "Make an exception of the given 'name' using 'node'."
9.6
9.7 - # NOTE: Reserving an attribute plus __class__.
9.8 + # NOTE: Reserving an attribute.
9.9
9.10 self.make_instance(self.get_builtin_class(name, node), 1)
9.11
9.12 @@ -415,13 +415,24 @@
9.13 # Where the last operation (defining the attribute owner) yields a
9.14 # constant...
9.15
9.16 - target_name = self.optimiser.optimise_constant_accessor()
9.17 + target_plus_name = self.optimiser.optimise_constant_accessor()
9.18
9.19 # Only try and discover the position if the target can be resolved.
9.20 # Since instances cannot be constants, this involves classes and
9.21 # modules.
9.22 + # It is acceptable to replace the instruction providing the constant
9.23 + # input because doing so does not lose any input information required by
9.24 + # the replacement instructions.
9.25
9.26 - if target_name is not None:
9.27 + if target_plus_name is not None:
9.28 + target, target_name = target_plus_name
9.29 +
9.30 + # Check for class.__class__.
9.31 +
9.32 + if attrname == "__class__":
9.33 + if isinstance(target, Class):
9.34 + self.replace_active_value(LoadAddress(self.get_builtin("type", node)))
9.35 + return
9.36
9.37 # Access the object table to get the attribute.
9.38
9.39 @@ -432,10 +443,8 @@
9.40
9.41 # Produce a suitable instruction.
9.42
9.43 - if attr.is_static_attribute() and AddressInstruction is not None:
9.44 + if AddressInstruction is not None:
9.45 self.replace_active_value(AddressInstruction(attr))
9.46 - elif not attr.is_static_attribute() and AttrInstruction is not None:
9.47 - self.replace_active_value(AttrInstruction(attr))
9.48 else:
9.49 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname)
9.50
9.51 @@ -517,7 +526,14 @@
9.52 target_names = self.possible_accessor_types(node)
9.53
9.54 if target_names is not None and len(target_names) == 1:
9.55 - target_name = list(target_names)[0]
9.56 + target_name, is_static = list(target_names)[0]
9.57 +
9.58 + # Check for class.__class__.
9.59 +
9.60 + if attrname == "__class__":
9.61 + if is_static:
9.62 + self.load_builtin("type", node)
9.63 + return
9.64
9.65 # Access the object table to get the attribute.
9.66
9.67 @@ -541,6 +557,27 @@
9.68
9.69 return
9.70
9.71 + # Check for class.__class__.
9.72 +
9.73 + if attrname == "__class__":
9.74 +
9.75 + # Remember the accessor.
9.76 +
9.77 + temp_accessor = self.optimiser.optimise_temp_storage()
9.78 +
9.79 + attr_block = self.new_block()
9.80 + end_block = self.new_block()
9.81 +
9.82 + self.new_op(CheckClass())
9.83 + self.new_op(JumpIfFalse(attr_block))
9.84 + self.load_builtin("type", node)
9.85 + self.new_op(Jump(end_block))
9.86 + self.set_block(attr_block)
9.87 +
9.88 + # Recall the accessor.
9.89 +
9.90 + self.new_op(temp_accessor)
9.91 +
9.92 # Otherwise, perform a normal operation.
9.93
9.94 try:
9.95 @@ -564,6 +601,11 @@
9.96 else:
9.97 self.new_op(AttrIndexInstruction(index))
9.98
9.99 + # Where __class__ was involved, define the start of the following code.
9.100 +
9.101 + if attrname == "__class__":
9.102 + self.set_block(end_block)
9.103 +
9.104 # Invocations involve the following:
9.105 #
9.106 # 1. Reservation of a frame for the arguments
9.107 @@ -1385,14 +1427,14 @@
9.108
9.109 "Make a tuple using the given program 'node'."
9.110
9.111 - # Reserve space for __class__ plus the elements themselves.
9.112 + # Reserve space for the elements themselves.
9.113
9.114 - self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes) + 1)
9.115 + self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes))
9.116 temp = self.get_temp()
9.117
9.118 - # Store using 1-based index values, since __class__ should be at position 0.
9.119 + # Store using 0-based index values.
9.120
9.121 - self._populateSequence(temp, node, 1)
9.122 + self._populateSequence(temp, node)
9.123
9.124 self.new_op(temp)
9.125 self.discard_temp(temp)
9.126 @@ -1409,12 +1451,12 @@
9.127 self.new_op(temp)
9.128 self.record_value()
9.129
9.130 - # Reserve space for __class__ plus _elements (the fragment reference).
9.131 + # Reserve space for _elements (the fragment reference).
9.132
9.133 - self.make_instance(self.get_builtin_class("list", node), 2)
9.134 + self.make_instance(self.get_builtin_class("list", node), 1)
9.135 list_temp = self.get_temp()
9.136 self.new_op(list_temp)
9.137 - self.new_op(StoreAttr(Attr(1, None, None)))
9.138 + self.new_op(StoreAttr(Attr(0, None, None))) # _elements is at position 0
9.139 self.set_source()
9.140 self.discard_value()
9.141
10.1 --- a/rsvp.py Sat Feb 26 01:12:25 2011 +0100
10.2 +++ b/rsvp.py Sun Feb 27 02:45:38 2011 +0100
10.3 @@ -158,7 +158,15 @@
10.4 def dump(self):
10.5 print "PC", self.pc, "->", self.load(self.pc)
10.6 print "PC stack", self.pc_stack
10.7 - print "Frame stack", self.frame_stack
10.8 + print "Frame stack:"
10.9 + if self.local_sp_stack:
10.10 + start = self.local_sp_stack[0]
10.11 + for end in self.local_sp_stack[1:]:
10.12 + print " %2d" % start, self.frame_stack[start:end]
10.13 + start = end
10.14 + else:
10.15 + print " %2d" % start, self.frame_stack[start:]
10.16 + print
10.17 print "Local stack pointers", self.local_sp_stack
10.18 print "Invocation stack pointers", self.invocation_sp_stack
10.19 print "Handler stack", self.handler_stack
10.20 @@ -206,12 +214,8 @@
10.21
10.22 def up(self):
10.23 retaddr = self.pc_stack[-1]
10.24 - new_breakpoint = retaddr not in self.breakpoints
10.25 - if new_breakpoint:
10.26 - self.set_break(retaddr)
10.27 + self.set_break(retaddr)
10.28 self.run()
10.29 - if new_breakpoint:
10.30 - self.breakpoints.remove(retaddr)
10.31
10.32 # Internal operations.
10.33
10.34 @@ -469,7 +473,7 @@
10.35 size = self.operand
10.36 value = self.value
10.37 # NOTE: Referencing the instance template.
10.38 - addr = self._MakeObject(size, value.ref - 2)
10.39 + addr = self._MakeObject(size, value.ref - Library.instance_template_size)
10.40 # Introduce object as context for the new object.
10.41 self.value = DataValue(addr, addr)
10.42
10.43 @@ -752,7 +756,7 @@
10.44
10.45 def RaiseException(self):
10.46 # NOTE: Adding the program counter as the first attribute after __class__.
10.47 - self.save(self.exception + 2, self.pc)
10.48 + self.save(self.exception + Library.instance_data_offset, self.pc)
10.49 # Jumping to the current handler.
10.50 if self.abort_upon_exception:
10.51 raise Exception
10.52 @@ -843,9 +847,6 @@
10.53 addr = self.new(size)
10.54 # Save the header, overriding the size.
10.55 self.save(addr, data.with_size(size))
10.56 - # Copy the __class__ attribute.
10.57 - cls_attr = self.load(ref + 1)
10.58 - self.save(addr + 1, cls_attr)
10.59 return addr
10.60
10.61 def _MakeFragment(self, occupied, size):
11.1 --- a/rsvplib.py Sat Feb 26 01:12:25 2011 +0100
11.2 +++ b/rsvplib.py Sun Feb 27 02:45:38 2011 +0100
11.3 @@ -3,7 +3,7 @@
11.4 """
11.5 A native function library for a really simple virtual processor.
11.6
11.7 -Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk>
11.8 +Copyright (C) 2007, 2008, 2009, 2010, 2011 Paul Boddie <paul@boddie.org.uk>
11.9
11.10 This program is free software; you can redistribute it and/or modify it under
11.11 the terms of the GNU General Public License as published by the Free Software
11.12 @@ -28,8 +28,8 @@
11.13
11.14 # NOTE: These attributes need changing if the instance layout changes.
11.15
11.16 - instance_data_offset = 2
11.17 - instance_size = 3
11.18 + instance_template_size = instance_data_offset = 1
11.19 + instance_size = instance_template_size + 1
11.20
11.21 def __init__(self, machine, constants):
11.22
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/tests/class_class_attr_indirect.py Sun Feb 27 02:45:38 2011 +0100
12.3 @@ -0,0 +1,20 @@
12.4 +#!/usr/bin/env python
12.5 +
12.6 +class A:
12.7 + pass
12.8 +
12.9 +class B(A):
12.10 + pass
12.11 +
12.12 +class C:
12.13 + pass
12.14 +
12.15 +a = A.__class__
12.16 +b = B.__class__
12.17 +c = C.__class__
12.18 +
12.19 +result_1 = a is type and 1 or 0
12.20 +result_2 = b is type and 2 or 0
12.21 +result_3 = c is type and 3 or 0
12.22 +
12.23 +# vim: tabstop=4 expandtab shiftwidth=4