From: nobu.nakada@... Date: 2003-10-07T12:45:29+09:00 Subject: [ruby-dev:21536] Re: break from block yielded in until なかだです。 At Tue, 30 Sep 2003 21:26:34 +0900, Yukihiro Matsumoto wrote: > |うーん、rb_iterate()でPUSH_SCOPE()してしまっていいんだろうか。 > |rb_catch()でしたほうがいいような気がしなくもない。 > > これではまずいんです。rb_iter_break()がちゃんと動作しなくな > るため、Enumerable#findなどが動かなくなります。 どうも[ruby-talk:83729]も同じ原因のように思えます。 Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.551 diff -u -2 -p -r1.551 eval.c --- eval.c 6 Oct 2003 17:59:52 -0000 1.551 +++ eval.c 7 Oct 2003 03:20:07 -0000 @@ -4078,5 +4078,5 @@ rb_yield_0(val, self, klass, flags, aval NODE *cnode = ruby_current_node; int state; - static unsigned serial = 1; + volatile int ifunc = 0; if (!rb_block_given_p()) { @@ -4173,5 +4173,5 @@ rb_yield_0(val, self, klass, flags, aval result = Qnil; } - else if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) { + else if (nd_type(node) == NODE_CFUNC || (ifunc = nd_type(node) == NODE_IFUNC)) { if (node->nd_state == YIELD_FUNC_AVALUE) { if (!avalue) { @@ -4186,4 +4186,5 @@ rb_yield_0(val, self, klass, flags, aval val = Qnil; } + if (ifunc) ruby_scope = (struct SCOPE *)node->u3.value; result = (*node->nd_cfnc)(val, node->nd_tval, self); } @@ -4229,5 +4230,5 @@ rb_yield_0(val, self, klass, flags, aval ruby_cref = (NODE*)old_cref; ruby_wrapper = old_wrapper; - if (ruby_scope->flags & SCOPE_DONT_RECYCLE) + if (!ifunc && (ruby_scope->flags & SCOPE_DONT_RECYCLE)) scope_dup(old_scope); ruby_scope = old_scope; @@ -4453,6 +4454,7 @@ rb_iterate(it_proc, data1, bl_proc, data PUSH_ITER(ITER_PRE); PUSH_BLOCK(0, node); - + PUSH_SCOPE(); PUSH_TAG(PROT_ITER); + node->u3.value = (VALUE)ruby_scope; state = EXEC_TAG(); if (state == 0) { @@ -4469,4 +4471,5 @@ rb_iterate(it_proc, data1, bl_proc, data } POP_TAG(); + POP_SCOPE(); POP_BLOCK(); POP_ITER(); -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦