From: nobu@... Date: 2005-10-14T01:24:30+09:00 Subject: [ruby-dev:27424] value of BEGIN block なかだです。 one linerでは-n/-pオプションは便利なんですが、BEGINで前処理をし たいとき(たとえば集計のためにHashを初期化しておくとか)、スコー プが独立しているためにローカル変数を使うわけにはいきません。こ れがちょっと不便な場合もあるので、BEGINの結果を後から参照できる ようにしてみました。 結果を参照するところまでBEGINに入るわけではないので a ||= BEGIN {...} のようにしないと毎回代入してしまうという制限もありますが、 コンテナ系ではこれで充分な場面も多いのではないかと。 Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.838 diff -U2 -p -u -r1.838 eval.c --- eval.c 11 Oct 2005 12:42:32 -0000 1.838 +++ eval.c 13 Oct 2005 12:00:39 -0000 @@ -1338,6 +1338,6 @@ eval_node(VALUE self, NODE *node) rb_eval(self, node->nd_head); node = node->nd_body; + if (!node) return Qnil; } - if (!node) return Qnil; return rb_eval(self, node); } @@ -3946,4 +3946,11 @@ rb_eval(VALUE self, NODE *n) break; + case NODE_PRELUDE: + result = rb_eval(self, node->nd_body); + node->nd_body = 0; + nd_set_type(node, NODE_LIT); + node->nd_lit = result; + break; + default: unknown_node(node); Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.419 diff -U2 -p -u -r1.419 parse.y --- parse.y 11 Oct 2005 12:42:32 -0000 1.419 +++ parse.y 13 Oct 2005 11:57:41 -0000 @@ -689,4 +689,5 @@ compstmt : stmts opt_terms { /*%%%*/ + if ($1 && nd_type($1) == NODE_PRELUDE) $1 = 0; void_stmts($1); $$ = $1; @@ -838,28 +839,4 @@ stmt : kALIAS fitem {lex_state = EXPR_F %*/ } - | klBEGIN - { - /*%%%*/ - if (in_def || in_single) { - yyerror("BEGIN in method"); - } - local_push(0); - /*% - if (in_def || in_single) { - yyerror("BEGIN in method"); - } - %*/ - } - '{' compstmt '}' - { - /*%%%*/ - ruby_eval_tree_begin = block_append(ruby_eval_tree_begin, - NEW_PREEXE($4)); - local_pop(); - $$ = 0; - /*% - $$ = dispatch1(BEGIN, $4); - %*/ - } | klEND '{' compstmt '}' { @@ -2923,4 +2900,32 @@ primary : literal %*/ } + | klBEGIN + { + /*%%%*/ + if (in_def || in_single) { + yyerror("BEGIN in method"); + } + local_push(0); + /*% + if (in_def || in_single) { + yyerror("BEGIN in method"); + } + %*/ + } + '{' compstmt '}' + { + /*%%%*/ + NODE *pre = 0; + if ($4) { + pre = NEW_PRELUDE(0, NEW_PREEXE($4)); + } + ruby_eval_tree_begin = block_append(ruby_eval_tree_begin, + pre); + local_pop(); + $$ = pre; + /*% + $$ = dispatch1(BEGIN, $4); + %*/ + } ; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦