module Opal::Nodes::Closure::NodeSupport
def thrower(type, value = nil)
def thrower(type, value = nil) case type when :return thrower_closure = select_closure(DEF, break_after: MODULE | TOP) last_closure = select_closure(JS_FUNCTION) if !thrower_closure iter_closure = select_closure(ITER, break_after: DEF | MODULE | TOP) if iter_closure generate_thrower_without_catcher(:return, iter_closure, value) elsif compiler.eval? push 'Opal.t_eval_return.$throw(', expr_or_nil(value), ', false)' else error 'Invalid return' end elsif thrower_closure == last_closure push 'return ', expr_or_nil(value) else id = generate_thrower(:return, thrower_closure, value) # Additionally, register our thrower on the surrounding iter, if present iter_closure = select_closure(ITER, break_after: DEF | MODULE | TOP) iter_closure.register_thrower(:return, id) if iter_closure end when :eval_return thrower_closure = select_closure(DEF | LAMBDA, break_after: MODULE | TOP) if thrower_closure thrower_closure.register_catcher(:eval_return) end when :next, :redo thrower_closure = select_closure(ITER | LOOP_INSIDE, break_after: DEF | MODULE | TOP) last_closure = select_closure(JS_FUNCTION | JS_LOOP_INSIDE) if !thrower_closure error 'Invalid next' elsif thrower_closure == last_closure if thrower_closure.is? LOOP_INSIDE push 'continue' elsif thrower_closure.is? ITER | LAMBDA push 'return ', expr_or_nil(value) end else generate_thrower(:next, thrower_closure, value) end when :break thrower_closure = select_closure(SEND | LAMBDA | LOOP, break_after: DEF | MODULE | TOP) last_closure = select_closure(JS_FUNCTION | JS_LOOP) if !thrower_closure iter_closure = select_closure(ITER, break_after: DEF | MODULE | TOP) if iter_closure generate_thrower_without_catcher(:break, iter_closure, value) else error 'Invalid break' end elsif thrower_closure == last_closure if thrower_closure.is? JS_FUNCTION | LAMBDA push 'return ', expr_or_nil(value) elsif thrower_closure.is? LOOP push 'break' end else generate_thrower(:break, thrower_closure, value) end when :retry thrower_closure = select_closure(RESCUE_RETRIER, break_after: DEF | MODULE | TOP) last_closure = select_closure(JS_LOOP_INSIDE) if !thrower_closure error 'Invalid retry' elsif thrower_closure == last_closure push 'continue' else generate_thrower(:retry, thrower_closure, value) end end end