MonkeeSage wrote:
> On Dec 3, 10:40 pm, Charles Oliver Nutter <charles.nut... / sun.com>
> wrote:
>   
>> MonkeeSage wrote:
>>     
>>> On Dec 3, 8:22 pm, Charles Oliver Nutter <charles.nut... / sun.com>
>>>       
>>>> Retry outside a rescue actually allows you to jump back across call
>>>> boundaries and start an invocation again. Scary.
>>>>         
>>>> - Charlie
>>>>         
>>> Ah. How does it unwind the stack like that? Is that what you meant
>>> about implementation specific stuff?
>>>       
>> It raises an exception, a LocalJumpError (which is how all non-local
>> flow control works) which is then handled further up the stack.
>>
>> The reason it's implementation-specific is because the behavior ends up
>> being a side effect of MRI's interpreter.
>>
>> The following call:
>>
>> foo {}
>>
>> Parses into an AST like this:
>>
>> Iter # this represents the block
>>    FCall :foo # this represents the call receiving the block
>>      nil # no args to the call
>>
>> Outside of a rescue, retry bubbles out to the nearest Iter. If there is
>> none, it bubbles all the way out and terminates execution. The
>> implementation-specific bit here is the fact that Iter contains FCall,
>> rather than the more intuitive reverse; this causes the retry to go all
>> the way back above the FCall and try it completely anew, reevaluating
>> its receiver and arguments in the process. In compiled implementations
>> or implementations with a different AST, this doesn't map well. It's
>> very specific to the way MRI represents Iter/Call in the AST.
>>
>>     
>>> Ps. I don't think anyone will miss retry outside of a rescue. I won't
>>> at least. :)
>>>       
>> I've just disabled it outside of rescue in JRuby trunk; we'll see how
>> that goes. So far, nothing seems breaks.
>>
>> - Charlie
>>     
>
> Just out of curiousity...is there a reason why MRI has Iter closing on
> the FCall rather than the other way 'round? Or is it just incidental?
>
> Regards,
> Jordan
>
>   
If Charlie did not mention this earlier in the thread we have in fact 
reversed that relationship in JRuby.  I suspect it was reversed in MRI 
to make it easier to set/unset (setup/teardown) some stuff when a method 
call needs to pass a block.   Consider:

doIter {
   set something block related
   doCall
   unset something block related
}

I don't remember specifically what they set/unset but I remember this 
appearing to be a possible reason for it.

Perhaps an MRI coder could comment since I have always wondered about 
this reversed relationship.

-Tom

--
Thomas E Enebo <thomas.enebo / sun.com>
JRuby Core Developer, http://www.bloglines.com/blog/ThomasEEnebo