From 8e9fbbf6d6f4c47286a6fbc4e2c4e77189be119b Mon Sep 17 00:00:00 2001 From: matz Date: Sat, 30 Aug 2003 00:04:02 +0000 Subject: * eval.c (struct BLOCK): remove BLOCKTAG, use scope instead. * eval.c (POP_TAG): no longer propagate retval. retval is now set directly by localjump_destination(). * eval.c (localjump_destination): new function to cast return/break local jump. * eval.c (rb_yield_0): stop TAG_RETURN/TAG_BREAK escaping. * variable.c (rb_autoload_load): call const_missing if autoloading constant is not defined to allow hook. * eval.c (rb_eval): use rb_const_get_from() instead of rb_const_get_at(). * eval.c (is_defined): forgot to check NODE_COLON3. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4462 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 22 ++++ eval.c | 343 ++++++++++++++++++++++----------------------------------- sample/test.rb | 10 +- variable.c | 68 +++++------- 4 files changed, 183 insertions(+), 260 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0421fd0d9e..9e64f0d515 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Sat Aug 30 03:58:21 2003 Yukihiro Matsumoto + + * eval.c (struct BLOCK): remove BLOCKTAG, use scope instead. + + * eval.c (POP_TAG): no longer propagate retval. retval is now set + directly by localjump_destination(). + + * eval.c (localjump_destination): new function to cast + return/break local jump. + + * eval.c (rb_yield_0): stop TAG_RETURN/TAG_BREAK escaping. + Fri Aug 29 22:35:00 2003 Shigeo Kobayashi * bigdecimal.c *.html: The 2nd arg. for add,sub,mult, and div is 0, @@ -34,6 +46,16 @@ Fri Aug 29 17:30:15 2003 Hidetoshi NAGAI * ext/tk/lib/tkfont.rb TkFont.new() accepts compound fonts +Thu Aug 28 22:07:12 2003 Yukihiro Matsumoto + + * variable.c (rb_autoload_load): call const_missing if autoloading + constant is not defined to allow hook. + + * eval.c (rb_eval): use rb_const_get_from() instead of + rb_const_get_at(). + + * eval.c (is_defined): forgot to check NODE_COLON3. + Thu Aug 28 17:30:24 2003 Yukihiro Matsumoto * variable.c (rb_const_get_0): should check constants defined in diff --git a/eval.c b/eval.c index 5ee4158b27..15911679c4 100644 --- a/eval.c +++ b/eval.c @@ -602,19 +602,12 @@ static struct SCOPE *top_scope; ruby_frame = _frame.prev; \ } while (0) -struct BLOCKTAG { - struct RBasic super; - long dst; - long flags; -}; - struct BLOCK { NODE *var; NODE *body; VALUE self; struct FRAME frame; struct SCOPE *scope; - struct BLOCKTAG *tag; VALUE klass; NODE *cref; int iter; @@ -629,26 +622,12 @@ struct BLOCK { }; #define BLOCK_D_SCOPE 1 -#define BLOCK_DYNAMIC 2 -#define BLOCK_ORPHAN 4 -#define BLOCK_LAMBDA 8 -#define BLOCK_LEFT 16 +#define BLOCK_LAMBDA 2 static struct BLOCK *ruby_block; -static struct BLOCKTAG* -new_blktag() -{ - NEWOBJ(blktag, struct BLOCKTAG); - OBJSETUP(blktag, 0, T_BLKTAG); - blktag->dst = 0; - blktag->flags = 0; - return blktag; -} - #define PUSH_BLOCK(v,b) do { \ struct BLOCK _block; \ - _block.tag = new_blktag(); \ _block.var = v; \ _block.body = b; \ _block.self = self; \ @@ -668,12 +647,7 @@ new_blktag() ruby_block = &_block #define POP_BLOCK() \ - if (_block.tag->flags & (BLOCK_DYNAMIC)) \ - _block.tag->flags |= BLOCK_ORPHAN; \ - else if (!(_block.scope->flags & SCOPE_DONT_RECYCLE)) \ - rb_gc_force_recycle((VALUE)_block.tag); \ ruby_block = _block.prev; \ - _block.tag->flags |= BLOCK_LEFT; \ } while (0) struct RVarmap *ruby_dyna_vars; @@ -845,7 +819,7 @@ struct tag { jmp_buf buf; struct FRAME *frame; struct iter *iter; - ID tag; + VALUE tag; VALUE retval; struct SCOPE *scope; int dst; @@ -864,9 +838,12 @@ static struct tag *prot_tag; _tag.dst = 0; \ prot_tag = &_tag -#define PROT_NONE 0 -#define PROT_FUNC -1 -#define PROT_THREAD -2 +#define PROT_NONE Qfalse /* 0 */ +#define PROT_THREAD Qtrue /* 2 */ +#define PROT_FUNC INT2FIX(0) /* 1 */ +#define PROT_ITER INT2FIX(1) /* 3 */ +#define PROT_CALL INT2FIX(2) /* 5 */ +#define PROT_PCALL INT2FIX(3) /* 7 */ #define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf)) @@ -877,14 +854,10 @@ static struct tag *prot_tag; } while (0) #define POP_TAG() \ - if (_tag.prev) \ - _tag.prev->retval = _tag.retval;\ prot_tag = _tag.prev; \ } while (0) -#define POP_TMPTAG() \ - prot_tag = _tag.prev; \ -} while (0) +#define TAG_DST(t) (_tag.dst == (VALUE)_tag.scope) #define TAG_RETURN 0x1 #define TAG_BREAK 0x2 @@ -1561,12 +1534,12 @@ jump_tag_but_local_jump(state) case TAG_RETURN: localjump_error("unexpected return", val, state); break; - case TAG_NEXT: - localjump_error("unexpected next", val, state); - break; case TAG_BREAK: localjump_error("unexpected break", val, state); break; + case TAG_NEXT: + localjump_error("unexpected next", val, state); + break; case TAG_REDO: localjump_error("unexpected redo", Qnil, state); break; @@ -1574,9 +1547,9 @@ jump_tag_but_local_jump(state) localjump_error("retry outside of rescue clause", Qnil, state); break; default: - JUMP_TAG(state); break; } + JUMP_TAG(state); } VALUE @@ -2163,6 +2136,12 @@ is_defined(self, node, buf) } break; + case NODE_COLON3: + if (rb_const_defined_from(rb_cObject, node->nd_mid)) { + return "constant"; + } + break; + case NODE_NTH_REF: if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) { sprintf(buf, "$%d", (int)node->nd_nth); @@ -2279,7 +2258,7 @@ call_trace_func(event, node, self, id, klass) Qundef, 0); } if (raised) thread_set_raised(); - POP_TMPTAG(); /* do not propagate retval */ + POP_TAG(); POP_FRAME(); tracing = 0; @@ -2434,12 +2413,12 @@ class_prefix(self, cpath) } } -static void return_check _((void)); #define return_value(v) do {\ if ((prot_tag->retval = (v)) == Qundef) {\ prot_tag->retval = Qnil;\ }\ } while (0) +static void localjump_destination _((int, struct SCOPE*, VALUE)); static VALUE rb_eval(self, n) @@ -2508,7 +2487,7 @@ rb_eval(self, n) /* node for speed-up(top-level loop for -n/-p) */ case NODE_OPT_N: - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_ITER); switch (state = EXEC_TAG()) { case 0: opt_n_next: @@ -2640,7 +2619,7 @@ rb_eval(self, n) RETURN(Qnil); case NODE_WHILE: - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_ITER); result = Qnil; switch (state = EXEC_TAG()) { case 0: @@ -2672,7 +2651,7 @@ rb_eval(self, n) RETURN(result); case NODE_UNTIL: - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_ITER); result = Qnil; switch (state = EXEC_TAG()) { case 0: @@ -2710,7 +2689,7 @@ rb_eval(self, n) case NODE_ITER: case NODE_FOR: { - PUSH_TAG(PROT_FUNC); + PUSH_TAG(PROT_ITER); PUSH_BLOCK(node->nd_var, node->nd_body); state = EXEC_TAG(); @@ -2733,30 +2712,19 @@ rb_eval(self, n) } POP_ITER(); } - else { - if (_block.tag->dst == state) { - state &= TAG_MASK; - if (state == TAG_RETURN || state == TAG_BREAK) { - result = prot_tag->retval; - } - } - if (state == TAG_RETRY) { - state = 0; - goto iter_retry; - } + else if (state == TAG_BREAK && TAG_DST()) { + result = prot_tag->retval; + state = 0; + } + else if (state == TAG_RETRY) { + state = 0; + goto iter_retry; } POP_BLOCK(); POP_TAG(); switch (state) { case 0: break; - - case TAG_BREAK: - break; - - case TAG_RETURN: - return_value(result); - /* fall through */ default: JUMP_TAG(state); } @@ -2764,8 +2732,7 @@ rb_eval(self, n) break; case NODE_BREAK: - return_value(rb_eval(self, node->nd_stts)); - JUMP_TAG(TAG_BREAK); + localjump_destination(TAG_BREAK, ruby_scope, rb_eval(self, node->nd_stts)); break; case NODE_NEXT: @@ -2938,9 +2905,7 @@ rb_eval(self, n) break; case NODE_RETURN: - return_value(rb_eval(self, node->nd_stts)); - return_check(); - JUMP_TAG(TAG_RETURN); + localjump_destination(TAG_RETURN, ruby_scope, rb_eval(self, node->nd_stts)); break; case NODE_ARGSCAT: @@ -3048,13 +3013,14 @@ rb_eval(self, n) { struct FRAME frame; NODE *saved_cref = 0; + int jump_chain = Qfalse; frame = *ruby_frame; frame.tmp = ruby_frame; ruby_frame = &frame; PUSH_SCOPE(); - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_PCALL); if (node->nd_rval) { saved_cref = ruby_cref; ruby_cref = (NODE*)node->nd_rval; @@ -3073,12 +3039,24 @@ rb_eval(self, n) if ((state = EXEC_TAG()) == 0) { result = rb_eval(self, node->nd_next); } + else if (TAG_DST()) { + result = prot_tag->retval; + jump_chain = Qtrue; + } POP_TAG(); POP_SCOPE(); ruby_frame = frame.tmp; if (saved_cref) ruby_cref = saved_cref; - if (state) JUMP_TAG(state); + switch (state) { + case 0: + break; + case TAG_RETURN: + case TAG_BREAK: + localjump_destination(state, ruby_scope, result); + default: + JUMP_TAG(state); + } } break; @@ -3271,7 +3249,7 @@ rb_eval(self, n) break; case NODE_COLON3: - result = rb_const_get_at(rb_cObject, node->nd_mid); + result = rb_const_get_from(rb_cObject, node->nd_mid); break; case NODE_NTH_REF: @@ -4024,6 +4002,37 @@ rb_f_block_given_p() return Qfalse; } +static VALUE rb_eThreadError; + +static void +localjump_destination(state, scope, retval) + int state; + struct SCOPE *scope; + VALUE retval; +{ + struct tag *tt = prot_tag; + VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC; + + if (retval == Qundef) retval = Qnil; + while (tt) { + if (tt->tag == PROT_PCALL || + (tt->tag == PROT_CALL || tt->tag == tag) && tt->scope == scope) { + tt->dst = (VALUE)scope; + tt->retval = retval; + break; + } + if (tt->tag == PROT_THREAD) { + rb_raise(rb_eThreadError, "%s jump can't across threads", + (state == TAG_BREAK) ? "break" : "return"); + } + tt = tt->prev; + } + if (!tt) { + jump_tag_but_local_jump(state); + } + JUMP_TAG(state); +} + static VALUE rb_yield_0(val, self, klass, flags, avalue) VALUE val, self, klass; /* OK */ @@ -4163,12 +4172,6 @@ rb_yield_0(val, self, klass, flags, avalue) state = 0; result = prot_tag->retval; break; - case TAG_BREAK: - case TAG_RETURN: - state |= (serial++ << 8); - state |= 0x10; - block->tag->dst = state; - break; default: break; } @@ -4201,17 +4204,7 @@ rb_yield_0(val, self, klass, flags, avalue) ruby_scope = old_scope; scope_vmode = old_vmode; ruby_current_node = cnode; - if (state) { - if (!block->tag) { - switch (state & TAG_MASK) { - case TAG_BREAK: - case TAG_RETURN: - jump_tag_but_local_jump(state & TAG_MASK); - break; - } - } - JUMP_TAG(state); - } + if (state) JUMP_TAG(state); return result; } @@ -4430,24 +4423,20 @@ rb_iterate(it_proc, data1, bl_proc, data2) PUSH_ITER(ITER_PRE); PUSH_BLOCK(0, node); - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_ITER); state = EXEC_TAG(); if (state == 0) { iter_retry: retval = (*it_proc)(data1); } - else { - if (ruby_block->tag->dst == state) { - state &= TAG_MASK; - if (state == TAG_RETURN || state == TAG_BREAK) { - retval = prot_tag->retval; - } - } - if (state == TAG_RETRY) { - state = 0; - goto iter_retry; - } + else if (state == TAG_BREAK && TAG_DST()) { + retval = prot_tag->retval; + state = 0; + } + else if (state == TAG_RETRY) { + state = 0; + goto iter_retry; } POP_TAG(); POP_BLOCK(); @@ -4456,13 +4445,6 @@ rb_iterate(it_proc, data1, bl_proc, data2) switch (state) { case 0: break; - - case TAG_BREAK: - break; - - case TAG_RETURN: - return_value(retval); - /* fall through */ default: JUMP_TAG(state); } @@ -4607,7 +4589,6 @@ rb_ensure(b_proc, data1, e_proc, data2) retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */ (*e_proc)(data2); if (prot_tag) return_value(retval); - if (state) JUMP_TAG(state); return result; } @@ -5051,7 +5032,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper) } result = rb_eval(recv, body); } - else if (state == TAG_RETURN) { + else if (state == TAG_RETURN && TAG_DST()) { result = prot_tag->retval; state = 0; } @@ -5067,10 +5048,13 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper) case 0: break; + case TAG_BREAK: + case TAG_RETURN: + JUMP_TAG(state); + break; + case TAG_RETRY: - if (rb_block_given_p()) { - JUMP_TAG(state); - } + if (rb_block_given_p()) JUMP_TAG(state); /* fall through */ default: jump_tag_but_local_jump(state); @@ -5482,13 +5466,6 @@ eval(self, src, scope, file, line) for (tag=prot_tag; tag; tag=tag->prev) { scope_dup(tag->scope); } - if (ruby_block) { - struct BLOCK *block = ruby_block; - while (block) { - block->tag->flags |= BLOCK_DYNAMIC; - block = block->prev; - } - } for (vars = ruby_dyna_vars; vars; vars = vars->next) { FL_SET(vars, DVAR_DONT_RECYCLE); } @@ -6708,7 +6685,6 @@ blk_mark(data) rb_gc_mark((VALUE)data->self); rb_gc_mark((VALUE)data->dyna_vars); rb_gc_mark((VALUE)data->cref); - rb_gc_mark((VALUE)data->tag); rb_gc_mark(data->wrapper); rb_gc_mark(data->block_obj); data = data->prev; @@ -6755,7 +6731,6 @@ blk_copy_prev(block) tmp->frame.flags |= FRAME_MALLOC; } scope_dup(tmp->scope); - tmp->tag->flags |= BLOCK_DYNAMIC; for (vars = tmp->dyna_vars; vars; vars = vars->next) { if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; @@ -6840,8 +6815,6 @@ rb_f_binding(self) else { data->prev = 0; } - data->flags |= BLOCK_DYNAMIC; - data->tag->flags |= BLOCK_DYNAMIC; for (p = data; p; p = p->prev) { for (vars = p->dyna_vars; vars; vars = vars->next) { @@ -6940,8 +6913,6 @@ proc_alloc(klass, proc) else { data->prev = 0; } - data->flags |= BLOCK_DYNAMIC; - data->tag->flags |= BLOCK_DYNAMIC; for (p = data; p; p = p->prev) { for (vars = p->dyna_vars; vars; vars = vars->next) { @@ -6996,8 +6967,7 @@ static int block_orphan(data) struct BLOCK *data; { - if ((data->tag->flags & BLOCK_ORPHAN) && - (data->scope->flags & SCOPE_NOSTACK)) { + if (data->scope->flags & SCOPE_NOSTACK) { return 1; } if (data->orig_thread != rb_thread_current()) { @@ -7014,8 +6984,8 @@ proc_invoke(proc, args, self, klass) struct BLOCK * volatile old_block; struct BLOCK _block; struct BLOCK *data; - volatile VALUE result = Qnil; - int state, incoming_state; + volatile VALUE result = Qundef; + int state; volatile int orphan; volatile int safe = ruby_safe_level; volatile VALUE old_wrapper = ruby_wrapper; @@ -7043,21 +7013,17 @@ proc_invoke(proc, args, self, klass) PUSH_ITER(ITER_CUR); ruby_frame->iter = ITER_CUR; - PUSH_TAG(PROT_NONE); + PUSH_TAG(pcall ? PROT_PCALL : PROT_CALL); state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(proc); result = rb_yield_0(args, self, self!=Qundef?CLASS_OF(self):0, pcall, Qtrue); } + else if (TAG_DST()) { + result = prot_tag->retval; + } POP_TAG(); - POP_ITER(); - incoming_state = state; - if (orphan || pcall || - ((ruby_block->tag->flags & BLOCK_LEFT) && - ruby_block->tag->dst == state)) { - state &= TAG_MASK; - } ruby_block = old_block; ruby_wrapper = old_wrapper; ruby_dyna_vars = old_dvars; @@ -7073,18 +7039,15 @@ proc_invoke(proc, args, self, klass) /* fall through */ case TAG_BREAK: case TAG_RETURN: - if (pcall) { - result = prot_tag->retval; - break; - } - else if (orphan) { /* orphan block */ + if (pcall) break; + if (orphan) { /* orphan block */ char mesg[32]; snprintf(mesg, sizeof mesg, "%s from proc-closure", state == TAG_BREAK ? "break" : "return"); localjump_error(mesg, prot_tag->retval, state); } - else if (state == incoming_state) { - ruby_block->tag->dst = incoming_state; + if (result != Qundef) { + localjump_destination(state, ruby_scope, result); } default: JUMP_TAG(state); @@ -7147,7 +7110,7 @@ proc_eq(self, other) if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse; Data_Get_Struct(self, struct BLOCK, data); Data_Get_Struct(other, struct BLOCK, data2); - if (data->tag == data2->tag) return Qtrue; + if (data->body == data2->body) return Qtrue; return Qfalse; } @@ -7166,12 +7129,12 @@ proc_to_s(self, other) if ((node = data->frame.node) || (node = data->body)) { len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3; str = rb_str_new(0, len); - sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->tag, + sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx@%s:%d>", cname, w, (VALUE)data->body, node->nd_file, nd_line(node)); } else { str = rb_str_new(0, len); - sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx>", cname, w, (VALUE)data->tag); + sprintf(RSTRING(str)->ptr, "#<%s:0x%.*lx>", cname, w, (VALUE)data->body); } RSTRING(str)->len = strlen(RSTRING(str)->ptr); if (OBJ_TAINTED(self)) OBJ_TAINT(str); @@ -7262,7 +7225,7 @@ block_pass(self, node) PUSH_ITER(ITER_PRE); ruby_frame->iter = ITER_PRE; - PUSH_TAG(PROT_NONE); + PUSH_TAG(PROT_ITER); state = EXEC_TAG(); if (state == 0) { retry: @@ -7271,26 +7234,11 @@ block_pass(self, node) ruby_safe_level = safe; result = rb_eval(self, node->nd_iter); } - if (_block.tag->dst == state) { - if (orphan) { - state &= TAG_MASK; - } - else { - struct BLOCK *ptr = old_block; - - while (ptr) { - if (ptr->scope == _block.scope) { - ptr->tag->dst = state; - break; - } - ptr = ptr->prev; - } - if (!ptr) { - state &= TAG_MASK; - } - } + else if (state == TAG_BREAK && TAG_DST()) { + result = prot_tag->retval; + state = 0; } - if (state == TAG_RETRY) { + else if (state == TAG_RETRY) { state = 0; goto retry; } @@ -7302,9 +7250,6 @@ block_pass(self, node) switch (state) {/* escape from orphan block */ case 0: break; - case TAG_BREAK: - result = prot_tag->retval; - break; case TAG_RETURN: if (orphan) { localjump_error("return from proc-closure", prot_tag->retval, state); @@ -7833,8 +7778,6 @@ win32_set_exception_list(p) #endif #endif -static VALUE rb_eThreadError; - int rb_thread_pending = 0; VALUE rb_cThread; @@ -9932,14 +9875,6 @@ rb_callcc(self) for (tag=prot_tag; tag; tag=tag->prev) { scope_dup(tag->scope); } - if (ruby_block) { - struct BLOCK *block = ruby_block; - - while (block) { - block->tag->flags |= BLOCK_DYNAMIC; - block = block->prev; - } - } th->thread = curr_thread->thread; for (vars = th->dyna_vars; vars; vars = vars->next) { @@ -10160,15 +10095,14 @@ rb_f_catch(dmy, tag) VALUE dmy, tag; { int state; - ID t; VALUE val = Qnil; /* OK */ - t = rb_to_id(tag); - PUSH_TAG(t); + tag = ID2SYM(rb_to_id(tag)); + PUSH_TAG(tag); if ((state = EXEC_TAG()) == 0) { val = rb_yield_0(tag, 0, 0, Qfalse, Qfalse); } - else if (state == TAG_THROW && t == prot_tag->dst) { + else if (state == TAG_THROW && tag == prot_tag->dst) { val = prot_tag->retval; state = 0; } @@ -10180,9 +10114,9 @@ rb_f_catch(dmy, tag) static VALUE catch_i(tag) - ID tag; + VALUE tag; { - return rb_funcall(Qnil, rb_intern("catch"), 1, ID2SYM(tag)); + return rb_funcall(Qnil, rb_intern("catch"), 1, tag); } VALUE @@ -10191,7 +10125,7 @@ rb_catch(tag, func, data) VALUE (*func)(); VALUE data; { - return rb_iterate((VALUE(*)_((VALUE)))catch_i, rb_intern(tag), func, data); + return rb_iterate((VALUE(*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), func, data); } static VALUE @@ -10200,28 +10134,27 @@ rb_f_throw(argc, argv) VALUE *argv; { VALUE tag, value; - ID t; struct tag *tt = prot_tag; rb_scan_args(argc, argv, "11", &tag, &value); - t = rb_to_id(tag); + tag = ID2SYM(rb_to_id(tag)); while (tt) { - if (tt->tag == t) { - tt->dst = t; + if (tt->tag == tag) { + tt->dst = tag; + tt->retval = value; break; } if (tt->tag == PROT_THREAD) { rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%lx", - rb_id2name(t), + rb_id2name(SYM2ID(tag)), curr_thread); } tt = tt->prev; } if (!tt) { - rb_name_error(t, "uncaught throw `%s'", rb_id2name(t)); + rb_name_error(SYM2ID(tag), "uncaught throw `%s'", rb_id2name(SYM2ID(tag))); } - return_value(value); rb_trap_restore_mask(); JUMP_TAG(TAG_THROW); #ifndef __GNUC__ @@ -10235,26 +10168,8 @@ rb_throw(tag, val) VALUE val; { VALUE argv[2]; - ID t = rb_intern(tag); - argv[0] = ID2SYM(t); + argv[0] = ID2SYM(rb_intern(tag)); argv[1] = val; rb_f_throw(2, argv); } - -static void -return_check() -{ - struct tag *tt = prot_tag; - - while (tt) { - if (tt->tag == PROT_FUNC) { - break; - } - if (tt->tag == PROT_THREAD) { - rb_raise(rb_eThreadError, "return from within thread 0x%lx", - curr_thread); - } - tt = tt->prev; - } -} diff --git a/sample/test.rb b/sample/test.rb index 7e96f01567..1898813564 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -374,7 +374,7 @@ a,b,*c = loop do break *[*[]]; end; test_ok([a,b,c] == [nil,nil,[]]) a,b,*c = loop do break *[*[1]]; end; test_ok([a,b,c] == [1,nil,[]]) a,b,*c = loop do break *[*[1,2]]; end; test_ok([a,b,c] == [1,2,[]]) -def r(val); a = yield(); test_ok(a == val); end +def r(val); a = yield(); test_ok(a == val, 2); end r(nil){next} r(nil){next nil} r(1){next 1} @@ -396,7 +396,7 @@ r(nil){next *[*[]]} r(1){next *[*[1]]} r([1,2]){next *[*[1,2]]} -def r(val); *a = yield(); test_ok(a == val); end +def r(val); *a = yield(); test_ok(a == val, 2); end r([nil]){next} r([nil]){next nil} r([1]){next 1} @@ -409,7 +409,7 @@ r([[]]){next [*[]]} r([[1]]){next [*[1]]} r([[1,2]]){next [*[1,2]]} -def r(val); *a = *yield(); test_ok(a == val); end +def r(val); *a = *yield(); test_ok(a == val, 2); end r([nil]){next *nil} r([1]){next *1} r([nil]){next *[]} @@ -421,7 +421,7 @@ r([nil]){next *[*[]]} r([1]){next *[*[1]]} r([1,2]){next *[*[1,2]]} -def r(val); a,b,*c = yield(); test_ok([a,b,c] == val); end +def r(val); a,b,*c = yield(); test_ok([a,b,c] == val, 2); end r([nil,nil,[]]){next} r([nil,nil,[]]){next nil} r([1,nil,[]]){next 1} @@ -434,7 +434,7 @@ r([nil,nil,[]]){next [*[]]} r([1,nil,[]]){next [*[1]]} r([1,2,[]]){next [*[1,2]]} -def r(val); a,b,*c = *yield(); test_ok([a,b,c] == val); end +def r(val); a,b,*c = *yield(); test_ok([a,b,c] == val, 2); end r([nil,nil,[]]){next *nil} r([1,nil,[]]){next *1} r([nil,nil,[]]){next *[]} diff --git a/variable.c b/variable.c index d182a703cc..444e2eed62 100644 --- a/variable.c +++ b/variable.c @@ -1207,11 +1207,8 @@ rb_autoload_load(klass, id) VALUE file; file = autoload_delete(klass, id); - if (NIL_P(file)) { - uninitialized_constant(klass, id); - } - if (rb_provided(RSTRING(file)->ptr)) { - uninitialized_constant(klass, id); + if (NIL_P(file) || rb_provided(RSTRING(file)->ptr)) { + const_missing(klass, id); } FL_UNSET(file, FL_TAINT); rb_f_require(Qnil, file); @@ -1268,8 +1265,7 @@ static VALUE rb_const_get_0(klass, id, exclude, recurse) VALUE klass; ID id; - int exclude; - int recurse; + int exclude, recurse; { VALUE value, tmp; int mod_retry = 0; @@ -1429,28 +1425,11 @@ rb_mod_constants(mod) return rb_const_list(rb_mod_const_of(mod, 0)); } -int -rb_const_defined_at(klass, id) - VALUE klass; - ID id; -{ - VALUE value; - - if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) { - if (value == Qundef && NIL_P(autoload_file(klass, id))) - return Qfalse; - return Qtrue; - } - if (klass == rb_cObject) { - return rb_const_defined(klass, id); - } - return Qfalse; -} - -int -rb_const_defined_from(klass, id) +static int +rb_const_defined_0(klass, id, exclude, recurse) VALUE klass; ID id; + int exclude, recurse; { VALUE tmp = klass, value; @@ -1463,30 +1442,37 @@ rb_const_defined_from(klass, id) return Qfalse; return Qtrue; } + if (!recurse && klass != rb_cObject) break; tmp = RCLASS(tmp)->super; } + if (!exclude && BUILTIN_TYPE(klass) == T_MODULE) { + return rb_const_defined(rb_cObject, id); + } return Qfalse; } int -rb_const_defined(klass, id) +rb_const_defined_at(klass, id) VALUE klass; ID id; { - VALUE tmp = klass, value; + return rb_const_defined_0(klass, id, Qtrue, Qfalse); +} - while (tmp) { - if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) { - if (value == Qundef && NIL_P(autoload_file(klass, id))) - return Qfalse; - return Qtrue; - } - tmp = RCLASS(tmp)->super; - } - if (BUILTIN_TYPE(klass) == T_MODULE) { - return rb_const_defined(rb_cObject, id); - } - return Qfalse; +int +rb_const_defined_from(klass, id) + VALUE klass; + ID id; +{ + return rb_const_defined_0(klass, id, Qfalse, Qtrue); +} + +int +rb_const_defined(klass, id) + VALUE klass; + ID id; +{ + return rb_const_defined_0(klass, id, Qtrue, Qtrue); } static void -- cgit v1.2.3