* eval.c (proc_invoke): no orphan block check is needed when pcall

is true.

* eval.c (localjump_destination): update localjump condition.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2004-02-27 13:30:00 +00:00
parent 3255bc8fbf
commit bf08067ded
3 changed files with 46 additions and 17 deletions

View File

@ -1,3 +1,10 @@
Fri Feb 27 20:37:09 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (proc_invoke): no orphan block check is needed when pcall
is true.
* eval.c (localjump_destination): update localjump condition.
Fri Feb 27 02:10:49 2004 Yukihiro Matsumoto <matz@ruby-lang.org> Fri Feb 27 02:10:49 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (localjump_destination): lambda should not interfere * eval.c (localjump_destination): lambda should not interfere

45
eval.c
View File

@ -993,8 +993,8 @@ static NODE *compile _((VALUE, char*, int));
static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int)); static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
#define YIELD_PROC_CALL 1 #define YIELD_LAMBDA_CALL 1
#define YIELD_PUBLIC_DEF 2 #define YIELD_PUBLIC_DEF 2
#define YIELD_FUNC_AVALUE 1 #define YIELD_FUNC_AVALUE 1
#define YIELD_FUNC_SVALUE 2 #define YIELD_FUNC_SVALUE 2
@ -4515,20 +4515,26 @@ localjump_destination(state, retval)
{ {
struct tag *tt = prot_tag; struct tag *tt = prot_tag;
VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC; VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC;
int uniq = 0; int yield = Qfalse;
if (retval == Qundef) retval = Qnil; if (retval == Qundef) retval = Qnil;
while (tt) { while (tt) {
if (tt->tag == PROT_YIELD) { if (tt->tag == PROT_YIELD) {
uniq = tt->frame->uniq; yield = Qtrue;
tt = tt->prev;
} }
if ((tt->tag == PROT_THREAD && state == TAG_BREAK) || if ((tt->tag == PROT_THREAD && state == TAG_BREAK) ||
(tt->tag == PROT_PCALL && uniq == 0) || ((tt->tag == PROT_CALL || tt->tag == PROT_PCALL || tt->tag == tag) &&
(tt->tag == PROT_CALL || tt->tag == tag) && tt->frame->uniq == ruby_frame->uniq) { tt->frame->uniq == ruby_frame->uniq)) {
tt->dst = (VALUE)ruby_frame->uniq; tt->dst = (VALUE)ruby_frame->uniq;
tt->retval = retval; tt->retval = retval;
JUMP_TAG(state); JUMP_TAG(state);
} }
if (tt->tag == PROT_PCALL && !yield) {
tt->dst = (VALUE)tt->frame->uniq;
tt->retval = retval;
JUMP_TAG(state);
}
if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) break; if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) break;
if (tt->tag == PROT_THREAD) { if (tt->tag == PROT_THREAD) {
rb_raise(rb_eThreadError, "return jump can't across threads"); rb_raise(rb_eThreadError, "return jump can't across threads");
@ -4552,6 +4558,7 @@ rb_yield_0(val, self, klass, flags, avalue)
int old_vmode; int old_vmode;
struct FRAME frame; struct FRAME frame;
NODE *cnode = ruby_current_node; NODE *cnode = ruby_current_node;
int lambda = flags & YIELD_LAMBDA_CALL;
int state; int state;
if (!rb_block_given_p()) { if (!rb_block_given_p()) {
@ -4590,7 +4597,7 @@ rb_yield_0(val, self, klass, flags, avalue)
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
if (block->var == (NODE*)1) { /* no parameter || */ if (block->var == (NODE*)1) { /* no parameter || */
if ((flags & YIELD_PROC_CALL) && RARRAY(val)->len != 0) { if (lambda && RARRAY(val)->len != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)", rb_raise(rb_eArgError, "wrong number of arguments (%ld for 0)",
RARRAY(val)->len); RARRAY(val)->len);
} }
@ -4605,7 +4612,7 @@ rb_yield_0(val, self, klass, flags, avalue)
if (!avalue) { if (!avalue) {
val = svalue_to_mrhs(val, block->var->nd_head); val = svalue_to_mrhs(val, block->var->nd_head);
} }
massign(self, block->var, val, flags&YIELD_PROC_CALL); massign(self, block->var, val, lambda);
} }
else { else {
int len = 0; int len = 0;
@ -4632,7 +4639,7 @@ rb_yield_0(val, self, klass, flags, avalue)
ruby_current_node = cnode; ruby_current_node = cnode;
} }
} }
assign(self, block->var, val, flags&YIELD_PROC_CALL); assign(self, block->var, val, lambda);
} }
} }
POP_TAG(); POP_TAG();
@ -4645,7 +4652,7 @@ rb_yield_0(val, self, klass, flags, avalue)
ruby_current_node = node; ruby_current_node = node;
PUSH_ITER(block->iter); PUSH_ITER(block->iter);
PUSH_TAG(PROT_YIELD); PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
redo: redo:
if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) { if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
@ -4677,6 +4684,10 @@ rb_yield_0(val, self, klass, flags, avalue)
state = 0; state = 0;
result = prot_tag->retval; result = prot_tag->retval;
break; break;
case TAG_RETURN:
if (!lambda)
result = prot_tag->retval;
break;
default: default:
break; break;
} }
@ -4717,7 +4728,7 @@ VALUE
rb_yield(val) rb_yield(val)
VALUE val; VALUE val;
{ {
return rb_yield_0(val, 0, 0, Qfalse, Qfalse); return rb_yield_0(val, 0, 0, 0, Qfalse);
} }
VALUE VALUE
@ -4733,7 +4744,7 @@ rb_yield_values(n, va_alist)
VALUE ary; VALUE ary;
if (n == 0) { if (n == 0) {
return rb_yield_0(Qundef, 0, 0, Qfalse, Qfalse); return rb_yield_0(Qundef, 0, 0, 0, Qfalse);
} }
ary = rb_ary_new2(n); ary = rb_ary_new2(n);
va_init_list(args, n); va_init_list(args, n);
@ -4741,7 +4752,7 @@ rb_yield_values(n, va_alist)
rb_ary_push(ary, va_arg(args, VALUE)); rb_ary_push(ary, va_arg(args, VALUE));
} }
va_end(args); va_end(args);
return rb_yield_0(ary, 0, 0, Qfalse, Qtrue); return rb_yield_0(ary, 0, 0, 0, Qtrue);
} }
VALUE VALUE
@ -4758,7 +4769,7 @@ rb_yield_splat(values)
avalue = Qtrue; avalue = Qtrue;
} }
} }
return rb_yield_0(values, 0, 0, Qfalse, avalue); return rb_yield_0(values, 0, 0, 0, avalue);
} }
/* /*
@ -4779,7 +4790,7 @@ static VALUE
rb_f_loop() rb_f_loop()
{ {
for (;;) { for (;;) {
rb_yield_0(Qundef, 0, 0, Qfalse, Qfalse); rb_yield_0(Qundef, 0, 0, 0, Qfalse);
CHECK_INTS; CHECK_INTS;
} }
return Qnil; /* dummy */ return Qnil; /* dummy */
@ -7970,8 +7981,8 @@ proc_invoke(proc, args, self, klass)
} }
Data_Get_Struct(proc, struct BLOCK, data); Data_Get_Struct(proc, struct BLOCK, data);
orphan = block_orphan(data); pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
pcall = data->flags & BLOCK_LAMBDA ? YIELD_PROC_CALL : 0; orphan = pcall ? 0 : block_orphan(data);
if (!pcall && RARRAY(args)->len == 1) { if (!pcall && RARRAY(args)->len == 1) {
avalue = Qfalse; avalue = Qfalse;
args = RARRAY(args)->ptr[0]; args = RARRAY(args)->ptr[0];

View File

@ -1127,6 +1127,17 @@ test_ok(lambda{|a|}.arity == 1)
test_ok(lambda{|a,|}.arity == 1) test_ok(lambda{|a,|}.arity == 1)
test_ok(lambda{|a,b|}.arity == 2) test_ok(lambda{|a,b|}.arity == 2)
def yield_in_lambda
lambda{ yield }[]
end
def return_in_lambda
yield_in_lambda{ return true }
false
end
test_ok(return_in_lambda())
def marity_test(m) def marity_test(m)
method = method(m) method = method(m)
test_ok(method.arity == method.to_proc.arity) test_ok(method.arity == method.to_proc.arity)