micropython

Changeset

230:892b13f1cba4
2009-05-30 Paul Boddie raw files shortlog changelog graph Changed instantiator invocation reserving a frame slot regardless of whether the target is known in advance. In the instantiator, the first frame slot is then overwritten with the new instance, and the RecoverFrame instruction is no longer required. Instead, a new JumpInFrame instruction maintains the existing locals, jumping to the initialiser method for the class. Updated various tests, renaming and enhancing the classes test.
docs/invocation.txt (file) micropython/ast.py (file) micropython/data.py (file) micropython/rsvp.py (file) micropython/trans.py (file) rsvp.py (file) tests/attributes_instance_bind_method.py (file) tests/call_method.py (file) tests/call_method_ref.py (file) tests/call_method_ref_internal.py (file) tests/call_method_self.py (file) tests/call_method_via_class.py (file) tests/call_method_via_class_internal.py (file) tests/class_init_defaults.py (file) tests/class_init_keywords.py (file) tests/classes.py
     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