1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
matz 2003-08-30 00:04:02 +00:00
parent da84ad63ee
commit 8e9fbbf6d6
4 changed files with 184 additions and 261 deletions

View file

@ -1,3 +1,15 @@
Sat Aug 30 03:58:21 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* 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 <shigek@ruby-lang.org> Fri Aug 29 22:35:00 2003 Shigeo Kobayashi <shigek@ruby-lang.org>
* bigdecimal.c *.html: The 2nd arg. for add,sub,mult, and div is 0, * 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 <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tkfont.rb TkFont.new() accepts compound fonts * ext/tk/lib/tkfont.rb TkFont.new() accepts compound fonts
Thu Aug 28 22:07:12 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* 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 <matz@ruby-lang.org> Thu Aug 28 17:30:24 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* variable.c (rb_const_get_0): should check constants defined in * variable.c (rb_const_get_0): should check constants defined in

345
eval.c
View file

@ -602,19 +602,12 @@ static struct SCOPE *top_scope;
ruby_frame = _frame.prev; \ ruby_frame = _frame.prev; \
} while (0) } while (0)
struct BLOCKTAG {
struct RBasic super;
long dst;
long flags;
};
struct BLOCK { struct BLOCK {
NODE *var; NODE *var;
NODE *body; NODE *body;
VALUE self; VALUE self;
struct FRAME frame; struct FRAME frame;
struct SCOPE *scope; struct SCOPE *scope;
struct BLOCKTAG *tag;
VALUE klass; VALUE klass;
NODE *cref; NODE *cref;
int iter; int iter;
@ -629,26 +622,12 @@ struct BLOCK {
}; };
#define BLOCK_D_SCOPE 1 #define BLOCK_D_SCOPE 1
#define BLOCK_DYNAMIC 2 #define BLOCK_LAMBDA 2
#define BLOCK_ORPHAN 4
#define BLOCK_LAMBDA 8
#define BLOCK_LEFT 16
static struct BLOCK *ruby_block; 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 { \ #define PUSH_BLOCK(v,b) do { \
struct BLOCK _block; \ struct BLOCK _block; \
_block.tag = new_blktag(); \
_block.var = v; \ _block.var = v; \
_block.body = b; \ _block.body = b; \
_block.self = self; \ _block.self = self; \
@ -668,12 +647,7 @@ new_blktag()
ruby_block = &_block ruby_block = &_block
#define POP_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; \ ruby_block = _block.prev; \
_block.tag->flags |= BLOCK_LEFT; \
} while (0) } while (0)
struct RVarmap *ruby_dyna_vars; struct RVarmap *ruby_dyna_vars;
@ -845,7 +819,7 @@ struct tag {
jmp_buf buf; jmp_buf buf;
struct FRAME *frame; struct FRAME *frame;
struct iter *iter; struct iter *iter;
ID tag; VALUE tag;
VALUE retval; VALUE retval;
struct SCOPE *scope; struct SCOPE *scope;
int dst; int dst;
@ -864,9 +838,12 @@ static struct tag *prot_tag;
_tag.dst = 0; \ _tag.dst = 0; \
prot_tag = &_tag prot_tag = &_tag
#define PROT_NONE 0 #define PROT_NONE Qfalse /* 0 */
#define PROT_FUNC -1 #define PROT_THREAD Qtrue /* 2 */
#define PROT_THREAD -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)) #define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
@ -877,14 +854,10 @@ static struct tag *prot_tag;
} while (0) } while (0)
#define POP_TAG() \ #define POP_TAG() \
if (_tag.prev) \
_tag.prev->retval = _tag.retval;\
prot_tag = _tag.prev; \ prot_tag = _tag.prev; \
} while (0) } while (0)
#define POP_TMPTAG() \ #define TAG_DST(t) (_tag.dst == (VALUE)_tag.scope)
prot_tag = _tag.prev; \
} while (0)
#define TAG_RETURN 0x1 #define TAG_RETURN 0x1
#define TAG_BREAK 0x2 #define TAG_BREAK 0x2
@ -1561,12 +1534,12 @@ jump_tag_but_local_jump(state)
case TAG_RETURN: case TAG_RETURN:
localjump_error("unexpected return", val, state); localjump_error("unexpected return", val, state);
break; break;
case TAG_NEXT:
localjump_error("unexpected next", val, state);
break;
case TAG_BREAK: case TAG_BREAK:
localjump_error("unexpected break", val, state); localjump_error("unexpected break", val, state);
break; break;
case TAG_NEXT:
localjump_error("unexpected next", val, state);
break;
case TAG_REDO: case TAG_REDO:
localjump_error("unexpected redo", Qnil, state); localjump_error("unexpected redo", Qnil, state);
break; break;
@ -1574,9 +1547,9 @@ jump_tag_but_local_jump(state)
localjump_error("retry outside of rescue clause", Qnil, state); localjump_error("retry outside of rescue clause", Qnil, state);
break; break;
default: default:
JUMP_TAG(state);
break; break;
} }
JUMP_TAG(state);
} }
VALUE VALUE
@ -2163,6 +2136,12 @@ is_defined(self, node, buf)
} }
break; break;
case NODE_COLON3:
if (rb_const_defined_from(rb_cObject, node->nd_mid)) {
return "constant";
}
break;
case NODE_NTH_REF: case NODE_NTH_REF:
if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) { if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) {
sprintf(buf, "$%d", (int)node->nd_nth); sprintf(buf, "$%d", (int)node->nd_nth);
@ -2279,7 +2258,7 @@ call_trace_func(event, node, self, id, klass)
Qundef, 0); Qundef, 0);
} }
if (raised) thread_set_raised(); if (raised) thread_set_raised();
POP_TMPTAG(); /* do not propagate retval */ POP_TAG();
POP_FRAME(); POP_FRAME();
tracing = 0; tracing = 0;
@ -2434,12 +2413,12 @@ class_prefix(self, cpath)
} }
} }
static void return_check _((void));
#define return_value(v) do {\ #define return_value(v) do {\
if ((prot_tag->retval = (v)) == Qundef) {\ if ((prot_tag->retval = (v)) == Qundef) {\
prot_tag->retval = Qnil;\ prot_tag->retval = Qnil;\
}\ }\
} while (0) } while (0)
static void localjump_destination _((int, struct SCOPE*, VALUE));
static VALUE static VALUE
rb_eval(self, n) rb_eval(self, n)
@ -2508,7 +2487,7 @@ rb_eval(self, n)
/* node for speed-up(top-level loop for -n/-p) */ /* node for speed-up(top-level loop for -n/-p) */
case NODE_OPT_N: case NODE_OPT_N:
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_ITER);
switch (state = EXEC_TAG()) { switch (state = EXEC_TAG()) {
case 0: case 0:
opt_n_next: opt_n_next:
@ -2640,7 +2619,7 @@ rb_eval(self, n)
RETURN(Qnil); RETURN(Qnil);
case NODE_WHILE: case NODE_WHILE:
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_ITER);
result = Qnil; result = Qnil;
switch (state = EXEC_TAG()) { switch (state = EXEC_TAG()) {
case 0: case 0:
@ -2672,7 +2651,7 @@ rb_eval(self, n)
RETURN(result); RETURN(result);
case NODE_UNTIL: case NODE_UNTIL:
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_ITER);
result = Qnil; result = Qnil;
switch (state = EXEC_TAG()) { switch (state = EXEC_TAG()) {
case 0: case 0:
@ -2710,7 +2689,7 @@ rb_eval(self, n)
case NODE_ITER: case NODE_ITER:
case NODE_FOR: case NODE_FOR:
{ {
PUSH_TAG(PROT_FUNC); PUSH_TAG(PROT_ITER);
PUSH_BLOCK(node->nd_var, node->nd_body); PUSH_BLOCK(node->nd_var, node->nd_body);
state = EXEC_TAG(); state = EXEC_TAG();
@ -2733,30 +2712,19 @@ rb_eval(self, n)
} }
POP_ITER(); POP_ITER();
} }
else { else if (state == TAG_BREAK && TAG_DST()) {
if (_block.tag->dst == state) { result = prot_tag->retval;
state &= TAG_MASK; state = 0;
if (state == TAG_RETURN || state == TAG_BREAK) { }
result = prot_tag->retval; else if (state == TAG_RETRY) {
} state = 0;
} goto iter_retry;
if (state == TAG_RETRY) {
state = 0;
goto iter_retry;
}
} }
POP_BLOCK(); POP_BLOCK();
POP_TAG(); POP_TAG();
switch (state) { switch (state) {
case 0: case 0:
break; break;
case TAG_BREAK:
break;
case TAG_RETURN:
return_value(result);
/* fall through */
default: default:
JUMP_TAG(state); JUMP_TAG(state);
} }
@ -2764,8 +2732,7 @@ rb_eval(self, n)
break; break;
case NODE_BREAK: case NODE_BREAK:
return_value(rb_eval(self, node->nd_stts)); localjump_destination(TAG_BREAK, ruby_scope, rb_eval(self, node->nd_stts));
JUMP_TAG(TAG_BREAK);
break; break;
case NODE_NEXT: case NODE_NEXT:
@ -2938,9 +2905,7 @@ rb_eval(self, n)
break; break;
case NODE_RETURN: case NODE_RETURN:
return_value(rb_eval(self, node->nd_stts)); localjump_destination(TAG_RETURN, ruby_scope, rb_eval(self, node->nd_stts));
return_check();
JUMP_TAG(TAG_RETURN);
break; break;
case NODE_ARGSCAT: case NODE_ARGSCAT:
@ -3048,13 +3013,14 @@ rb_eval(self, n)
{ {
struct FRAME frame; struct FRAME frame;
NODE *saved_cref = 0; NODE *saved_cref = 0;
int jump_chain = Qfalse;
frame = *ruby_frame; frame = *ruby_frame;
frame.tmp = ruby_frame; frame.tmp = ruby_frame;
ruby_frame = &frame; ruby_frame = &frame;
PUSH_SCOPE(); PUSH_SCOPE();
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_PCALL);
if (node->nd_rval) { if (node->nd_rval) {
saved_cref = ruby_cref; saved_cref = ruby_cref;
ruby_cref = (NODE*)node->nd_rval; ruby_cref = (NODE*)node->nd_rval;
@ -3073,12 +3039,24 @@ rb_eval(self, n)
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
result = rb_eval(self, node->nd_next); result = rb_eval(self, node->nd_next);
} }
else if (TAG_DST()) {
result = prot_tag->retval;
jump_chain = Qtrue;
}
POP_TAG(); POP_TAG();
POP_SCOPE(); POP_SCOPE();
ruby_frame = frame.tmp; ruby_frame = frame.tmp;
if (saved_cref) if (saved_cref)
ruby_cref = 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; break;
@ -3271,7 +3249,7 @@ rb_eval(self, n)
break; break;
case NODE_COLON3: case NODE_COLON3:
result = rb_const_get_at(rb_cObject, node->nd_mid); result = rb_const_get_from(rb_cObject, node->nd_mid);
break; break;
case NODE_NTH_REF: case NODE_NTH_REF:
@ -4024,6 +4002,37 @@ rb_f_block_given_p()
return Qfalse; 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 static VALUE
rb_yield_0(val, self, klass, flags, avalue) rb_yield_0(val, self, klass, flags, avalue)
VALUE val, self, klass; /* OK */ VALUE val, self, klass; /* OK */
@ -4163,12 +4172,6 @@ rb_yield_0(val, self, klass, flags, avalue)
state = 0; state = 0;
result = prot_tag->retval; result = prot_tag->retval;
break; break;
case TAG_BREAK:
case TAG_RETURN:
state |= (serial++ << 8);
state |= 0x10;
block->tag->dst = state;
break;
default: default:
break; break;
} }
@ -4201,17 +4204,7 @@ rb_yield_0(val, self, klass, flags, avalue)
ruby_scope = old_scope; ruby_scope = old_scope;
scope_vmode = old_vmode; scope_vmode = old_vmode;
ruby_current_node = cnode; ruby_current_node = cnode;
if (state) { if (state) JUMP_TAG(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);
}
return result; return result;
} }
@ -4430,24 +4423,20 @@ rb_iterate(it_proc, data1, bl_proc, data2)
PUSH_ITER(ITER_PRE); PUSH_ITER(ITER_PRE);
PUSH_BLOCK(0, node); PUSH_BLOCK(0, node);
PUSH_TAG(PROT_NONE);
PUSH_TAG(PROT_ITER);
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
iter_retry: iter_retry:
retval = (*it_proc)(data1); retval = (*it_proc)(data1);
} }
else { else if (state == TAG_BREAK && TAG_DST()) {
if (ruby_block->tag->dst == state) { retval = prot_tag->retval;
state &= TAG_MASK; state = 0;
if (state == TAG_RETURN || state == TAG_BREAK) { }
retval = prot_tag->retval; else if (state == TAG_RETRY) {
} state = 0;
} goto iter_retry;
if (state == TAG_RETRY) {
state = 0;
goto iter_retry;
}
} }
POP_TAG(); POP_TAG();
POP_BLOCK(); POP_BLOCK();
@ -4456,13 +4445,6 @@ rb_iterate(it_proc, data1, bl_proc, data2)
switch (state) { switch (state) {
case 0: case 0:
break; break;
case TAG_BREAK:
break;
case TAG_RETURN:
return_value(retval);
/* fall through */
default: default:
JUMP_TAG(state); JUMP_TAG(state);
} }
@ -4607,7 +4589,6 @@ rb_ensure(b_proc, data1, e_proc, data2)
retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */ retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
(*e_proc)(data2); (*e_proc)(data2);
if (prot_tag) return_value(retval); if (prot_tag) return_value(retval);
if (state) JUMP_TAG(state); if (state) JUMP_TAG(state);
return result; return result;
} }
@ -5051,7 +5032,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
} }
result = rb_eval(recv, body); result = rb_eval(recv, body);
} }
else if (state == TAG_RETURN) { else if (state == TAG_RETURN && TAG_DST()) {
result = prot_tag->retval; result = prot_tag->retval;
state = 0; state = 0;
} }
@ -5067,10 +5048,13 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
case 0: case 0:
break; break;
case TAG_BREAK:
case TAG_RETURN:
JUMP_TAG(state);
break;
case TAG_RETRY: case TAG_RETRY:
if (rb_block_given_p()) { if (rb_block_given_p()) JUMP_TAG(state);
JUMP_TAG(state);
}
/* fall through */ /* fall through */
default: default:
jump_tag_but_local_jump(state); jump_tag_but_local_jump(state);
@ -5482,13 +5466,6 @@ eval(self, src, scope, file, line)
for (tag=prot_tag; tag; tag=tag->prev) { for (tag=prot_tag; tag; tag=tag->prev) {
scope_dup(tag->scope); 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) { for (vars = ruby_dyna_vars; vars; vars = vars->next) {
FL_SET(vars, DVAR_DONT_RECYCLE); FL_SET(vars, DVAR_DONT_RECYCLE);
} }
@ -6708,7 +6685,6 @@ blk_mark(data)
rb_gc_mark((VALUE)data->self); rb_gc_mark((VALUE)data->self);
rb_gc_mark((VALUE)data->dyna_vars); rb_gc_mark((VALUE)data->dyna_vars);
rb_gc_mark((VALUE)data->cref); rb_gc_mark((VALUE)data->cref);
rb_gc_mark((VALUE)data->tag);
rb_gc_mark(data->wrapper); rb_gc_mark(data->wrapper);
rb_gc_mark(data->block_obj); rb_gc_mark(data->block_obj);
data = data->prev; data = data->prev;
@ -6755,7 +6731,6 @@ blk_copy_prev(block)
tmp->frame.flags |= FRAME_MALLOC; tmp->frame.flags |= FRAME_MALLOC;
} }
scope_dup(tmp->scope); scope_dup(tmp->scope);
tmp->tag->flags |= BLOCK_DYNAMIC;
for (vars = tmp->dyna_vars; vars; vars = vars->next) { for (vars = tmp->dyna_vars; vars; vars = vars->next) {
if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
@ -6840,8 +6815,6 @@ rb_f_binding(self)
else { else {
data->prev = 0; data->prev = 0;
} }
data->flags |= BLOCK_DYNAMIC;
data->tag->flags |= BLOCK_DYNAMIC;
for (p = data; p; p = p->prev) { for (p = data; p; p = p->prev) {
for (vars = p->dyna_vars; vars; vars = vars->next) { for (vars = p->dyna_vars; vars; vars = vars->next) {
@ -6940,8 +6913,6 @@ proc_alloc(klass, proc)
else { else {
data->prev = 0; data->prev = 0;
} }
data->flags |= BLOCK_DYNAMIC;
data->tag->flags |= BLOCK_DYNAMIC;
for (p = data; p; p = p->prev) { for (p = data; p; p = p->prev) {
for (vars = p->dyna_vars; vars; vars = vars->next) { for (vars = p->dyna_vars; vars; vars = vars->next) {
@ -6996,8 +6967,7 @@ static int
block_orphan(data) block_orphan(data)
struct BLOCK *data; struct BLOCK *data;
{ {
if ((data->tag->flags & BLOCK_ORPHAN) && if (data->scope->flags & SCOPE_NOSTACK) {
(data->scope->flags & SCOPE_NOSTACK)) {
return 1; return 1;
} }
if (data->orig_thread != rb_thread_current()) { if (data->orig_thread != rb_thread_current()) {
@ -7014,8 +6984,8 @@ proc_invoke(proc, args, self, klass)
struct BLOCK * volatile old_block; struct BLOCK * volatile old_block;
struct BLOCK _block; struct BLOCK _block;
struct BLOCK *data; struct BLOCK *data;
volatile VALUE result = Qnil; volatile VALUE result = Qundef;
int state, incoming_state; int state;
volatile int orphan; volatile int orphan;
volatile int safe = ruby_safe_level; volatile int safe = ruby_safe_level;
volatile VALUE old_wrapper = ruby_wrapper; volatile VALUE old_wrapper = ruby_wrapper;
@ -7043,21 +7013,17 @@ proc_invoke(proc, args, self, klass)
PUSH_ITER(ITER_CUR); PUSH_ITER(ITER_CUR);
ruby_frame->iter = ITER_CUR; ruby_frame->iter = ITER_CUR;
PUSH_TAG(PROT_NONE); PUSH_TAG(pcall ? PROT_PCALL : PROT_CALL);
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
proc_set_safe_level(proc); proc_set_safe_level(proc);
result = rb_yield_0(args, self, self!=Qundef?CLASS_OF(self):0, pcall, Qtrue); result = rb_yield_0(args, self, self!=Qundef?CLASS_OF(self):0, pcall, Qtrue);
} }
POP_TAG(); else if (TAG_DST()) {
result = prot_tag->retval;
POP_ITER();
incoming_state = state;
if (orphan || pcall ||
((ruby_block->tag->flags & BLOCK_LEFT) &&
ruby_block->tag->dst == state)) {
state &= TAG_MASK;
} }
POP_TAG();
POP_ITER();
ruby_block = old_block; ruby_block = old_block;
ruby_wrapper = old_wrapper; ruby_wrapper = old_wrapper;
ruby_dyna_vars = old_dvars; ruby_dyna_vars = old_dvars;
@ -7073,18 +7039,15 @@ proc_invoke(proc, args, self, klass)
/* fall through */ /* fall through */
case TAG_BREAK: case TAG_BREAK:
case TAG_RETURN: case TAG_RETURN:
if (pcall) { if (pcall) break;
result = prot_tag->retval; if (orphan) { /* orphan block */
break;
}
else if (orphan) { /* orphan block */
char mesg[32]; char mesg[32];
snprintf(mesg, sizeof mesg, "%s from proc-closure", snprintf(mesg, sizeof mesg, "%s from proc-closure",
state == TAG_BREAK ? "break" : "return"); state == TAG_BREAK ? "break" : "return");
localjump_error(mesg, prot_tag->retval, state); localjump_error(mesg, prot_tag->retval, state);
} }
else if (state == incoming_state) { if (result != Qundef) {
ruby_block->tag->dst = incoming_state; localjump_destination(state, ruby_scope, result);
} }
default: default:
JUMP_TAG(state); JUMP_TAG(state);
@ -7147,7 +7110,7 @@ proc_eq(self, other)
if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse; if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
Data_Get_Struct(self, struct BLOCK, data); Data_Get_Struct(self, struct BLOCK, data);
Data_Get_Struct(other, struct BLOCK, data2); Data_Get_Struct(other, struct BLOCK, data2);
if (data->tag == data2->tag) return Qtrue; if (data->body == data2->body) return Qtrue;
return Qfalse; return Qfalse;
} }
@ -7166,12 +7129,12 @@ proc_to_s(self, other)
if ((node = data->frame.node) || (node = data->body)) { if ((node = data->frame.node) || (node = data->body)) {
len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3; len += strlen(node->nd_file) + 2 + (SIZEOF_LONG*CHAR_BIT-NODE_LSHIFT)/3;
str = rb_str_new(0, len); 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)); node->nd_file, nd_line(node));
} }
else { else {
str = rb_str_new(0, len); 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); RSTRING(str)->len = strlen(RSTRING(str)->ptr);
if (OBJ_TAINTED(self)) OBJ_TAINT(str); if (OBJ_TAINTED(self)) OBJ_TAINT(str);
@ -7262,7 +7225,7 @@ block_pass(self, node)
PUSH_ITER(ITER_PRE); PUSH_ITER(ITER_PRE);
ruby_frame->iter = ITER_PRE; ruby_frame->iter = ITER_PRE;
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_ITER);
state = EXEC_TAG(); state = EXEC_TAG();
if (state == 0) { if (state == 0) {
retry: retry:
@ -7271,26 +7234,11 @@ block_pass(self, node)
ruby_safe_level = safe; ruby_safe_level = safe;
result = rb_eval(self, node->nd_iter); result = rb_eval(self, node->nd_iter);
} }
if (_block.tag->dst == state) { else if (state == TAG_BREAK && TAG_DST()) {
if (orphan) { result = prot_tag->retval;
state &= TAG_MASK; state = 0;
}
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;
}
}
} }
if (state == TAG_RETRY) { else if (state == TAG_RETRY) {
state = 0; state = 0;
goto retry; goto retry;
} }
@ -7302,9 +7250,6 @@ block_pass(self, node)
switch (state) {/* escape from orphan block */ switch (state) {/* escape from orphan block */
case 0: case 0:
break; break;
case TAG_BREAK:
result = prot_tag->retval;
break;
case TAG_RETURN: case TAG_RETURN:
if (orphan) { if (orphan) {
localjump_error("return from proc-closure", prot_tag->retval, state); localjump_error("return from proc-closure", prot_tag->retval, state);
@ -7833,8 +7778,6 @@ win32_set_exception_list(p)
#endif #endif
#endif #endif
static VALUE rb_eThreadError;
int rb_thread_pending = 0; int rb_thread_pending = 0;
VALUE rb_cThread; VALUE rb_cThread;
@ -9932,14 +9875,6 @@ rb_callcc(self)
for (tag=prot_tag; tag; tag=tag->prev) { for (tag=prot_tag; tag; tag=tag->prev) {
scope_dup(tag->scope); 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; th->thread = curr_thread->thread;
for (vars = th->dyna_vars; vars; vars = vars->next) { for (vars = th->dyna_vars; vars; vars = vars->next) {
@ -10160,15 +10095,14 @@ rb_f_catch(dmy, tag)
VALUE dmy, tag; VALUE dmy, tag;
{ {
int state; int state;
ID t;
VALUE val = Qnil; /* OK */ VALUE val = Qnil; /* OK */
t = rb_to_id(tag); tag = ID2SYM(rb_to_id(tag));
PUSH_TAG(t); PUSH_TAG(tag);
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
val = rb_yield_0(tag, 0, 0, Qfalse, Qfalse); 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; val = prot_tag->retval;
state = 0; state = 0;
} }
@ -10180,9 +10114,9 @@ rb_f_catch(dmy, tag)
static VALUE static VALUE
catch_i(tag) 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 VALUE
@ -10191,7 +10125,7 @@ rb_catch(tag, func, data)
VALUE (*func)(); VALUE (*func)();
VALUE data; 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 static VALUE
@ -10200,28 +10134,27 @@ rb_f_throw(argc, argv)
VALUE *argv; VALUE *argv;
{ {
VALUE tag, value; VALUE tag, value;
ID t;
struct tag *tt = prot_tag; struct tag *tt = prot_tag;
rb_scan_args(argc, argv, "11", &tag, &value); rb_scan_args(argc, argv, "11", &tag, &value);
t = rb_to_id(tag); tag = ID2SYM(rb_to_id(tag));
while (tt) { while (tt) {
if (tt->tag == t) { if (tt->tag == tag) {
tt->dst = t; tt->dst = tag;
tt->retval = value;
break; break;
} }
if (tt->tag == PROT_THREAD) { if (tt->tag == PROT_THREAD) {
rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%lx", rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%lx",
rb_id2name(t), rb_id2name(SYM2ID(tag)),
curr_thread); curr_thread);
} }
tt = tt->prev; tt = tt->prev;
} }
if (!tt) { 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(); rb_trap_restore_mask();
JUMP_TAG(TAG_THROW); JUMP_TAG(TAG_THROW);
#ifndef __GNUC__ #ifndef __GNUC__
@ -10235,26 +10168,8 @@ rb_throw(tag, val)
VALUE val; VALUE val;
{ {
VALUE argv[2]; VALUE argv[2];
ID t = rb_intern(tag);
argv[0] = ID2SYM(t); argv[0] = ID2SYM(rb_intern(tag));
argv[1] = val; argv[1] = val;
rb_f_throw(2, argv); 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;
}
}

View file

@ -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]]; end; test_ok([a,b,c] == [1,nil,[]])
a,b,*c = loop do break *[*[1,2]]; end; test_ok([a,b,c] == [1,2,[]]) 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}
r(nil){next nil} r(nil){next nil}
r(1){next 1} r(1){next 1}
@ -396,7 +396,7 @@ r(nil){next *[*[]]}
r(1){next *[*[1]]} r(1){next *[*[1]]}
r([1,2]){next *[*[1,2]]} 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}
r([nil]){next nil} r([nil]){next nil}
r([1]){next 1} r([1]){next 1}
@ -409,7 +409,7 @@ r([[]]){next [*[]]}
r([[1]]){next [*[1]]} r([[1]]){next [*[1]]}
r([[1,2]]){next [*[1,2]]} 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([nil]){next *nil}
r([1]){next *1} r([1]){next *1}
r([nil]){next *[]} r([nil]){next *[]}
@ -421,7 +421,7 @@ r([nil]){next *[*[]]}
r([1]){next *[*[1]]} r([1]){next *[*[1]]}
r([1,2]){next *[*[1,2]]} 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}
r([nil,nil,[]]){next nil} r([nil,nil,[]]){next nil}
r([1,nil,[]]){next 1} r([1,nil,[]]){next 1}
@ -434,7 +434,7 @@ r([nil,nil,[]]){next [*[]]}
r([1,nil,[]]){next [*[1]]} r([1,nil,[]]){next [*[1]]}
r([1,2,[]]){next [*[1,2]]} 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([nil,nil,[]]){next *nil}
r([1,nil,[]]){next *1} r([1,nil,[]]){next *1}
r([nil,nil,[]]){next *[]} r([nil,nil,[]]){next *[]}

View file

@ -1207,11 +1207,8 @@ rb_autoload_load(klass, id)
VALUE file; VALUE file;
file = autoload_delete(klass, id); file = autoload_delete(klass, id);
if (NIL_P(file)) { if (NIL_P(file) || rb_provided(RSTRING(file)->ptr)) {
uninitialized_constant(klass, id); const_missing(klass, id);
}
if (rb_provided(RSTRING(file)->ptr)) {
uninitialized_constant(klass, id);
} }
FL_UNSET(file, FL_TAINT); FL_UNSET(file, FL_TAINT);
rb_f_require(Qnil, file); rb_f_require(Qnil, file);
@ -1268,8 +1265,7 @@ static VALUE
rb_const_get_0(klass, id, exclude, recurse) rb_const_get_0(klass, id, exclude, recurse)
VALUE klass; VALUE klass;
ID id; ID id;
int exclude; int exclude, recurse;
int recurse;
{ {
VALUE value, tmp; VALUE value, tmp;
int mod_retry = 0; int mod_retry = 0;
@ -1429,28 +1425,11 @@ rb_mod_constants(mod)
return rb_const_list(rb_mod_const_of(mod, 0)); return rb_const_list(rb_mod_const_of(mod, 0));
} }
int static int
rb_const_defined_at(klass, id) rb_const_defined_0(klass, id, exclude, recurse)
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)
VALUE klass; VALUE klass;
ID id; ID id;
int exclude, recurse;
{ {
VALUE tmp = klass, value; VALUE tmp = klass, value;
@ -1463,30 +1442,37 @@ rb_const_defined_from(klass, id)
return Qfalse; return Qfalse;
return Qtrue; return Qtrue;
} }
if (!recurse && klass != rb_cObject) break;
tmp = RCLASS(tmp)->super; tmp = RCLASS(tmp)->super;
} }
if (!exclude && BUILTIN_TYPE(klass) == T_MODULE) {
return rb_const_defined(rb_cObject, id);
}
return Qfalse; return Qfalse;
} }
int
rb_const_defined_at(klass, id)
VALUE klass;
ID id;
{
return rb_const_defined_0(klass, id, Qtrue, Qfalse);
}
int
rb_const_defined_from(klass, id)
VALUE klass;
ID id;
{
return rb_const_defined_0(klass, id, Qfalse, Qtrue);
}
int int
rb_const_defined(klass, id) rb_const_defined(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
VALUE tmp = klass, value; return rb_const_defined_0(klass, id, Qtrue, Qtrue);
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;
} }
static void static void