Project

General

Profile

Bug #1852 » catch.diff

marcandre (Marc-Andre Lafortune), 09/16/2009 05:36 AM

View differences:

vm_eval.c
rb_throw_obj(ID2SYM(rb_intern(tag)), val);
}
static VALUE
catch_i(VALUE tag, VALUE data) {
return rb_yield_0(1, &tag);
}
/*
* call-seq:
* catch([arg]) {|tag| block } => obj
......
rb_f_catch(int argc, VALUE *argv)
{
VALUE tag;
int state;
volatile VALUE val = Qnil; /* OK */
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *saved_cfp = th->cfp;
if (argc == 0) {
tag = rb_obj_alloc(rb_cObject);
......
else {
rb_scan_args(argc, argv, "01", &tag);
}
return rb_catch_obj(tag, catch_i, 0);
}
VALUE
rb_catch(const char *tag, VALUE (*func)(), VALUE data)
{
VALUE vtag = tag ? ID2SYM(rb_intern(tag)) : rb_obj_alloc(rb_cObject);
return rb_catch_obj(vtag, func, data);
}
VALUE
rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
{
int state;
volatile VALUE val = Qnil; /* OK */
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *saved_cfp = th->cfp;
PUSH_TAG();
th->tag->tag = tag;
if ((state = EXEC_TAG()) == 0) {
val = rb_yield_0(1, &tag);
/* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
val = (*func)(tag, data, 1, &tag, Qnil);
}
else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
th->cfp = saved_cfp;
......
return val;
}
static VALUE
catch_null_i(VALUE dmy)
{
return rb_funcall(Qnil, rb_intern("catch"), 0, 0);
}
static VALUE
catch_i(VALUE tag)
{
return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
}
VALUE
rb_catch(const char *tag, VALUE (*func)(), VALUE data)
{
if (!tag) {
return rb_iterate(catch_null_i, 0, func, data);
}
return rb_iterate(catch_i, ID2SYM(rb_intern(tag)), func, data);
}
VALUE
rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
{
return rb_iterate((VALUE (*)_((VALUE)))catch_i, tag, func, data);
}
/*
* call-seq:
* caller(start=1) => array
(4-4/5)