1.1 --- a/docs/structures.txt Mon Jan 26 01:25:30 2009 +0100
1.2 +++ b/docs/structures.txt Mon Feb 02 01:34:35 2009 +0100
1.3 @@ -197,7 +197,10 @@
1.4 return instance
1.5
1.6 If C has a __call__ attribute, the invocation "slot" of C instances would
1.7 -refer to the same thing as C.__call__.
1.8 +refer to the same thing as C.__call__. This "slot" has to be prepared when
1.9 +creating instances, potentially using a template instance or by modifying the
1.10 +sequence of instructions used in, amongst other places, the instantiator
1.11 +function.
1.12
1.13 For functions, the same general layout applies:
1.14
2.1 --- a/micropython/__init__.py Mon Jan 26 01:25:30 2009 +0100
2.2 +++ b/micropython/__init__.py Mon Feb 02 01:34:35 2009 +0100
2.3 @@ -257,28 +257,34 @@
2.4 instantiator_code_location = item.get_instantiator().blocks[0].location
2.5
2.6 # NOTE: Need initialiser details!
2.7 - self.raw_code.append((
2.8 - objtable.as_list().get_code(item.full_name()),
2.9 - objtable.get_index(item.full_name()),
2.10 - instantiator_code_location,
2.11 - (
2.12 - len(item.get_instantiator().positional_names),
2.13 - len(item.get_instantiator().defaults)
2.14 - ),
2.15 - 0
2.16 - ))
2.17 + self.raw_code.append(
2.18 + DataObject(
2.19 + objtable.as_list().get_code(item.full_name()),
2.20 + objtable.get_index(item.full_name()),
2.21 + instantiator_code_location,
2.22 + (
2.23 + len(item.get_instantiator().positional_names),
2.24 + len(item.get_instantiator().defaults)
2.25 + ),
2.26 + 0,
2.27 + item.full_name()
2.28 + )
2.29 + )
2.30
2.31 elif isinstance(item, micropython.data.Const):
2.32 assert item.location == len(self.raw_code)
2.33
2.34 # NOTE: Need class details!
2.35 - self.raw_code.append((
2.36 - objtable.as_list().get_code(item.value_type_name()),
2.37 - objtable.get_index(item.value_type_name()),
2.38 - None,
2.39 - None,
2.40 - 1
2.41 - ))
2.42 + self.raw_code.append(
2.43 + DataObject(
2.44 + objtable.as_list().get_code(item.value_type_name()),
2.45 + objtable.get_index(item.value_type_name()),
2.46 + None,
2.47 + None,
2.48 + 1,
2.49 + item.value_type_name()
2.50 + )
2.51 + )
2.52
2.53 self.raw_code += self.raw_data(item)
2.54
2.55 @@ -286,16 +292,19 @@
2.56 assert item.location == len(self.raw_code)
2.57
2.58 # NOTE: Need class and parameter details! Should arguably be types.FunctionType.
2.59 - self.raw_code.append((
2.60 - objtable.as_list().get_code("__builtins__.function"),
2.61 - objtable.get_index("__builtins__.function"),
2.62 - item.code_location,
2.63 - (
2.64 - len(item.positional_names),
2.65 - len(item.defaults)
2.66 - ),
2.67 - 0
2.68 - ))
2.69 + self.raw_code.append(
2.70 + DataObject(
2.71 + objtable.as_list().get_code("__builtins__.function"),
2.72 + objtable.get_index("__builtins__.function"),
2.73 + item.code_location,
2.74 + (
2.75 + len(item.positional_names),
2.76 + len(item.defaults)
2.77 + ),
2.78 + 0,
2.79 + "__builtins__.function"
2.80 + )
2.81 + )
2.82
2.83 # Check the code location only where the code has been generated.
2.84
2.85 @@ -305,13 +314,16 @@
2.86 elif isinstance(item, micropython.data.Module):
2.87 assert item.location == len(self.raw_code)
2.88
2.89 - self.raw_code.append((
2.90 - objtable.as_list().get_code(item.full_name()),
2.91 - None, # module name not used as an attribute
2.92 - None,
2.93 - None,
2.94 - 0
2.95 - ))
2.96 + self.raw_code.append(
2.97 + DataObject(
2.98 + objtable.as_list().get_code(item.full_name()),
2.99 + None, # module name not used as an attribute
2.100 + None,
2.101 + None,
2.102 + 0,
2.103 + item.full_name()
2.104 + )
2.105 + )
2.106
2.107 else:
2.108 self.raw_code.append(item)
2.109 @@ -458,7 +470,7 @@
2.110 # Name records (used to track actual use of names).
2.111 # Include names which may not be explicitly used in programs.
2.112
2.113 - self.names_used = set(["__init__"])
2.114 + self.names_used = set(["__init__", "__call__"])
2.115
2.116 # Status information.
2.117
3.1 --- a/micropython/ast.py Mon Jan 26 01:25:30 2009 +0100
3.2 +++ b/micropython/ast.py Mon Feb 02 01:34:35 2009 +0100
3.3 @@ -197,9 +197,11 @@
3.4 Request a new object with the given class 'cls' and with 'n' attributes.
3.5 """
3.6
3.7 + self.new_op(LoadConst(cls))
3.8 +
3.9 + # NOTE: Provide __call__ details, if any.
3.10 # NOTE: Object headers are one location.
3.11
3.12 - self.new_op(LoadConst(cls))
3.13 self.new_op(MakeObject(n + 1))
3.14
3.15 # Name-related methods.
3.16 @@ -517,36 +519,45 @@
3.17 try:
3.18 attr = self.unit.parent.instance_attributes()[attrname]
3.19 self.new_op(AttrInstruction(attr))
3.20 + return
3.21
3.22 # Or generate an instruction operating on a class attribute.
3.23
3.24 except KeyError:
3.25 - attr = self.unit.parent.all_attributes()[attrname]
3.26 -
3.27 - # Switch the context if the class attribute is compatible with
3.28 - # the instance.
3.29 -
3.30 - if attr.defined_within_hierarchy():
3.31 -
3.32 - # Only permit loading (not storing) of class attributes via self.
3.33 -
3.34 - if AddressContextInstruction is not None:
3.35 - self.new_op(AddressContextInstruction(attr))
3.36 +
3.37 + try:
3.38 + attr = self.unit.parent.all_attributes()[attrname]
3.39 +
3.40 + # Switch the context if the class attribute is compatible with
3.41 + # the instance.
3.42 +
3.43 + if attr.defined_within_hierarchy():
3.44 +
3.45 + # Only permit loading (not storing) of class attributes via self.
3.46 +
3.47 + if AddressContextInstruction is not None:
3.48 + self.new_op(AddressContextInstruction(attr))
3.49 + else:
3.50 + raise TranslateError(self.module.full_name(), node,
3.51 + "Storing of class attribute %r via self not permitted." % attrname)
3.52 +
3.53 + # Preserve the context if the class attribute comes from an
3.54 + # incompatible class.
3.55 +
3.56 else:
3.57 - raise TranslateError(self.module.full_name(), node,
3.58 - "Storing of class attribute %r via self not permitted." % attrname)
3.59 -
3.60 - # Preserve the context if the class attribute comes from an
3.61 - # incompatible class.
3.62 -
3.63 - else:
3.64 - if AddressInstruction is not None:
3.65 - self.new_op(AddressInstruction(attr))
3.66 - else:
3.67 - raise TranslateError(self.module.full_name(), node,
3.68 - "Storing of class attribute %r via self not permitted." % attrname)
3.69 -
3.70 - return
3.71 + if AddressInstruction is not None:
3.72 + self.new_op(AddressInstruction(attr))
3.73 + else:
3.74 + raise TranslateError(self.module.full_name(), node,
3.75 + "Storing of class attribute %r via self not permitted." % attrname)
3.76 +
3.77 + return
3.78 +
3.79 + # Or delegate the attribute access to a general instruction
3.80 + # since the kind of attribute cannot be deduced.
3.81 +
3.82 + except KeyError:
3.83 + pass
3.84
3.85 # Otherwise, perform a normal operation.
3.86
4.1 --- a/micropython/common.py Mon Jan 26 01:25:30 2009 +0100
4.2 +++ b/micropython/common.py Mon Feb 02 01:34:35 2009 +0100
4.3 @@ -84,6 +84,23 @@
4.4 def __repr__(self):
4.5 return "Block(%r, location=%r)" % (id(self), self.location)
4.6
4.7 +# Program data representations.
4.8 +
4.9 +class DataObject:
4.10 +
4.11 + "A representation of a raw program data object."
4.12 +
4.13 + def __init__(self, classcode, attrcode, codeaddr, codedetails, instance, name):
4.14 + self.classcode = classcode
4.15 + self.attrcode = attrcode
4.16 + self.codeaddr = codeaddr
4.17 + self.codedetails = codedetails
4.18 + self.instance = instance
4.19 + self.name = name
4.20 +
4.21 + def __repr__(self):
4.22 + return "%r # %s" % ((self.classcode, self.attrcode, self.codeaddr, self.codedetails, self.instance), self.name)
4.23 +
4.24 # Inspection representations.
4.25
4.26 class AtLeast:
5.1 --- a/rsvp.py Mon Jan 26 01:25:30 2009 +0100
5.2 +++ b/rsvp.py Mon Feb 02 01:34:35 2009 +0100
5.3 @@ -52,6 +52,8 @@
5.4 current callable
5.5 """
5.6
5.7 +from micropython.common import DataObject # for creating "nice" new objects
5.8 +
5.9 class IllegalInstruction(Exception):
5.10 pass
5.11
5.12 @@ -114,7 +116,8 @@
5.13
5.14 # Native class constants.
5.15
5.16 - self.int_class = objlist.access("__builtins__", "int").value.location
5.17 + cls = objlist.access("__builtins__", "int")
5.18 + self.int_class = cls and cls.value.location
5.19
5.20 # Debugging methods.
5.21
5.22 @@ -342,8 +345,8 @@
5.23
5.24 def LoadAttrIndex(self):
5.25 context, ref = self.value
5.26 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.27 - element = self.objlist[classcode + self.operand]
5.28 + data = self.load(ref)
5.29 + element = self.objlist[data.classcode + self.operand]
5.30 attr_index, class_attr, replace_context, offset = element
5.31 if attr_index == self.operand:
5.32 if class_attr:
5.33 @@ -359,8 +362,8 @@
5.34
5.35 def StoreAttrIndex(self):
5.36 context, ref = self.value
5.37 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.38 - element = self.objlist[classcode + self.operand]
5.39 + data = self.load(ref)
5.40 + element = self.objlist[data.classcode + self.operand]
5.41 attr_index, class_attr, replace_context, offset = element
5.42 if attr_index == self.operand:
5.43 if class_attr:
5.44 @@ -390,8 +393,8 @@
5.45
5.46 def StoreFrameIndex(self):
5.47 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
5.48 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.49 - element = self.objlist[classcode + self.operand]
5.50 + data = self.load(ref)
5.51 + element = self.objlist[data.classcode + self.operand]
5.52 attr_index, offset = element
5.53 if attr_index == self.operand:
5.54 self.frame_stack[frame + offset] = self.value
5.55 @@ -400,14 +403,14 @@
5.56
5.57 def LoadCallable(self):
5.58 context, ref = self.value
5.59 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.60 - self.callable = codeaddr, codedetails
5.61 + data = self.load(ref)
5.62 + self.callable = data.codeaddr, data.codedetails
5.63
5.64 def StoreCallable(self):
5.65 context, ref = self.value
5.66 # NOTE: Should improve the representation and permit direct saving.
5.67 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.68 - self.save(ref, (classcode, attrcode) + self.callable + (instance,))
5.69 + data = self.load(ref)
5.70 + self.save(ref, (data.classcode, data.attrcode) + self.callable + (data.instance,))
5.71
5.72 def LoadContext(self):
5.73 context, ref = self.value
5.74 @@ -417,7 +420,7 @@
5.75 operand = self.operand
5.76 frame = self.invocation_sp_stack[-1]
5.77 context, ref = self.value
5.78 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.79 + data = self.load(ref)
5.80
5.81 # Support sliding of the frame to exclude any inappropriate context.
5.82
5.83 @@ -425,12 +428,12 @@
5.84 self.invocation_sp_stack[-1] += 1
5.85 operand -= 1
5.86 else:
5.87 - context_classcode, context_attrcode, context_codeaddr, context_codedetails, context_instance = self.load(context)
5.88 - if not context_instance:
5.89 + context_data = self.load(context)
5.90 + if not context_data.instance:
5.91 self.invocation_sp_stack[-1] += 1
5.92 operand -= 1
5.93
5.94 - nargs, ndefaults = codedetails
5.95 + nargs, ndefaults = data.codedetails
5.96 if not (nargs - ndefaults <= operand <= nargs):
5.97 raise Exception, "CheckFrame %r" % (nargs - ndefaults, self.operand, nargs)
5.98
5.99 @@ -519,20 +522,20 @@
5.100 # Common implementation details.
5.101
5.102 def _CheckInstance(self, ref, cls):
5.103 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.104 - target_classcode, target_attrcode, target_codeaddr, target_codedetails, target_instance = self.load(cls)
5.105 + data = self.load(ref)
5.106 + target_data = self.load(cls)
5.107
5.108 # Find the table entry for the descendant.
5.109
5.110 - element = self.objlist[target_classcode + attrcode]
5.111 + element = self.objlist[target_data.classcode + data.attrcode]
5.112 attr_index, class_attr, replace_context, offset = element
5.113 - return attr_index == attrcode
5.114 + return attr_index == data.attrcode
5.115
5.116 def _MakeObject(self, size, ref):
5.117 - classcode, attrcode, codeaddr, codedetails, instance = self.load(ref)
5.118 + data = self.load(ref)
5.119 addr = self.new(size)
5.120 # Set the header to resemble the class.
5.121 - self.save(addr, (classcode, attrcode, None, None, 1)) # NOTE: __call__ method not yet provided.
5.122 + self.save(addr, DataObject(data.classcode, data.attrcode, None, None, 1, data.name)) # NOTE: __call__ method not yet provided.
5.123 return addr
5.124
5.125 # Native function implementations.
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/tests/call_instance.py Mon Feb 02 01:34:35 2009 +0100
6.3 @@ -0,0 +1,10 @@
6.4 +#!/usr/bin/env python
6.5 +
6.6 +class C:
6.7 + def __call__(self):
6.8 + return "called"
6.9 +
6.10 +c = C()
6.11 +c()
6.12 +
6.13 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/tests/mixins.py Mon Feb 02 01:34:35 2009 +0100
7.3 @@ -0,0 +1,20 @@
7.4 +#!/usr/bin/env python
7.5 +
7.6 +class A:
7.7 + def a(self):
7.8 + return self.x
7.9 +
7.10 +class B(A):
7.11 + x = 123
7.12 +
7.13 +class C(A):
7.14 + def __init__(self, x):
7.15 + self.x = x
7.16 +
7.17 +b = B()
7.18 +c = C(456)
7.19 +
7.20 +p = b.a()
7.21 +q = c.a()
7.22 +
7.23 +# vim: tabstop=4 expandtab shiftwidth=4