[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