1.1 --- a/docs/invocation.txt Fri May 29 00:18:40 2009 +0200
1.2 +++ b/docs/invocation.txt Sat May 30 20:27:20 2009 +0200
1.3 @@ -129,14 +129,18 @@
1.4 f(obj, 1, 2) # f not known at compile-time
1.5
1.6 f -> C.__new__ (known and called at run-time)
1.7 + -> load context for argument #1
1.8 + obj -> argument #2
1.9 + 1 -> argument #3
1.10 + 2 -> argument #4
1.11
1.12 Need to call C.__init__(<instance>, obj, 1, 2), preferably with the existing
1.13 frame:
1.14
1.15 - <insert instance before received arguments>
1.16 - obj -> argument #1
1.17 - 1 -> argument #2
1.18 - 2 -> argument #3
1.19 + *** -> instance overwrites argument #1
1.20 + obj -> argument #2
1.21 + 1 -> argument #3
1.22 + 2 -> argument #4
1.23
1.24 Then jump without switching frames.
1.25 It should be possible to replace the old, tentative context information in the
2.1 --- a/micropython/ast.py Fri May 29 00:18:40 2009 +0200
2.2 +++ b/micropython/ast.py Sat May 30 20:27:20 2009 +0200
2.3 @@ -168,33 +168,21 @@
2.4
2.5 init_method = cls.get_init_method()
2.6
2.7 - # Fix the current frame to include a new storage slot at the beginning.
2.8 -
2.9 - self.new_op(AdjustFrame(-1))
2.10 -
2.11 - # Convert this frame back to being an invocation frame.
2.12 -
2.13 - self.new_op(RecoverFrame())
2.14 -
2.15 - # Make an object.
2.16 + # Make an object and store it in the unused first slot.
2.17
2.18 self.make_object(cls, len(cls.instance_attributes()))
2.19 - self.new_op(StoreFrame(0))
2.20 + self.new_op(StoreTemp(0))
2.21
2.22 # Invoke the appropriate initialiser.
2.23
2.24 self.new_op(LoadFunction(init_method))
2.25 self.new_op(LoadCallable())
2.26 - self.new_op(JumpWithFrame())
2.27 + self.new_op(JumpInFrame())
2.28
2.29 # Store the object as the result.
2.30
2.31 - self.new_op(LoadName(init_method.all_locals()["self"])) # load the context in the invocation frame
2.32 + self.new_op(LoadTemp(0)) # load the context from the locals
2.33 self.new_op(StoreResult())
2.34 -
2.35 - # Fix the current frame to release the storage slot at the beginning.
2.36 -
2.37 - self.new_op(AdjustFrame(1))
2.38 self.new_op(Return())
2.39
2.40 self.unit.blocks = self.blocks
3.1 --- a/micropython/data.py Fri May 29 00:18:40 2009 +0200
3.2 +++ b/micropython/data.py Sat May 30 20:27:20 2009 +0200
3.3 @@ -1081,9 +1081,9 @@
3.4
3.5 def as_instantiator(self):
3.6
3.7 - "Make an instantiator function from a method."
3.8 + "Make an instantiator function from a method, keeping all arguments."
3.9
3.10 - function = Function(self.parent.name, self.parent.parent, self.argnames[1:], self.defaults,
3.11 + function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults,
3.12 self.has_star, self.has_dstar, self.module, self.astnode)
3.13 function.default_attrs = self.default_attrs
3.14 return function
4.1 --- a/micropython/rsvp.py Fri May 29 00:18:40 2009 +0200
4.2 +++ b/micropython/rsvp.py Sat May 30 20:27:20 2009 +0200
4.3 @@ -195,7 +195,6 @@
4.4
4.5 class MakeFrame(Immediate): "Make a new invocation frame."
4.6 class DropFrame(Instruction): "Drop an invocation frame."
4.7 -class RecoverFrame(Instruction): "Recover the current frame as an invocation frame."
4.8 class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position."
4.9 class StoreFrameIndex(Immediate): "Store the source value as an argument of the current value for the parameter with the given index."
4.10 class LoadContext(Instruction): "Load the context of an invocation."
4.11 @@ -211,6 +210,7 @@
4.12
4.13 # Invocation-related instructions, using a special result "register".
4.14
4.15 +class JumpInFrame(Instruction): "Jump, using the current locals, to the current callable."
4.16 class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the current callable."
4.17 class JumpWithFrameDirect(Target): "Jump to the specified address, adopting the invocation frame."
4.18 class ExtendFrame(Immediate): "Extend the current frame for temporary storage use."
5.1 --- a/micropython/trans.py Fri May 29 00:18:40 2009 +0200
5.2 +++ b/micropython/trans.py Sat May 30 20:27:20 2009 +0200
5.3 @@ -557,9 +557,12 @@
5.4
5.5 # Handle calls to classes.
5.6 # The resulting target must match that used in the actual invocation.
5.7 + # A context is reserved for the new instance, but this is not provided
5.8 + # in the invocation (since the instantiator will fill the locals slot
5.9 + # concerned).
5.10
5.11 elif isinstance(target, Class):
5.12 - ncontext = 0
5.13 + ncontext = 1
5.14 expect_context = 0
5.15 target = target.get_instantiator()
5.16
6.1 --- a/rsvp.py Fri May 29 00:18:40 2009 +0200
6.2 +++ b/rsvp.py Sat May 30 20:27:20 2009 +0200
6.3 @@ -395,7 +395,7 @@
6.4
6.5 def StoreName(self):
6.6 frame = self.local_sp_stack[-1]
6.7 - self.frame_stack[frame + self.operand] = self.source
6.8 + self.frame_stack[frame + self.operand] = self.source # uses the source value
6.9
6.10 LoadTemp = LoadName
6.11
6.12 @@ -511,9 +511,6 @@
6.13 frame = self.invocation_sp_stack.pop()
6.14 self.frame_stack = self.frame_stack[:frame] # reset stack before call
6.15
6.16 - def RecoverFrame(self):
6.17 - self.invocation_sp_stack[-1] = self.local_sp_stack.pop()
6.18 -
6.19 def StoreFrame(self):
6.20 frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame
6.21 self.frame_stack[frame + self.operand] = self.value
6.22 @@ -607,6 +604,10 @@
6.23
6.24 self.status = self._CheckInstance(ref, target_context)
6.25
6.26 + def JumpInFrame(self):
6.27 + codeaddr = self.callable
6.28 + return self.jump(codeaddr, self.pc + 1) # return to the instruction after this one
6.29 +
6.30 def JumpWithFrame(self):
6.31 codeaddr = self.callable
6.32 self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
6.33 @@ -714,10 +715,9 @@
6.34 return addr
6.35
6.36 def _LoadAddressContextCond(self, context, ref, inst_ref):
6.37 -
6.38 # Check the instance context against the target's context.
6.39 -
6.40 - if self._CheckInstance(inst_ref, context):
6.41 + # This provides the context overriding for methods.
6.42 + if context is not None and self._CheckInstance(inst_ref, context):
6.43 # Replace the context with the instance.
6.44 return inst_ref, ref
6.45 else:
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/tests/attributes_instance_bind_method.py Sat May 30 20:27:20 2009 +0200
7.3 @@ -0,0 +1,32 @@
7.4 +#!/usr/bin/env python
7.5 +
7.6 +class B:
7.7 + def __init__(self, y):
7.8 + self.y = y
7.9 + def m(self, x):
7.10 + return x
7.11 +
7.12 +class A:
7.13 + c1 = B
7.14 + m1 = B.m
7.15 + def __init__(self, b):
7.16 + self.c2 = B
7.17 + self.m2 = B.m
7.18 + self.c3 = b
7.19 + self.m3 = b.m
7.20 +
7.21 +b = B(789)
7.22 +a = A(b)
7.23 +result_123 = A.m1(b, 123) # A.m1 is unbound
7.24 +result_234 = a.m1(b, 234) # a.m1 is unbound
7.25 +result_345 = a.m2(b, 345) # a.m2 is unbound
7.26 +result_456 = a.m3(456) # a.m3 is bound to b
7.27 +
7.28 +b1 = A.c1(678) # A.c1 is just a reference to B
7.29 +result_678 = b1.y
7.30 +b2 = a.c1(567) # a.c1 is just a reference to B
7.31 +result_567 = b2.y
7.32 +b3 = a.c2(765) # a.c2 is just a reference to B
7.33 +result_765 = b3.y
7.34 +
7.35 +# vim: tabstop=4 expandtab shiftwidth=4
8.1 --- a/tests/call_method.py Fri May 29 00:18:40 2009 +0200
8.2 +++ b/tests/call_method.py Sat May 30 20:27:20 2009 +0200
8.3 @@ -5,5 +5,6 @@
8.4 self.x = x
8.5
8.6 c = C(123)
8.7 +result_123 = c.x
8.8
8.9 # vim: tabstop=4 expandtab shiftwidth=4
9.1 --- a/tests/call_method_ref.py Fri May 29 00:18:40 2009 +0200
9.2 +++ b/tests/call_method_ref.py Sat May 30 20:27:20 2009 +0200
9.3 @@ -10,5 +10,8 @@
9.4
9.5 f = c.f
9.6 f(1, 2, 3)
9.7 +result_1 = c.a
9.8 +result_2 = c.b
9.9 +result_3 = c.c
9.10
9.11 # vim: tabstop=4 expandtab shiftwidth=4
10.1 --- a/tests/call_method_ref_internal.py Fri May 29 00:18:40 2009 +0200
10.2 +++ b/tests/call_method_ref_internal.py Sat May 30 20:27:20 2009 +0200
10.3 @@ -12,5 +12,8 @@
10.4
10.5 c = C()
10.6 c.f(1, 2, 3)
10.7 +result_1 = c.a
10.8 +result_2 = c.b
10.9 +result_3 = c.c
10.10
10.11 # vim: tabstop=4 expandtab shiftwidth=4
11.1 --- a/tests/call_method_self.py Fri May 29 00:18:40 2009 +0200
11.2 +++ b/tests/call_method_self.py Sat May 30 20:27:20 2009 +0200
11.3 @@ -11,5 +11,8 @@
11.4
11.5 c = C()
11.6 c.f(1, 2, 3)
11.7 +result_1 = c.a
11.8 +result_2 = c.b
11.9 +result_3 = c.c
11.10
11.11 # vim: tabstop=4 expandtab shiftwidth=4
12.1 --- a/tests/call_method_via_class.py Fri May 29 00:18:40 2009 +0200
12.2 +++ b/tests/call_method_via_class.py Sat May 30 20:27:20 2009 +0200
12.3 @@ -10,5 +10,8 @@
12.4
12.5 f = C.f
12.6 f(c, 1, 2, 3) # test self argument
12.7 +result_1 = c.a
12.8 +result_2 = c.b
12.9 +result_3 = c.c
12.10
12.11 # vim: tabstop=4 expandtab shiftwidth=4
13.1 --- a/tests/call_method_via_class_internal.py Fri May 29 00:18:40 2009 +0200
13.2 +++ b/tests/call_method_via_class_internal.py Sat May 30 20:27:20 2009 +0200
13.3 @@ -11,5 +11,8 @@
13.4
13.5 c = C()
13.6 c.f(1, 2, 3)
13.7 +result_1 = c.a
13.8 +result_2 = c.b
13.9 +result_3 = c.c
13.10
13.11 # vim: tabstop=4 expandtab shiftwidth=4
14.1 --- a/tests/class_init_defaults.py Fri May 29 00:18:40 2009 +0200
14.2 +++ b/tests/class_init_defaults.py Sat May 30 20:27:20 2009 +0200
14.3 @@ -7,5 +7,8 @@
14.4 self.z = z
14.5
14.6 c = C()
14.7 +result_1 = c.x
14.8 +result_2 = c.y
14.9 +result_3 = c.z
14.10
14.11 # vim: tabstop=4 expandtab shiftwidth=4
15.1 --- a/tests/class_init_keywords.py Fri May 29 00:18:40 2009 +0200
15.2 +++ b/tests/class_init_keywords.py Sat May 30 20:27:20 2009 +0200
15.3 @@ -7,5 +7,8 @@
15.4 self.z = z
15.5
15.6 c = C(1, 2, z=3)
15.7 +result_1 = c.x
15.8 +result_2 = c.y
15.9 +result_3 = c.z
15.10
15.11 # vim: tabstop=4 expandtab shiftwidth=4
16.1 --- a/tests/classes.py Fri May 29 00:18:40 2009 +0200
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,17 +0,0 @@
16.4 -#!/usr/bin/env python
16.5 -
16.6 -class B:
16.7 - pass
16.8 -
16.9 -class A:
16.10 - c0 = B
16.11 - def __init__(self):
16.12 - self.c2 = B
16.13 -
16.14 -a = A()
16.15 -
16.16 - # context on A attribute context on a attribute
16.17 -A.c0 # none none
16.18 -a.c2 # N/A none
16.19 -
16.20 -# vim: tabstop=4 expandtab shiftwidth=4