[#10793] 今度こそ (patch of the ruby-1.4.6 for NT4.0&VC4.0 on DEC Alpha.) — kou@...1609.sip.eee.yamaguchi-u.ac.jp (Koichi Okada)
岡田です。
10 messages
2000/09/01
[#10815] Re: 今度こそ (patch of the ruby-1.4.6 for NT4.0&VC4.0on DEC Alpha.)
— nobu.nakada@...
2000/09/03
なかだです。
[#10816] Re: 今度こそ (patchof the ruby-1.4.6 for NT4.0&VC4.0on DEC Alpha.)
— kou@...1609.sip.eee.yamaguchi-u.ac.jp (Koichi Okada)
2000/09/04
岡田です。
[#10820] Re: 今度こそ (patchof the ruby-1.4.6 for NT4.0&VC4.0on DEC Alpha.)
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/04
なかだ@ゴミです。
[#10866] Class Variable (sono 2) — Shin-ichiro HARA <sinara@...>
原です。
5 messages
2000/09/08
[#10882] setenv,unsetenv — Takaaki Tateishi <ttate@...>
立石です.
6 messages
2000/09/11
[#10894] Forward: [ruby-ext:01274] Re: 多重代入での to_a (Re: Ruby/Python doesn't work with Ruby 1.6) — matz@... (Yukihiro Matsumoto)
まつもと ゆきひろです
3 messages
2000/09/11
[#10897] Re: [CVS 266] "matz: 1.6.0 final (hopufully)" — WATANABE Hirofumi <Hirofumi.Watanabe@...>
わたなべです.
6 messages
2000/09/12
[#10903] Class Variable と継承 — Kazuhiro NISHIYAMA <zn@...>
メソッドや定数は子クラスの方が常に優先されるみたいですが
8 messages
2000/09/12
[#10914] Re: Class Variable と継承
— Yasushi Shoji <yashi@...>
2000/09/13
At Wed, 13 Sep 2000 02:57:29 +0900,
[#10920] SIGINT on windows — "Nobuyoshi.Nakada" <nobu.nakada@...>
なかだです。
17 messages
2000/09/14
[#11077] Re: SIGINT on windows
— matz@... (Yukihiro Matsumoto)
2000/09/27
まつもと ゆきひろです
[#11080] Re: SIGINT on windows
— Katsuyuki Komatsu <komatsu@...>
2000/09/27
小松です.
[#11081] Re: SIGINT on windows
— matz@... (Yukihiro Matsumoto)
2000/09/27
まつもと ゆきひろです
[#11089] Re: SIGINT on windows
— nobu.nakada@...
2000/09/27
なかだです。
[#11094] Re: SIGINT on windows
— nobu.nakada@...
2000/09/28
なかだです。
[#10921] proper tail recursion — Shugo Maeda <shugo@...>
前田です。
5 messages
2000/09/14
[#10943] Passing []/String as argument — Jun Adachi <adachi@...>
安達@沖データと申します。
2 messages
2000/09/18
[#10944] dummy DLL on Windows — "Nobuyoshi.Nakada" <nobu.nakada@...>
なかだです。
19 messages
2000/09/18
[#10955] Re: dummy DLL on Windows
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10963] Re: dummy DLL on Windows
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/19
なかだです。
[#10964] Re: dummy DLL on Windows
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10967] Re: dummy DLL on Windows
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10970] Re: dummy DLL on Windows
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/19
なかだです。
[#10971] Re: dummy DLL on Windows
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10975] Re: dummy DLL on Windows
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/19
なかだです。
[#10976] Re: dummy DLL on Windows
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10977] Re: dummy DLL on Windows
— matz@... (Yukihiro Matsumoto)
2000/09/19
まつもと ゆきひろです
[#10979] Re: dummy DLL on Windows
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/20
なかだです。
[#10946] require "marshal" failure — Katsuyuki Komatsu <komatsu@...>
小松です.
9 messages
2000/09/18
[#10949] Re: require "marshal" failure
— matz@... (Yukihiro Matsumoto)
2000/09/18
まつもと ゆきひろです
[#10953] Re: require "marshal" failure
— WATANABE Hirofumi <eban@...>
2000/09/19
わたなべです.
[#10948] File::Constants — Yasushi Shoji <yashi@...>
Wed Oct 22 12:52:30 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
5 messages
2000/09/18
[#10978] [PATCH] require in require — "Nobuyoshi.Nakada" <nobu.nakada@...>
なかだです。
15 messages
2000/09/20
[#10981] Re: [PATCH] require in require
— matz@... (Yukihiro Matsumoto)
2000/09/20
まつもと ゆきひろです
[#10982] ruby1.6.0 on win32c
— Akira Muraki <a-muraki@...>
2000/09/20
村木@日立ITです。
[#10993] Re: ruby1.6.0 on win32c
— WATANABE Hirofumi <eban@...>
2000/09/21
わたなべです.
[#10985] httphead.rb proxy version problem — Katsuyuki Komatsu <komatsu@...>
小松です.
16 messages
2000/09/20
[#10989] Re: httphead.rb proxy version problem
— Minero Aoki <aamine@...>
2000/09/20
あおきです。
[#10992] Re: httphead.rb proxy version problem
— Katsuyuki Komatsu <komatsu@...>
2000/09/21
小松です。
[#10996] Re: httphead.rb proxy version problem
— matz@... (Yukihiro Matsumoto)
2000/09/21
まつもと ゆきひろです
[#10997] Re: httphead.rb proxy version problem
— matz@... (Yukihiro Matsumoto)
2000/09/21
まつもと ゆきひろです
[#11006] lstat — WATANABE Hirofumi <eban@...>
わたなべです.
14 messages
2000/09/21
[#11007] Re: lstat
— matz@... (Yukihiro Matsumoto)
2000/09/21
まつもと ゆきひろです
[#11008] Re: lstat
— matz@... (Yukihiro Matsumoto)
2000/09/21
まつもと ゆきひろです
[#11028] regex.c warning of alpha — Katsuyuki Komatsu <komatsu@...>
小松です。
7 messages
2000/09/22
[#11037] RUBYLIB_PRIFIX at emx/gcc — kenn@...
長沢です。
7 messages
2000/09/22
[#11052] ruby-1.6.1-20000921-i386-cygwin and Thread — Shin-ichiro HARA <sinara@...>
原です。
12 messages
2000/09/24
[#11056] Re: ruby-1.6.1-20000921-i386-cygwin and Thread
— WATANABE Hirofumi <eban@...>
2000/09/24
わたなべです.
[#11057] Re: ruby-1.6.1-20000921-i386-cygwin and Thread
— Shin-ichiro Hara <sinara@...>
2000/09/25
原です。
[#11058] Re: ruby-1.6.1-20000921-i386-cygwin and Thread
— ARIMA Yasuhiro <fit0298@...>
2000/09/25
有馬です。
[#11066] [PATCH] gcc extension in regex.c — "Nobuyoshi.Nakada" <nobu.nakada@...>
なかだです。
6 messages
2000/09/26
[#11068] Re: [PATCH] gcc extension in regex.c
— "Nobuyoshi.Nakada" <nobu.nakada@...>
2000/09/26
なかだです。
[#11074] 定数のネスト — Kazuhiro NISHIYAMA <zn@...>
http://www2.osk.3web.ne.jp/~kgt/Ruby.html#000925_2
8 messages
2000/09/26
[ruby-dev:10921] proper tail recursion
From:
Shugo Maeda <shugo@...>
Date:
2000-09-14 20:26:55 UTC
List:
ruby-dev #10921
前田です。
tail recursiveにする方法を思いついたので、試しに実装してみました。
$ ./ruby16 -e 'def foo; return foo; end'
でちゃんと無限ループになります:)
また下記のような再帰版のfact2.rbで、10000の階乗まで計算できること
を確認しました。
# 普通のrubyでは3000くらいでアウトでした。
-- fact2.rb ---
def fact_iter(product, counter, max_count)
if counter > max_count
return product
else
return fact_iter(product * counter,
counter + 1,
max_count)
end
end
def fact(n)
return fact_iter(1, 1, n)
end
print fact(ARGV[0].to_i), "\n"
-------------
rb_call()のたびに一回余分にPUSH_TAG()/EXEC_TAG()するので速度に影
響が出るかと思ったのですが、思ったほど影響はありませんでした。
現時点ではreturnを使ってない場合はtail recursionが検出されないと
いう制限があります。
1.6へのパッチです。
--
前田 修吾
Index: eval.c
===================================================================
RCS file: /home/cvs/ruby/eval.c,v
retrieving revision 1.103
diff -u -r1.103 eval.c
--- eval.c 2000/09/12 06:41:23 1.103
+++ eval.c 2000/09/14 19:52:57
@@ -504,6 +504,9 @@
static struct FRAME *top_frame;
static struct SCOPE *top_scope;
+static ID tail_call_mid = 0;
+static VALUE tail_call_args = Qnil;
+
#define PUSH_FRAME() { \
struct FRAME _frame; \
_frame.prev = ruby_frame; \
@@ -770,6 +773,7 @@
#define TAG_RAISE 0x6
#define TAG_THROW 0x7
#define TAG_FATAL 0x8
+#define TAG_TAILCALL 0x9
#define TAG_MASK 0xf
VALUE ruby_class;
@@ -2369,6 +2373,27 @@
JUMP_TAG(TAG_RETURN);
break;
+ case NODE_RETURN_FCALL:
+ {
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ BEGIN_CALLARGS;
+ SETUP_ARGS(node->nd_args);
+ END_CALLARGS;
+ tail_call_mid = node->nd_mid;
+ tail_call_args = rb_ary_new4(argc, argv);
+ TMP_PROTECT_END;
+ JUMP_TAG(TAG_TAILCALL);
+ }
+ break;
+
+ case NODE_RETURN_VCALL:
+ tail_call_mid = node->nd_mid;
+ tail_call_args = Qnil;
+ JUMP_TAG(TAG_TAILCALL);
+ break;
+
case NODE_ARGSCAT:
result = rb_ary_concat(rb_eval(self, node->nd_head),
rb_eval(self, node->nd_body));
@@ -4306,45 +4331,79 @@
VALUE *argv; /* OK */
int scope;
{
+ VALUE result;
NODE *body; /* OK */
int noex;
ID id = mid;
struct cache_entry *ent;
+ int state;
+
+ again:
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ /* is it in the method cache? */
+ ent = cache + EXPR1(klass, mid);
+ if (ent->mid == mid && ent->klass == klass) {
+ if (!ent->method) {
+ result = rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
+ goto end;
+ }
+ klass = ent->origin;
+ id = ent->mid0;
+ noex = ent->noex;
+ body = ent->method;
+ }
+ else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
+ if (scope == 3) {
+ rb_raise(rb_eNameError, "super: no superclass method `%s'",
+ rb_id2name(mid));
+ }
+ result = rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
+ goto end;
+ }
+
+ if (mid != missing) {
+ /* receiver specified form for private method */
+ if ((noex & NOEX_PRIVATE) && scope == 0) {
+ result = rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
+ goto end;
+ }
+
+ /* self must be kind of a specified form for private method */
+ if ((noex & NOEX_PROTECTED)) {
+ VALUE defined_class = klass;
+ while (TYPE(defined_class) == T_ICLASS)
+ defined_class = RBASIC(defined_class)->klass;
+ if (!rb_obj_is_kind_of(ruby_frame->self, defined_class)) {
+ result = rb_undefined(recv, mid, argc, argv, CSTAT_PROT);
+ goto end;
+ }
+ }
+ }
- /* is it in the method cache? */
- ent = cache + EXPR1(klass, mid);
- if (ent->mid == mid && ent->klass == klass) {
- if (!ent->method)
- return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- klass = ent->origin;
- id = ent->mid0;
- noex = ent->noex;
- body = ent->method;
- }
- else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- if (scope == 3) {
- rb_raise(rb_eNameError, "super: no superclass method `%s'",
- rb_id2name(mid));
- }
- return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
- }
-
- if (mid != missing) {
- /* receiver specified form for private method */
- if ((noex & NOEX_PRIVATE) && scope == 0)
- return rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
-
- /* self must be kind of a specified form for private method */
- if ((noex & NOEX_PROTECTED)) {
- VALUE defined_class = klass;
- while (TYPE(defined_class) == T_ICLASS)
- defined_class = RBASIC(defined_class)->klass;
- if (!rb_obj_is_kind_of(ruby_frame->self, defined_class))
- return rb_undefined(recv, mid, argc, argv, CSTAT_PROT);
+ result = rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF);
+ }
+ end:
+ POP_TAG();
+ switch (state) {
+ case 0:
+ return result;
+ case TAG_TAILCALL:
+ mid = tail_call_mid;
+ if (NIL_P(tail_call_args)) {
+ argc = 0;
+ argv = 0;
+ }
+ else {
+ argc = RARRAY(tail_call_args)->len;
+ argv = RARRAY(tail_call_args)->ptr;
}
+ tail_call_mid = 0;
+ tail_call_args = Qnil;
+ goto again;
+ default:
+ JUMP_TAG(state);
}
-
- return rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF);
}
VALUE
@@ -5599,6 +5658,8 @@
rb_global_variable((VALUE*)&ruby_eval_tree);
rb_global_variable((VALUE*)&ruby_dyna_vars);
+
+ rb_global_variable(&tail_call_args);
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
Index: node.h
===================================================================
RCS file: /home/cvs/ruby/node.h,v
retrieving revision 1.16
diff -u -r1.16 node.h
--- node.h 2000/09/07 06:59:36 1.16
+++ node.h 2000/09/14 19:52:57
@@ -64,6 +64,8 @@
NODE_ZARRAY,
NODE_HASH,
NODE_RETURN,
+ NODE_RETURN_FCALL,
+ NODE_RETURN_VCALL,
NODE_YIELD,
NODE_LVAR,
NODE_DVAR,
Index: parse.y
===================================================================
RCS file: /home/cvs/ruby/parse.y,v
retrieving revision 1.56
diff -u -r1.56 parse.y
--- parse.y 2000/09/12 05:37:24 1.56
+++ parse.y 2000/09/14 19:53:00
@@ -95,6 +95,7 @@
static NODE *new_call();
static NODE *new_fcall();
static NODE *new_super();
+static NODE *new_return();
static NODE *gettable();
static NODE *assignable();
@@ -419,7 +420,7 @@
{
if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
- $$ = NEW_RETURN($2);
+ $$ = new_return($2);
}
| command_call
| expr kAND expr
@@ -1099,7 +1100,7 @@
if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
value_expr($3);
- $$ = NEW_RETURN($3);
+ $$ = new_return($3);
}
| kRETURN '(' ')'
{
@@ -4470,6 +4471,27 @@
return a;
}
return NEW_SUPER(a);
+}
+
+static NODE*
+new_return(node)
+ NODE *node;
+{
+ switch (nd_type(node)) {
+ case NODE_FCALL:
+ if (node->nd_mid == cur_mid) {
+ nd_set_type(node, NODE_RETURN_FCALL);
+ return node;
+ }
+ break;
+ case NODE_VCALL:
+ if (node->nd_mid == cur_mid) {
+ nd_set_type(node, NODE_RETURN_VCALL);
+ return node;
+ }
+ break;
+ }
+ return NEW_RETURN(node);
}
static struct local_vars {