遠藤です。 2010年6月17日6:31 Yukihiro Matsumoto <matz / ruby-lang.org>: > が、もともとの動機とは別として、「&」1文字でそのコンテキスト > のブロックを渡すのは、面白いアイディアだと思います。この場合 > は、仮引数リストのブロック引数がなくても、ブロックを渡すこと > になるんですかね。 パッチを書いてみました。思ったより小さく書けました。 def foo yield end def bar foo(&) end bar { p 1 } #=> 1 カッコを省略した場合、 foo & bar というのが foo & bar なのか foo(&); bar なのか曖昧という問題が ありました。が、互換性重視で foo & bar と解釈するようになってい ます。というか書いてみたらそうなった。conflict は出ません。 diff --git a/compile.c b/compile.c index 2fd804c..3f8c331 100644 --- a/compile.c +++ b/compile.c @@ -2863,8 +2863,13 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *args, NODE *argn, unsigned long *flag) INIT_ANCHOR(arg_block); INIT_ANCHOR(args_splat); if (argn && nd_type(argn) == NODE_BLOCK_PASS) { - COMPILE(arg_block, "block", argn->nd_body); - *flag |= VM_CALL_ARGS_BLOCKARG_BIT; + if ((VALUE)argn->nd_body != (VALUE)-1) { + COMPILE(arg_block, "block", argn->nd_body); + *flag |= VM_CALL_ARGS_BLOCKARG_BIT; + } + else { + *flag |= VM_CALL_ARGS_BLOCKTRGH_BIT; + } argn = argn->nd_head; } diff --git a/node.c b/node.c index 65bc541..85574b4 100644 --- a/node.c +++ b/node.c @@ -621,7 +621,12 @@ dump_node(VALUE buf, VALUE indent, int comment, NODE *node) ANN("example: foo(x, &blk)"); F_NODE(nd_head, "other arguments"); LAST_NODE; - F_NODE(nd_body, "block argument"); + if ((VALUE)node->nd_body != (VALUE)-1) { + F_NODE(nd_body, "block argument"); + } + else { + F_MSG(nd_body, "block argument", "-1 (anonymous)"); + } break; case NODE_DEFN: diff --git a/parse.y b/parse.y index e085088..b0b946b 100644 --- a/parse.y +++ b/parse.y @@ -2459,6 +2459,14 @@ block_arg : tAMPER arg_value $$ = $2; %*/ } + | tAMPER + { + /*%%%*/ + $$ = NEW_BLOCK_PASS(-1); + /*% + $$ = dispatch0(anonymous_block_arg); + %*/ + } ; opt_block_arg : ',' block_arg diff --git a/vm_core.h b/vm_core.h index 7676b2f..f0fa3a3 100644 --- a/vm_core.h +++ b/vm_core.h @@ -544,6 +544,7 @@ typedef struct { #define VM_CALL_TAILRECURSION_BIT (0x01 << 6) #define VM_CALL_SUPER_BIT (0x01 << 7) #define VM_CALL_OPT_SEND_BIT (0x01 << 8) +#define VM_CALL_ARGS_BLOCKTRGH_BIT (0x01 << 9) #define VM_SPECIAL_OBJECT_VMCORE 0x01 #define VM_SPECIAL_OBJECT_CBASE 0x02 diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 985a2fb..2a127d7 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -261,6 +261,10 @@ caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag, *block = blockptr; } } + else if (flag & VM_CALL_ARGS_BLOCKTRGH_BIT) { + rb_control_frame_t *reg_cfp = cfp; + *block = GET_BLOCK_PTR(); + } else if (blockiseq) { blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); blockptr->iseq = blockiseq; -- Yusuke Endoh <mame / tsg.ne.jp>