From: nobu@... Date: 2006-07-08T23:28:29+09:00 Subject: Re: [BUG] next in ensure body (Ruby 1.8.x) Hi, At Sat, 8 Jul 2006 18:23:20 +0900, ts wrote in [ruby-core:08170]: > > >>>>> "D" == Dominik Bathon writes: > > D> It seems to work correctly in 1.9. > > Not really, > > > moulon% cat ~/b.rb > def foo; yield; end > p foo { begin; next 5; ensure; 12; end } > moulon% > > moulon% ./ruby -v ~/b.rb > ruby 1.9.0 (2006-07-08) [i686-linux] > nil > moulon% Hmmm, makes sense. * eval.c (next_jump): deal with destination of next. fixed: [ruby-core:08169] Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.616.2.176 diff -p -u -2 -r1.616.2.176 eval.c --- eval.c 26 Jun 2006 15:54:20 -0000 1.616.2.176 +++ eval.c 8 Jul 2006 14:18:23 -0000 @@ -2863,4 +2863,5 @@ class_prefix(self, cpath) NORETURN(static void return_jump _((VALUE))); NORETURN(static void break_jump _((VALUE))); +NORETURN(static void next_jump _((VALUE))); NORETURN(static void unknown_node _((NODE * volatile))); @@ -3201,6 +3202,5 @@ rb_eval(self, n) case NODE_NEXT: CHECK_INTS; - return_value(rb_eval(self, node->nd_stts)); - JUMP_TAG(TAG_NEXT); + next_jump(rb_eval(self, node->nd_stts)); break; @@ -3284,5 +3284,4 @@ rb_eval(self, n) if (state != TAG_RAISE) ruby_errinfo = e_info; if (state) { - if (state == TAG_NEXT) prot_tag->retval = result; JUMP_TAG(state); } @@ -4817,4 +4816,30 @@ break_jump(retval) } +static void +next_jump(retval) + VALUE retval; +{ + struct tag *tt = prot_tag; + + if (retval == Qundef) retval = Qnil; + while (tt) { + switch (tt->tag) { + case PROT_THREAD: + case PROT_YIELD: + case PROT_LOOP: + case PROT_LAMBDA: + case PROT_FUNC: + tt->dst = (VALUE)tt->frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_NEXT); + break; + default: + break; + } + tt = tt->prev; + } + localjump_error("unexpected next", retval, TAG_NEXT); +} + void rb_need_block() Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.914 diff -p -u -2 -r1.914 eval.c --- eval.c 4 Jul 2006 06:22:11 -0000 1.914 +++ eval.c 8 Jul 2006 14:24:50 -0000 @@ -2661,4 +2661,5 @@ class_prefix(VALUE self, NODE *cpath) NORETURN(static void return_jump(VALUE)); NORETURN(static void break_jump(VALUE)); +NORETURN(static void next_jump(VALUE)); NORETURN(static void unknown_node(NODE * volatile)); @@ -2979,6 +2980,5 @@ rb_eval(VALUE self, NODE *n) case NODE_NEXT: CHECK_INTS; - return_value(rb_eval(self, node->nd_stts)); - JUMP_TAG(TAG_NEXT); + next_jump(rb_eval(self, node->nd_stts)); break; @@ -3057,5 +3057,4 @@ rb_eval(VALUE self, NODE *n) if (state != TAG_RAISE) ruby_errinfo = e_info; if (state) { - if (state == TAG_NEXT) prot_tag->retval = result; JUMP_TAG(state); } @@ -4657,4 +4656,31 @@ break_jump(VALUE retval) } +static void +next_jump(VALUE retval) +{ + struct tag *tt = prot_tag; + + if (retval == Qundef) retval = Qnil; + while (tt) { + switch (tt->tag) { + case PROT_THREAD: + /* skip toplevel tag */ + if (!tt->prev) break; + case PROT_YIELD: + case PROT_LAMBDA: + case PROT_LOOP: + case PROT_FUNC: + tt->dst = (VALUE)tt->frame->uniq; + tt->retval = retval; + JUMP_TAG(TAG_NEXT); + break; + default: + break; + } + tt = tt->prev; + } + localjump_error("unexpected next", retval, TAG_NEXT, 0); +} + static VALUE bmcall(VALUE, VALUE); static int method_arity(VALUE); -- Nobu Nakada