From: nobuyoshi nakada Date: 2005-06-28T19:40:16+09:00 Subject: Re: yield does not take a block Hi, At Tue, 28 Jun 2005 17:37:06 +0900, Daniel Brockman wrote in [ruby-talk:146630]: > Under ruby 1.9.0 (2005-06-23) [i386-linux], irb 0.9.5(05/04/13), > these forms are not permitted: > > yield { .. } > yield &.. > > But these are okay: > > Proc.new.call { .. } > Proc.new.call &.. > > This is an oversight, right? Right. Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.791 diff -U2 -p -r1.791 eval.c --- eval.c 20 Jun 2005 09:59:58 -0000 1.791 +++ eval.c 28 Jun 2005 10:29:44 -0000 @@ -3201,4 +3201,18 @@ rb_eval(self, n) result = Qundef; /* no arg */ } + if (node->nd_body) { + PUSH_BLOCK(0, 0); + if ((state = EXEC_TAG()) == 0) { + struct BLOCK *prev = ruby_block->prev; + *ruby_block = *prev; + ruby_block->prev = prev; + ruby_block->block_obj = rb_eval(self, node->nd_body); + SET_CURRENT_SOURCE(); + result = rb_yield_0(result, 0, 0, YIELD_PROC_CALL, node->nd_state); + } + POP_BLOCK(); + if (state) rb_jump_tag(state); + break; + } SET_CURRENT_SOURCE(); result = rb_yield_0(result, 0, 0, 0, node->nd_state); Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.387 diff -U2 -p -r1.387 parse.y --- parse.y 12 Jun 2005 16:56:05 -0000 1.387 +++ parse.y 28 Jun 2005 10:15:29 -0000 @@ -231,5 +231,5 @@ static void void_stmts_gen _((struct par #define void_stmts(node) void_stmts_gen(parser, node) static void reduce_nodes _((NODE**)); -static void block_dup_check _((NODE*)); +static NODE *add_iter_block _((NODE*,NODE*)); static NODE *block_append _((NODE*,NODE*)); @@ -1138,7 +1138,5 @@ command : operation command_args $$ = new_fcall($1, $2); if ($3) { - block_dup_check($$); - $3->nd_iter = $$; - $$ = $3; + $$ = add_iter_block($$, $3); } fixpos($$, $2); @@ -1162,7 +1160,5 @@ command : operation command_args $$ = new_call($1, $3, $4); if ($5) { - block_dup_check($$); - $5->nd_iter = $$; - $$ = $5; + $$ = add_iter_block($$, $5); } fixpos($$, $1); @@ -1186,7 +1182,5 @@ command : operation command_args $$ = new_call($1, $3, $4); if ($5) { - block_dup_check($$); - $5->nd_iter = $$; - $$ = $5; + $$ = add_iter_block($$, $5); } fixpos($$, $1); @@ -2561,28 +2555,4 @@ primary : literal %*/ } - | kYIELD '(' call_args rparen - { - /*%%%*/ - $$ = new_yield($3); - /*% - $$ = dispatch1(yield, dispatch1(paren, $3)); - %*/ - } - | kYIELD '(' rparen - { - /*%%%*/ - $$ = NEW_YIELD(0, Qfalse); - /*% - $$ = dispatch1(yield, dispatch1(paren, arg_new())); - %*/ - } - | kYIELD - { - /*%%%*/ - $$ = NEW_YIELD(0, Qfalse); - /*% - $$ = dispatch0(yield0); - %*/ - } | kDEFINED opt_nl '(' {in_defined = 1;} expr rparen { @@ -2610,7 +2580,5 @@ primary : literal { /*%%%*/ - block_dup_check($$); - $2->nd_iter = $1; - $$ = $2; + $$ = add_iter_block($1, $2); fixpos($$, $1); /*% @@ -3215,7 +3183,5 @@ block_call : command do_block { /*%%%*/ - block_dup_check($1); - $2->nd_iter = $1; - $$ = $2; + $$ = add_iter_block($1, $2); fixpos($$, $1); /*% @@ -3296,4 +3262,20 @@ method_call : operation paren_args %*/ } + | kYIELD paren_args + { + /*%%%*/ + $$ = new_yield($2); + /*% + $$ = dispatch1(yield, dispatch1(paren, $2)); + %*/ + } + | kYIELD + { + /*%%%*/ + $$ = NEW_YIELD(0, Qfalse); + /*% + $$ = dispatch0(yield0); + %*/ + } | tLPAREN compstmt ')' paren_args { @@ -7212,11 +7194,22 @@ aryset_gen(parser, recv, idx) } -static void -block_dup_check(node) - NODE *node; +static NODE * +add_iter_block(node, block) + NODE *node, *block; { - if (node && nd_type(node) == NODE_BLOCK_PASS) { - compile_error(PARSER_ARG "both block arg and actual block given"); + if (node) { + switch (nd_type(node)) { + case NODE_YIELD: + if (!node->nd_body) { + nd_set_type(block, NODE_LAMBDA); + node->nd_body = block; + return node; + } + case NODE_BLOCK_PASS: + compile_error(PARSER_ARG "both block arg and actual block given"); + } } + block->nd_iter = node; + return block; } @@ -7794,13 +7787,22 @@ new_yield(node) { long state = Qtrue; + NODE *body = 0; if (node) { - no_blockarg(node); - if (nd_type(node) == NODE_ARRAY && node->nd_next == 0) { + switch (nd_type(node)) { + case NODE_BLOCK_PASS: + body = node; + node = node->nd_iter; + nd_set_type(body, NODE_LAMBDA); + body->nd_iter = 0; + break; + case NODE_ARRAY: + if (node->nd_next != 0) break; node = node->nd_head; state = Qfalse; - } - else if (node && nd_type(node) == NODE_SPLAT) { + break; + case NODE_SPLAT: state = Qtrue; + break; } } @@ -7808,5 +7810,7 @@ new_yield(node) state = Qfalse; } - return NEW_YIELD(node, state); + node = NEW_YIELD(node, state); + node->nd_body = body; + return node; } -- Nobu Nakada