From bf08067ded3a38c12924cbb02289162e11792547 Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 27 Feb 2004 13:30:00 +0000 Subject: [PATCH] * 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 --- ChangeLog | 7 +++++++ eval.c | 45 ++++++++++++++++++++++++++++----------------- sample/test.rb | 11 +++++++++++ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2afaacff9b..d058adbea7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Fri Feb 27 20:37:09 2004 Yukihiro Matsumoto + + * 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 * eval.c (localjump_destination): lambda should not interfere diff --git a/eval.c b/eval.c index 78141504a8..292f6c8610 100644 --- a/eval.c +++ b/eval.c @@ -993,8 +993,8 @@ static NODE *compile _((VALUE, char*, int)); static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int)); -#define YIELD_PROC_CALL 1 -#define YIELD_PUBLIC_DEF 2 +#define YIELD_LAMBDA_CALL 1 +#define YIELD_PUBLIC_DEF 2 #define YIELD_FUNC_AVALUE 1 #define YIELD_FUNC_SVALUE 2 @@ -4515,20 +4515,26 @@ localjump_destination(state, retval) { struct tag *tt = prot_tag; VALUE tag = (state == TAG_BREAK) ? PROT_ITER : PROT_FUNC; - int uniq = 0; + int yield = Qfalse; if (retval == Qundef) retval = Qnil; while (tt) { if (tt->tag == PROT_YIELD) { - uniq = tt->frame->uniq; + yield = Qtrue; + tt = tt->prev; } if ((tt->tag == PROT_THREAD && state == TAG_BREAK) || - (tt->tag == PROT_PCALL && uniq == 0) || - (tt->tag == PROT_CALL || tt->tag == tag) && tt->frame->uniq == ruby_frame->uniq) { + ((tt->tag == PROT_CALL || tt->tag == PROT_PCALL || tt->tag == tag) && + tt->frame->uniq == ruby_frame->uniq)) { tt->dst = (VALUE)ruby_frame->uniq; tt->retval = retval; 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_THREAD) { 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; struct FRAME frame; NODE *cnode = ruby_current_node; + int lambda = flags & YIELD_LAMBDA_CALL; int state; if (!rb_block_given_p()) { @@ -4590,7 +4597,7 @@ rb_yield_0(val, self, klass, flags, avalue) PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { 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)", RARRAY(val)->len); } @@ -4605,7 +4612,7 @@ rb_yield_0(val, self, klass, flags, avalue) if (!avalue) { 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 { int len = 0; @@ -4632,7 +4639,7 @@ rb_yield_0(val, self, klass, flags, avalue) ruby_current_node = cnode; } } - assign(self, block->var, val, flags&YIELD_PROC_CALL); + assign(self, block->var, val, lambda); } } POP_TAG(); @@ -4645,7 +4652,7 @@ rb_yield_0(val, self, klass, flags, avalue) ruby_current_node = node; PUSH_ITER(block->iter); - PUSH_TAG(PROT_YIELD); + PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD); if ((state = EXEC_TAG()) == 0) { redo: 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; result = prot_tag->retval; break; + case TAG_RETURN: + if (!lambda) + result = prot_tag->retval; + break; default: break; } @@ -4717,7 +4728,7 @@ VALUE rb_yield(val) VALUE val; { - return rb_yield_0(val, 0, 0, Qfalse, Qfalse); + return rb_yield_0(val, 0, 0, 0, Qfalse); } VALUE @@ -4733,7 +4744,7 @@ rb_yield_values(n, va_alist) VALUE ary; 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); va_init_list(args, n); @@ -4741,7 +4752,7 @@ rb_yield_values(n, va_alist) rb_ary_push(ary, va_arg(args, VALUE)); } va_end(args); - return rb_yield_0(ary, 0, 0, Qfalse, Qtrue); + return rb_yield_0(ary, 0, 0, 0, Qtrue); } VALUE @@ -4758,7 +4769,7 @@ rb_yield_splat(values) 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() { for (;;) { - rb_yield_0(Qundef, 0, 0, Qfalse, Qfalse); + rb_yield_0(Qundef, 0, 0, 0, Qfalse); CHECK_INTS; } return Qnil; /* dummy */ @@ -7970,8 +7981,8 @@ proc_invoke(proc, args, self, klass) } Data_Get_Struct(proc, struct BLOCK, data); - orphan = block_orphan(data); - pcall = data->flags & BLOCK_LAMBDA ? YIELD_PROC_CALL : 0; + pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0; + orphan = pcall ? 0 : block_orphan(data); if (!pcall && RARRAY(args)->len == 1) { avalue = Qfalse; args = RARRAY(args)->ptr[0]; diff --git a/sample/test.rb b/sample/test.rb index 65cfcad475..d37c978774 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -1127,6 +1127,17 @@ test_ok(lambda{|a|}.arity == 1) test_ok(lambda{|a,|}.arity == 1) 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) method = method(m) test_ok(method.arity == method.to_proc.arity)