Author: Anton Gulenko <anton.gule...@googlemail.com>
Branch: storage-context-state-v2
Changeset: r959:b76819c9b3b6
Date: 2014-07-27 11:18 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/b76819c9b3b6/

Log:    Removed LocalReturn exception, handling it with flags in the Return
        exception. This fixed drawing issue in the mini image.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -11,11 +11,13 @@
         self.object = object
 
 class Return(Exception):
-    _attrs_ = ["value", "s_target_context", "is_local"]
-    def __init__(self, s_target_context, w_result, is_local):
+    _attrs_ = ["value", "s_target_context", "is_local", "arrived_at_target"]
+    _immutable_attrs_ = ["value", "s_target_context", "is_local"]
+    def __init__(self, s_target_context, w_result):
         self.value = w_result
         self.s_target_context = s_target_context
-        self.is_local = is_local
+        self.arrived_at_target = False
+        self.is_local = s_target_context is None
 
 class NonVirtualReturn(Exception):
     _attrs_ = ["s_target_context", "s_current_context", "value"]
@@ -27,11 +29,6 @@
     def print_trace(self):
         print "\n====== Sender Chain Manipulation, contexts forced to heap at: 
%s" % self.s_current_context.short_str()
 
-class LocalReturn(Exception):
-    _attrs_ = ["value"]
-    def __init__(self, value):
-        self.value = value
-
 class ContextSwitchException(Exception):
     """General Exception that causes the interpreter to leave
     the current context."""
@@ -108,14 +105,13 @@
                 if self.is_tracing():
                     e.print_trace()
                 s_context = e.s_new_context
-            except LocalReturn, ret:
-                s_context = self.unwind_context_chain(s_sender, s_sender, 
ret.value, "LocalReturn")
             except Return, ret:
-                s_context = self.unwind_context_chain(s_sender, 
ret.s_target_context, ret.value, "Return")
+                target = s_sender if ret.arrived_at_target else 
ret.s_target_context
+                s_context = self.unwind_context_chain(s_sender, target, 
ret.value)
             except NonVirtualReturn, ret:
                 if self.is_tracing():
                     ret.print_trace()
-                s_context = self.unwind_context_chain(ret.s_current_context, 
ret.s_target_context, ret.value, "NonVirtual")
+                s_context = self.unwind_context_chain(ret.s_current_context, 
ret.s_target_context, ret.value)
     
     # This is a wrapper around loop_bytecodes that cleanly enters/leaves the 
frame,
     # handles the stack overflow protection mechanism and handles/dispatches 
Returns.
@@ -140,10 +136,9 @@
                 raise NonVirtualReturn(target_context, s_sender, ret.value)
             else:
                 s_frame._activate_unwind_context(self)
-                if ret.s_target_context is s_sender or ret.is_local:
-                    raise LocalReturn(ret.value)
-                else:
-                    raise ret
+                if ret.is_local or ret.s_target_context is s_sender:
+                    ret.arrived_at_target = True
+                raise ret
         finally:
             if self.is_tracing():
                 self.stack_depth -= 1
@@ -169,10 +164,13 @@
                 s_context=s_context)
             try:
                 self.step(s_context)
-            except LocalReturn, ret:
-                s_context.push(ret.value)
+            except Return, ret:
+                if ret.arrived_at_target:
+                    s_context.push(ret.value)
+                else:
+                    raise ret
     
-    def unwind_context_chain(self, start_context, target_context, 
return_value, source=""):
+    def unwind_context_chain(self, start_context, target_context, 
return_value):
         if start_context is None:
             # This is the toplevel frame. Execution ended.
             raise ReturnFromTopLevel(return_value)
@@ -180,8 +178,7 @@
         context = start_context
         while context is not target_context:
             if not context:
-                msg = "Context chain ended (source: %s) while trying to 
return\n%s\nfrom\n%s\n(pc %s)\nto\n%s\n(pc %s)" % (
-                        source,
+                msg = "Context chain ended while trying to 
return\n%s\nfrom\n%s\n(pc %s)\nto\n%s\n(pc %s)" % (
                         return_value.as_repr_string(),
                         start_context.short_str(),
                         start_context.pc(),
diff --git a/spyvm/interpreter_bytecodes.py b/spyvm/interpreter_bytecodes.py
--- a/spyvm/interpreter_bytecodes.py
+++ b/spyvm/interpreter_bytecodes.py
@@ -393,13 +393,12 @@
             # it will find the sender as a local, and we don't have to
             # force the reference
             s_return_to = None
-            is_local = True
         else:
             s_return_to = self.s_home().s_sender()
-            is_local = False
+            assert s_return_to, "No sender to return to!"
         
         from spyvm.interpreter import Return
-        raise Return(s_return_to, return_value, is_local)
+        raise Return(s_return_to, return_value)
 
     # ====== Send/Return bytecodes ======
 
@@ -494,12 +493,13 @@
         if self.gettemp(1).is_nil(self.space):
             self.settemp(1, self.space.w_true) # mark unwound
             self.push(self.gettemp(0)) # push the first argument
-            from spyvm.interpreter import LocalReturn
+            from spyvm.interpreter import Return
             try:
                 self.bytecodePrimValue(interp, 0)
-            except LocalReturn:
+            except Return, ret:
                 # Local return value of ensure: block is ignored
-                pass
+                if not ret.arrived_at_target:
+                    raise ret
             finally:
                 self.mark_returned()
     
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to