James,<div><br></div><div>    ^-return in a block attempts to return from the enclosing method activation (the home context), as if a return from the method has occurred.  But errors and exceptions can occur.</div><div><br>
</div><div>a) if the method has already been returned from the enclosing method context (the home context) will be specially marked (it will have a nil sender and a nil pc) and a cannotReturn: error should be invoked by sending cannotRetuern: with the result as its argument to the activation of the block which is trying to return.</div>
<div><br></div><div>b) if the enclosing home context is not on the sender chain of the block activation (i.e. because the block is being evaluated in a different process, a so-called &quot;sideways return&quot;) the implementation may choose (and IMO /should choose) to invoke a cannotReturn: error.</div>
<div><br></div><div>c) if an unwind-protect is found between the block activation and the sender of the home context then a message invoking unwind-protect processing (implementation-dependent; in Squeak this is #aboutToReturn:through:) should be sent to the block activation, with at least the result as an argument, but typically with the result and the first unwind-protect activation as arguments.<br>
<br></div><div>Further, if the return can occur without error, all activations must be marked as returned-from (so that other attempts to return from intervening acrtivations provoke cannotReturn: errors).</div><div><br></div>
<div>In Squeak the following methods implement this in the simulation, but N.B. fail to prevent side-ways returns:</div><div><br></div><div>MethodContext methods for accessing</div><div><div>methodReturnContext</div><div>
<span class="Apple-tab-span" style="white-space:pre">        </span>&quot;Answer the context from which an ^-return should return from.&quot;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>closureOrNil == nil ifTrue:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>[^self].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^closureOrNil outerContext methodReturnContext</div></div><div><br></div><div>
ContextPart methods for instruction decoding</div><div><div>methodReturnTop</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;Simulate the action of a &#39;return top of stack&#39; bytecode. This corresponds</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> to source expressions like &#39;^something&#39;.&quot;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^self return: self pop from: self methodReturnContext</div>
</div><div><br></div><div><div>return: value from: aSender </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;For simulation.  Roll back self to aSender and return value from it.  Execute any unwind blocks on the way.  ASSUMES aSender is a sender of self&quot;</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| newTop ctxt |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>aSender isDead ifTrue: [</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>^ self send: #cannotReturn: to: self with: {value} super: false].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>newTop := aSender sender.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>ctxt := self findNextUnwindContextUpTo: newTop.</div><div>
<span class="Apple-tab-span" style="white-space:pre">        </span>ctxt ifNotNil: [</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>^ self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>self releaseTo: newTop.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>newTop ifNotNil: [newTop push: value].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^ newTop</div>
</div><div><br></div><div>To prevent side-ways returns return: value from: aSender needs to be modified to something like</div><div><br></div><div><div>return: value from: aSender </div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;For simulation.  Roll back self to aSender and return value from it.  Execute any unwind blocks on the way.&quot;</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| newTop |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>((self hasSender: aSender)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>and: [aSender isDead not]) ifFalse:</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>[^self send: #cannotReturn: to: self with: {value} super: false].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>newTop := aSender sender.</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>(self findNextUnwindContextUpTo: newTop) ifNotNil:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[:ctxt| ^self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>self releaseTo: newTop.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>newTop ifNotNil: [newTop push: value].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^newTop</div>
</div><div><br></div><div>HTH</div><div>Eliot</div><div><br></div><div><div class="gmail_quote">On Tue, Apr 17, 2012 at 3:56 PM, James Ladd <span dir="ltr">&lt;<a href="mailto:james_ladd@hotmail.com">james_ladd@hotmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div><div dir="ltr">
<br>If I understand what I have read from the blue book the following is <br>how a block with a return is handled:<br><br><span style="font-family:courier new,monospace">1 - sampleMethod</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">2     self doIt: [ ^ true ].</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">3     Transcript show: &#39;here&#39;; cr.</span><br style="font-family:courier new,monospace">

<br>Line 1 defines the instance method &#39;sampleMethod&#39; - using Redline syntax of course.<br>Line 2 sends the keyword message doIt: to receiver with a block that contains a &#39;^&#39; (return).<br>Line 3 outputs a message using the Transcript.<br>

<br>When Line 2 is executed and the passed block is sent the message &#39;value&#39; then the <br>value true is returned from the method &#39;sampleMethod&#39;, and line 3 of sampleMethod is <br>never executed.<br><br>Correct?<br>
<br>Rgs, James.<br>                                               </div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>
</div>