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:
parent
da84ad63ee
commit
8e9fbbf6d6
4 changed files with 184 additions and 261 deletions
22
ChangeLog
22
ChangeLog
|
@ -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>
|
||||
|
||||
* 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
|
||||
|
||||
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>
|
||||
|
||||
* variable.c (rb_const_get_0): should check constants defined in
|
||||
|
|
345
eval.c
345
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);
|
||||
}
|
||||
POP_TAG();
|
||||
|
||||
POP_ITER();
|
||||
incoming_state = state;
|
||||
if (orphan || pcall ||
|
||||
((ruby_block->tag->flags & BLOCK_LEFT) &&
|
||||
ruby_block->tag->dst == state)) {
|
||||
state &= TAG_MASK;
|
||||
else if (TAG_DST()) {
|
||||
result = prot_tag->retval;
|
||||
}
|
||||
POP_TAG();
|
||||
POP_ITER();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 *[]}
|
||||
|
|
68
variable.c
68
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_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
|
||||
rb_const_defined(klass, id)
|
||||
VALUE klass;
|
||||
ID id;
|
||||
{
|
||||
VALUE tmp = klass, value;
|
||||
|
||||
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;
|
||||
return rb_const_defined_0(klass, id, Qtrue, Qtrue);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue