From: shugo@... (Shugo Maeda) Date: 1999-01-09T23:44:27+09:00 Subject: [ruby-dev:4084] Re: call/cc --Multipart_Sat_Jan__9_23:43:28_1999-1 Content-Type: text/plain; charset=ISO-2022-JP 前田です。 matz@netlab.co.jp (Yukihiro Matsumoto) writes: > たぶんコンテキストの情報量は一緒です.普通はcall/ccのある言 > 語ではこれを使ってスレッドを実装するのは簡単なんですが,逆も > 出来るかな. 以下の変更でとりあえず動きました。 # しかし問題が...。 --Multipart_Sat_Jan__9_23:43:28_1999-1 Content-Type: application/octet-stream; type=patch Content-Disposition: attachment; filename="eval.c.diff" Content-Transfer-Encoding: 7bit --- eval.c.orig Fri Jan 8 16:09:02 1999 +++ eval.c Sat Jan 9 23:17:34 1999 @@ -6816,6 +6816,77 @@ } } +static VALUE rb_cContinuation; + +static VALUE +rb_call_cc(self) + VALUE self; +{ + thread_t th = ALLOC(struct thread); + + th->status = THREAD_RUNNABLE; + + th->status = 0; + th->result = 0; + th->rb_errinfo = Qnil; + + th->stk_ptr = 0; + th->stk_len = 0; + th->stk_max = 0; + th->wait_for = 0; + th->fd = 0; + th->delay = 0.0; + th->join = 0; + + th->frame = 0; + th->scope = 0; + th->klass = 0; + th->dyna_vars = 0; + th->block = 0; + th->iter = 0; + th->tag = 0; + th->rb_errinfo = 0; + th->last_status = 0; + th->last_line = 0; + th->last_match = 0; + th->abort = 0; + + th->thread = Data_Wrap_Struct(rb_cContinuation, thread_mark, + thread_free, th); + + FL_SET(ruby_scope, SCOPE_SHARED); + rb_thread_save_context(th); + if (setjmp(th->context)) { + return th->result; + } + else { + return rb_yield(th->thread); + } +} + +static VALUE +rb_continuation_call(argc, argv, cont) + int argc; + VALUE *argv; + VALUE cont; +{ + thread_t th = rb_thread_check(cont); + + switch (argc) { + case 0: + th->result = Qnil; + break; + case 1: + th->result = *argv; + break; + default: + th->result = rb_ary_new4(argc, argv); + break; + } + rb_thread_restore_context(th, 0); + return th->result; +} + void Init_Thread() { @@ -6855,6 +6926,13 @@ /* allocate main thread */ main_thread = rb_thread_alloc(rb_cThread); + + rb_cContinuation = rb_define_class("Continuation", rb_cObject); + rb_undef_method(CLASS_OF(rb_cContinuation), "new"); + rb_define_method(rb_cContinuation, "call", rb_continuation_call, -1); + rb_define_method(rb_mKernel, "call_with_current_continuation", + rb_call_cc, 0); + rb_define_alias(rb_mKernel, "call_cc", "call_with_current_continuation"); } #endif --Multipart_Sat_Jan__9_23:43:28_1999-1 Content-Type: text/plain; charset=ISO-2022-JP call_cc {|c| $cont = c} print "Hello, World!\n" $cont.call のようなスクリプトを実行すると無限ループになります。 これはSchemeと同じ動作ではないのですが、それはさておき、irb上で、 irb(main):001:0> call_cc {|c| $cont = c} # irb(main):002:0> print "Hello!\n" Hello! nil irb(main):003:0> $cont.call nil irb(main):004:0> $cont # などという不穏な動作をします。 # Continuationがnilになっている? 更に、 irb(main):001:0> cont = call_cc {|c| c} # irb(main):002:0> cont.call(cont) /home/shugo/bin/irb.rb:417: [BUG] class path is not set properly Aborted とすると落ちてしまいます:-( 一体どこがまずいのでしょうか。 # irbでcall_ccした時に何が起こっているのか考えいたら頭がいたく # なってきました。 -- 前田 修吾 (mailto:shugo@aianet.ne.jp) --Multipart_Sat_Jan__9_23:43:28_1999-1--