Non-local returns with promises (was: Re: Thoughts on a concurrent
reefedjib at yahoo.com
Sun Nov 4 14:27:10 UTC 2007
----- Original Message -----
From: "Igor Stasenko" <siguctua at gmail.com>
> I'm personally much more worrying about non-local returns.
As an example of the problem of non-local return, let's look at this simple
bar ifTrue: [^ 1].
If bar is eventual, we don't know at the time of invocation whether the
method will exit through the non-local
return or through the return at the end of the method.
How to best deal with this?
My thought is that the context needs to become eventual, be sent as a lambda
to the bar promise, and the context return a promise. The return will check
to see if there is a resolver on the context and #resolve: it with the
appropriate return value. The lambda needs to be all sequential code from
the point where a message is sent to the promise that includes a block as an
argument to the end of the context. So the lambda would be:
f := [:barVow |
barVow ifTrue: [^1].
and we would send:
^ bar whenResolved: f.
So the challenge here would be in capturing the lambda and in effect
rewriting the code for this method, on the fly. The lambda is just a one
arg blockContext, where the ip points to the pushTemp: 0.
17 <10> pushTemp: 0
18 <99> jumpFalse: 21
19 <76> pushConstant: 1
20 <7C> returnTop
21 <70> self
22 <D0> send: snafu
23 <87> pop
24 <75> pushConstant: 0
25 <7C> returnTop
and the two return bytecodes, would each need to resolve the promise
returned. This needs to become something like the following, where lines
28-36 is the original block with three rewrites:
first, pushTemp: 1 instead of pushTemp: 0, since the block arg is a
second, the two returnTops needs to become a jumpTo: and a blockReturn,
so we can resolve the promise.
21 <10> pushTemp: 0
22 <89> pushThisContext:
23 <76> pushConstant: 1
24 <C8> send: blockCopy:
25 <A4 0A> jumpTo: 37
27 <69> popIntoTemp: 1
28 <11> pushTemp: 1
29 <99> jumpFalse: 32
30 <76> pushConstant: 1
31 <93> jumpTo: 36
32 <70> self
33 <D1> send: snafu
34 <87> pop
35 <75> pushConstant: 0
36 <7D> blockReturn
37 <E0> send: whenResolved:
38 <7C> returnTop
Of course, we don't want to modify the original method, since another call
to it may not involve a promise. So we are looking at creating a new
MethodContext, which we rewrite to create a new BlockContext defined from
lines 22-25 through 36 above. For every non-local return method when called
with a promise.
What do you think?
More information about the Squeak-dev