----- Original Message ----- From: "Igor Stasenko" siguctua@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 method:
foo: bar
bar ifTrue: [^ 1]. self snafu. ^ 0
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]. self snafu. ^ 0]
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 separate temp. 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?
Rob