From: nobu.nakada@... Date: 2003-10-03T13:00:29+09:00 Subject: [ruby-dev:21476] 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などが動かなくなります。 やっぱりrb_catch()でPUSH_SCOPE()する以外ないみたいですが、 [ruby-dev:21448]のような場合はどうしましょうか。 スコープを分ける関数を追加する、というのも考えられますが…。 * eval.c (rb_scope): new API; create new ruby scope and execute given function in it. [ruby-dev:21448] * eval.c (rb_catch): use rb_scope. Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.546 diff -u -2 -p -r1.546 eval.c --- eval.c 2 Oct 2003 08:24:45 -0000 1.546 +++ eval.c 3 Oct 2003 03:21:54 -0000 @@ -10153,4 +10153,24 @@ Init_Thread() } +VALUE +rb_scope(func, data) + VALUE (*func)(); + VALUE data; +{ + int state; + VALUE val = Qnil; /* OK */ + + PUSH_TAG(PROT_NONE); + PUSH_SCOPE(); + if ((state = EXEC_TAG()) == 0) { + val = func(data); + } + POP_SCOPE(); + POP_TAG(); + if (state) JUMP_TAG(state); + + return val; +} + static VALUE rb_f_catch(dmy, tag) @@ -10182,4 +10202,16 @@ catch_i(tag) } +struct catch_arg { + VALUE tag, (*func)(), data; +}; + +static VALUE +catch_scope(data) + VALUE data; +{ + struct catch_arg *arg = (struct catch_arg *)data; + return rb_iterate((VALUE(*)_((VALUE)))catch_i, arg->tag, arg->func, arg->data); +} + VALUE rb_catch(tag, func, data) @@ -10188,17 +10220,10 @@ rb_catch(tag, func, data) VALUE data; { - int state; - VALUE val = Qnil; /* OK */ + struct catch_arg arg; - PUSH_TAG(PROT_NONE); - PUSH_SCOPE(); - if ((state = EXEC_TAG()) == 0) { - val = rb_iterate((VALUE(*)_((VALUE)))catch_i, ID2SYM(rb_intern(tag)), func, data); - } - POP_SCOPE(); - POP_TAG(); - if (state) JUMP_TAG(state); - - return val; + arg.tag = ID2SYM(rb_intern(tag)); + arg.func = func; + arg.data = data; + return rb_scope(catch_scope, (VALUE)&arg); } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦