Re: [Pharo-project] Block with ^ examples ...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] Block with ^ examples ...

Eliot Miranda-2
 
James,

    ^-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.

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.

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 "sideways return") the implementation may choose (and IMO /should choose) to invoke a cannotReturn: error.

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.

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).

In Squeak the following methods implement this in the simulation, but N.B. fail to prevent side-ways returns:

MethodContext methods for accessing
methodReturnContext
"Answer the context from which an ^-return should return from."

closureOrNil == nil ifTrue:
[^self].
^closureOrNil outerContext methodReturnContext

ContextPart methods for instruction decoding
methodReturnTop
"Simulate the action of a 'return top of stack' bytecode. This corresponds
to source expressions like '^something'."

^self return: self pop from: self methodReturnContext

return: value from: aSender 
"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"

| newTop ctxt |
aSender isDead ifTrue: [
^ self send: #cannotReturn: to: self with: {value} super: false].
newTop := aSender sender.
ctxt := self findNextUnwindContextUpTo: newTop.
ctxt ifNotNil: [
^ self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false].
self releaseTo: newTop.
newTop ifNotNil: [newTop push: value].
^ newTop

To prevent side-ways returns return: value from: aSender needs to be modified to something like

return: value from: aSender 
"For simulation.  Roll back self to aSender and return value from it.  Execute any unwind blocks on the way."

| newTop |
((self hasSender: aSender)
and: [aSender isDead not]) ifFalse:
[^self send: #cannotReturn: to: self with: {value} super: false].
newTop := aSender sender.
(self findNextUnwindContextUpTo: newTop) ifNotNil:
[:ctxt| ^self send: #aboutToReturn:through: to: self with: {value. ctxt} super: false].
self releaseTo: newTop.
newTop ifNotNil: [newTop push: value].
^newTop

HTH
Eliot

On Tue, Apr 17, 2012 at 3:56 PM, James Ladd <[hidden email]> wrote:

If I understand what I have read from the blue book the following is
how a block with a return is handled:

1 - sampleMethod
2     self doIt: [ ^ true ].
3     Transcript show: 'here'; cr.

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

When Line 2 is executed and the passed block is sent the message 'value' then the
value true is returned from the method 'sampleMethod', and line 3 of sampleMethod is
never executed.

Correct?

Rgs, James.



--
best,
Eliot