なかだです。

以前からときおり要望のある、procの省略を試しに実装してみました。

  x = {|a| p a}; x.call(4)
  x = (do |a| p a end); x.call(9)

ブレースのほうは||、do/endはカッコが必須という制限がありますが。


* eval.c (rb_eval): NODE_LAMBDA implemented.

* node.h (NODE_LAMBDA): for literal Proc object.

* parse.y (expr): interpret mere do...end block as proc object.

* parse.y (primary): ditto, for brace block.


Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.755 diff -U2 -p -r1.755 eval.c --- eval.c 22 Feb 2005 14:57:43 -0000 1.755 +++ eval.c 1 Mar 2005 09:53:40 -0000 @@ -2942,4 +2942,5 @@ rb_eval(self, n) case NODE_ITER: case NODE_FOR: + case NODE_LAMBDA: { PUSH_TAG(PROT_LOOP); @@ -2953,4 +2954,8 @@ rb_eval(self, n) result = rb_eval(self, node->nd_iter); } + else if (nd_type(node) == NODE_LAMBDA) { + ruby_iter->iter = ruby_frame->iter = ITER_CUR; + result = rb_block_proc(); + } else { VALUE recv; Index: node.h =================================================================== RCS file: /cvs/ruby/src/ruby/node.h,v retrieving revision 1.61 diff -U2 -p -r1.61 node.h --- node.h 16 Dec 2004 15:01:49 -0000 1.61 +++ node.h 1 Mar 2005 09:53:40 -0000 @@ -126,4 +126,5 @@ enum node_type { NODE_ATTRASGN, NODE_PRELUDE, + NODE_LAMBDA, NODE_LAST }; @@ -341,4 +342,5 @@ typedef struct RNode { #define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a) #define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0) +#define NEW_LAMBDA(v,b) NEW_NODE(NODE_LAMBDA,v,b,0) #define NOEX_PUBLIC 0 Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.370 diff -U2 -p -r1.370 parse.y --- parse.y 26 Feb 2005 21:08:24 -0000 1.370 +++ parse.y 1 Mar 2005 13:35:21 -0000 @@ -490,5 +490,5 @@ static void ripper_compile_error _((stru %type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg %type <node> assoc_list assocs assoc undef_list backref string_dvar -%type <node> for_var block_var opt_block_var block_par +%type <node> for_var block_var opt_block_var block_var_def block_par %type <node> brace_block cmd_brace_block do_block lhs none fitem %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node @@ -1015,4 +1015,9 @@ expr : command_call %*/ } + | do_block + { + $$ = $1; + nd_set_type($$, NODE_LAMBDA); + } | arg ; @@ -2505,4 +2509,24 @@ primary : literal %*/ } + | tLBRACE + { + /*%%%*/ + $<vars>$ = dyna_push(); + $<num>1 = ruby_sourceline; + /*% + %*/ + } + block_var_def {$<vars>$ = ruby_dyna_vars;} + compstmt + '}' + { + /*%%%*/ + $$ = NEW_LAMBDA($3, dyna_init($5, $<vars>4)); + nd_set_line($$, $<num>1); + dyna_pop($<vars>2); + /*% + $$ = dispatch2(brace_block, escape_Qundef($3), $5); + %*/ + } | kRETURN { @@ -3063,5 +3087,11 @@ block_var : block_par opt_block_var : none - | '|' /* none */ '|' + | block_var_def + { + $$ = $1; + } + ; + +block_var_def : '|' /* none */ '|' { /*%%%*/ @@ -6381,5 +6411,5 @@ parser_yylex(parser) if (CMDARG_P() && state != EXPR_CMDARG) return kDO_BLOCK; - if (state == EXPR_ENDARG) + if (state == EXPR_ENDARG || state == EXPR_BEG) return kDO_BLOCK; return kDO;
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦