diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 5cf56b643..7429b7e60 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1376,7 +1376,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) pa = node_len(tree->car->cdr->cdr->cdr->car); pargs = tree->car->cdr->cdr->cdr->car; /* keyword arguments */ - ka = tail? node_len(tail->cdr->car) : 0; + ka = tail ? node_len(tail->cdr->car) : 0; /* keyword dictionary? */ kd = tail && tail->cdr->cdr->car? 1 : 0; /* block argument? */ @@ -1388,16 +1388,16 @@ lambda_body(codegen_scope *s, node *tree, int blk) /* (23bits = 5:5:1:5:5:1:1) */ a = MRB_ARGS_REQ(ma) | MRB_ARGS_OPT(oa) - | (ra? MRB_ARGS_REST() : 0) + | (ra ? MRB_ARGS_REST() : 0) | MRB_ARGS_POST(pa) | MRB_ARGS_KEY(ka, kd) - | (ba? MRB_ARGS_BLOCK() : 0); + | (ba ? MRB_ARGS_BLOCK() : 0); genop_W(s, OP_ENTER, a); /* (12bits = 5:1:5:1) */ s->ainfo = (((ma+oa) & 0x3f) << 7) | ((ra & 0x1) << 6) | ((pa & 0x1f) << 1) - | ((ka | kd) ? 1 : 0); + | (ka || kd); /* generate jump table for optional arguments initializer */ pos = new_label(s); for (i=0; icdr->car && !kwrest) { genop_0(s, OP_KEYEND); } + if (ba) { + mrb_sym bparam = nsym(tail->cdr->cdr->cdr->car); + pos = ma+oa+ra+pa+(ka||kd); + if (bparam) { + int idx = lv_idx(s, bparam); + genop_2(s, OP_MOVE, idx, pos+1); + } + } } /* argument destructuring */ diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 843d3da43..415119287 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -334,12 +334,8 @@ local_add(parser_state *p, mrb_sym sym) } } -static void -local_add_blk(parser_state *p, mrb_sym blk) -{ - /* allocate register for block */ - local_add_f(p, blk ? blk : 0); -} +/* allocate register for block */ +#define local_add_blk(p) local_add_f(p, 0) static void local_add_kw(parser_state *p, mrb_sym kwd) @@ -865,7 +861,8 @@ new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk) local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0); } - local_add_blk(p, blk); + local_add_blk(p); + if (blk) local_add_f(p, blk); /* allocate register for keywords arguments */ /* order is for Proc#parameters */ @@ -3096,7 +3093,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail opt_block_param : none { - local_add_blk(p, 0); + local_add_blk(p); $$ = 0; } | block_param_def @@ -3106,13 +3103,13 @@ opt_block_param : none } ; -block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|' +block_param_def : '|' {local_add_blk(p);} opt_bv_decl '|' { $$ = 0; } | tOROP { - local_add_blk(p, 0); + local_add_blk(p); $$ = 0; } | '|' block_param opt_bv_decl '|' diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index 8586abc77..bd2b20260 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -152,6 +152,9 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i])); } if (p->name == MRB_SYM(block)) { + if (irep->lv[i+1]) { + mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i+1])); + } block = a; continue; } if (p->name == MRB_SYM(keyrest)) { diff --git a/mrbgems/mruby-proc-ext/test/proc.rb b/mrbgems/mruby-proc-ext/test/proc.rb index 13e7058f9..7a105323a 100644 --- a/mrbgems/mruby-proc-ext/test/proc.rb +++ b/mrbgems/mruby-proc-ext/test/proc.rb @@ -33,11 +33,6 @@ assert('Proc#inspect') do assert_match "#", ins end -assert('Proc#parameters') do - parameters = Proc.new{|x,y=42,*other|}.parameters - assert_equal [[:opt, :x], [:opt, :y], [:rest, :other]], parameters -end - assert('Proc#lambda?') do assert_true lambda{}.lambda? assert_true !Proc.new{}.lambda? @@ -80,6 +75,7 @@ assert('Proc#parameters') do assert_equal([[:req, :a]], ->(a){}.parameters) assert_equal([[:rest, :*]], lambda { |*| }.parameters) assert_equal([[:rest, :a]], Proc.new {|*a|}.parameters) + assert_equal([[:opt, :x], [:opt, :y], [:rest, :other]], Proc.new{|x,y=42,*other|}.parameters) assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], Proc.new {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) end