[pypy-commit] lang-smalltalk default: added blockclosure bytecode-based tests

lwassermann noreply at buildbot.pypy.org
Mon Feb 25 10:52:27 CET 2013


Author: Lars Wassermann <lars.wassermann at gmail.com>
Branch: 
Changeset: r96:8b8742f9cf14
Date: 2013-02-25 10:52 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/8b8742f9cf14/

Log:	added blockclosure bytecode-based tests implemented nonlocal return
	for blockclosures

diff --git a/spyvm/error.py b/spyvm/error.py
--- a/spyvm/error.py
+++ b/spyvm/error.py
@@ -22,3 +22,6 @@
 class FatalError(SmalltalkException):
     def __init__(self, msg):
         self.msg = msg
+
+class BlockCannotReturnError(PrimitiveFailedError):
+	pass
\ No newline at end of file
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -256,6 +256,8 @@
         # for tests, when returning from the top-level context
         if w_return_to.is_same_object(self.space.w_nil):
             raise ReturnFromTopLevel(object)
+        # widow this context
+        self.store_pc(None)
         w_return_to.as_context_get_shadow(self.space).push(object)
         return w_return_to
 
@@ -272,6 +274,7 @@
         return self._return(interp.space.w_nil, interp, self.s_home().w_sender())
 
     def returnTopFromMethod(self, interp, current_bytecode):
+        # overwritten in MethodContextShadow
         return self._return(self.top(), interp, self.s_home().w_sender())
 
     def returnTopFromBlock(self, interp, current_bytecode):
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -930,6 +930,7 @@
 
 
 def activateClosure(interp, s_frame, w_block, args_w, mayContextSwitch=True):
+    # XXX may context switch is ignored
     space = interp.space
     if not w_block.getclass(space).is_same_object(
             space.w_BlockClosure):
@@ -939,8 +940,7 @@
         raise PrimitiveFailedError()
     outer_ctxt_class = block.outerContext().getclass(space)
     if not (outer_ctxt_class is space.w_MethodContext
-                or outer_ctxt_class is space.w_BlockContext
-                or outer_ctxt_class is space.w_BlockClosure):
+                or outer_ctxt_class is space.w_BlockContext):
         raise PrimitiveFailedError()
     
     # additionally to the smalltalk implementation, this also pushes
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -736,6 +736,19 @@
     def myblocksize(self):
         return self.size() - self.tempsize()
 
+    def returnTopFromMethod(self, interp, current_bytecode):
+        if self.w_closure_or_nil is not self.space.w_nil:
+            # this is a context for a blockClosure
+            s_outerContext = self.w_closure_or_nil.fetch(self.space, 
+                    constants.BLKCLSR_OUTER_CONTEXT).get_shadow(self.space)
+            # XXX check whether we can actually return from that context
+            if s_outerContext.pc() == None:
+                raise error.BlockCannotReturnError()
+            s_outerContext._return(self.top(), interp, 
+                                    s_outerContext.s_home().w_sender())
+        else:
+            return self._return(self.top(), interp, self.s_home().w_sender())
+
 
 class CompiledMethodShadow(object):
     _immutable_fields_ = ["_w_self", "bytecode",
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -923,3 +923,29 @@
     assert closure.outerContext() is s_frame._w_self
     assert closure.at0(0) == "english"
     assert closure.at0(1) == "bar"
+
+def test_blockclosure_valuevalue():
+    #someTest
+    #   ^ [ :a :b | a + b ] value: 1 value: 2
+    def test():
+        assert interpret_bc(
+            [ 0x8f, 2, 0, 4, 16, 17, 0xb0, 0x7d, 0x76, 0x77, 0xf0, 0x7c ],
+            fakeliterals(space, "value:value:", )).value == 3
+    run_with_faked_primitive_methods(
+        [[space.w_BlockClosure, primitives.CLOSURE_VALUE_VALUE,
+            2, "value:value:"]],
+        test)
+
+def test_blockclosure_return():
+    #someTest
+    #   [ :a :b | ^ a + b ] value: 1 value: 2.
+    #   ^ 1
+    def test():
+        assert interpret_bc(
+            [ 0x8f, 2, 0, 4, 16, 17, 0xb0, 0x7c, 
+            0x76, 0x77, 0xf0, 0x87, 0x76, 0x7c ],
+            fakeliterals(space, "value:value:", )).value == 3
+    run_with_faked_primitive_methods(
+        [[space.w_BlockClosure, primitives.CLOSURE_VALUE_VALUE,
+            2, "value:value:"]],
+        test)


More information about the pypy-commit mailing list