[pypy-commit] pypy stacklet: Because it's not much code, and for symmetry, implement

arigo noreply at buildbot.pypy.org
Fri Aug 19 01:29:50 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46620:f3d97e54818d
Date: 2011-08-18 22:59 +0200
http://bitbucket.org/pypy/pypy/changeset/f3d97e54818d/

Log:	Because it's not much code, and for symmetry, implement
	c1.throw(exc, value, tb, to), giving an explicit "to", like in
	c1.switch().

diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -48,7 +48,14 @@
             start_state.clear()
             raise getmemoryerror(self.space)
 
-    def switch(self, to=None):
+    def switch(self, w_to):
+        to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
+        if to is not None:
+            if self is to:    # double-switch to myself: no-op
+                return get_result()
+            if to.sthread is None:
+                start_state.clear()
+                raise geterror(self.space, "continulet not initialized yet")
         if self.sthread is None:
             start_state.clear()
             raise geterror(self.space, "continulet not initialized yet")
@@ -77,26 +84,13 @@
         #
         ec = sthread.ec
         ec.topframeref = saved_topframeref
-        if start_state.propagate_exception:
-            e = start_state.propagate_exception
-            start_state.propagate_exception = None
-            raise e
-        w_value = start_state.w_value
-        start_state.w_value = None
-        return w_value
+        return get_result()
 
     def descr_switch(self, w_value=None, w_to=None):
-        to = self.space.interp_w(W_Continulet, w_to, can_be_None=True)
-        if to is not None:
-            if self is to:    # double-switch to myself: no-op
-                return w_value
-            if to.sthread is None:
-                start_state.clear()
-                raise geterror(self.space, "continulet not initialized yet")
         start_state.w_value = w_value
-        return self.switch(to)
+        return self.switch(w_to)
 
-    def descr_throw(self, w_type, w_val=None, w_tb=None):
+    def descr_throw(self, w_type, w_val=None, w_tb=None, w_to=None):
         from pypy.interpreter.pytraceback import check_traceback
         space = self.space
         #
@@ -108,8 +102,9 @@
         #
         operr = OperationError(w_type, w_val, tb)
         operr.normalize_exception(space)
+        start_state.w_value = None
         start_state.propagate_exception = operr
-        return self.switch()
+        return self.switch(w_to)
 
     def descr_is_pending(self):
         valid = (self.sthread is not None
@@ -218,3 +213,12 @@
     start_state.origin = None
     start_state.destination = None
     self.h, origin.h = origin.h, h
+
+def get_result():
+    if start_state.propagate_exception:
+        e = start_state.propagate_exception
+        start_state.propagate_exception = None
+        raise e
+    w_value = start_state.w_value
+    start_state.w_value = None
+    return w_value
diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py
--- a/pypy/module/_continuation/test/test_stacklet.py
+++ b/pypy/module/_continuation/test/test_stacklet.py
@@ -576,6 +576,38 @@
         c1 = continulet(f1)
         raises(IndexError, c1.throw, IndexError)
 
+    def test_throw2_simple(self):
+        from _continuation import continulet
+        #
+        def f1(c1):
+            not_reached
+        def f2(c2):
+            try:
+                c2.switch("ready")
+            except IndexError:
+                raise ValueError
+        #
+        c1 = continulet(f1)
+        c2 = continulet(f2)
+        res = c2.switch()
+        assert res == "ready"
+        assert c1.is_pending()
+        assert c2.is_pending()
+        raises(ValueError, c1.throw, IndexError, to=c2)
+        assert not c1.is_pending()
+        assert not c2.is_pending()
+
+    def test_throw2_no_op(self):
+        from _continuation import continulet
+        #
+        def f1(c1):
+            raises(ValueError, c1.throw, ValueError, to=c1)
+            return "ok"
+        #
+        c1 = continulet(f1)
+        res = c1.switch()
+        assert res == "ok"
+
     def test_various_depths(self):
         skip("may fail on top of CPython")
         # run it from test_translated, but not while being actually translated


More information about the pypy-commit mailing list