/* * call-seq: * catch(symbol) {| | block } > obj * * +catch+ executes its block. If a +throw+ is * executed, Ruby searches up its stack for a +catch+ block * with a tag corresponding to the +throw+'s * _symbol_. If found, that block is terminated, and * +catch+ returns the value given to +throw+. If * +throw+ is not called, the block terminates normally, and * the value of +catch+ is the value of the last expression * evaluated. +catch+ expressions may be nested, and the * +throw+ call need not be in lexical scope. * * def routine(n) * puts n * throw :done if n <= 0 * routine(n-1) * end * * * catch(:done) { routine(3) } * * <em>produces:</em> * * 3 * 2 * 1 * 0 */ static VALUE rb_f_catch(dmy, tag) VALUE dmy, tag; { int state; VALUE val = Qnil; /* OK */ tag = ID2SYM(rb_to_id(tag)); PUSH_TAG(tag); if ((state = EXEC_TAG()) == 0) { val = rb_yield_0(tag, 0, 0, 0, Qfalse); } else if (state == TAG_THROW && tag == prot_tag->dst) { val = prot_tag->retval; state = 0; } POP_TAG(); if (state) JUMP_TAG(state); return val; }