Nakada, Nobuyoshi
6/28/2005 10:40:00 AM
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