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