Make `Proc#parameters` to support keyword arguments; fix #5066

TODO: Unlike CRuby, mruby's `Proc#parameters` does not distinguish
required keyword arguments and optional keyword arguments currently.
parent 02e69d1c
...@@ -57,7 +57,7 @@ struct RProc { ...@@ -57,7 +57,7 @@ struct RProc {
#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1) #define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1)
#define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f) #define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f)
#define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f) #define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f)
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1)) #define MRB_ASPEC_KDICT(a) (((a) >> 1) & 0x1)
#define MRB_ASPEC_BLOCK(a) ((a) & 1) #define MRB_ASPEC_BLOCK(a) ((a) & 1)
#define MRB_PROC_CFUNC_FL 128 #define MRB_PROC_CFUNC_FL 128
......
...@@ -3791,7 +3791,7 @@ f_rest_arg : restarg_mark tIDENTIFIER ...@@ -3791,7 +3791,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
} }
| restarg_mark | restarg_mark
{ {
local_add_f(p, MRB_QSYM(and)); local_add_f(p, MRB_QSYM(mul));
$$ = -1; $$ = -1;
} }
; ;
......
...@@ -9442,7 +9442,7 @@ yyreduce: ...@@ -9442,7 +9442,7 @@ yyreduce:
case 554: case 554:
#line 3793 "mrbgems/mruby-compiler/core/parse.y" #line 3793 "mrbgems/mruby-compiler/core/parse.y"
{ {
local_add_f(p, MRB_QSYM(and)); local_add_f(p, MRB_QSYM(mul));
(yyval.id) = -1; (yyval.id) = -1;
} }
#line 9449 "mrbgems/mruby-compiler/core/y.tab.c" #line 9449 "mrbgems/mruby-compiler/core/y.tab.c"
......
...@@ -91,21 +91,24 @@ static mrb_value ...@@ -91,21 +91,24 @@ static mrb_value
mrb_proc_parameters(mrb_state *mrb, mrb_value self) mrb_proc_parameters(mrb_state *mrb, mrb_value self)
{ {
struct parameters_type { struct parameters_type {
size_t len; mrb_sym name;
const char *name;
int size; int size;
} *p, parameters_list [] = { } *p, parameters_list [] = {
{sizeof("req") - 1, "req", 0}, {MRB_SYM(req), 0},
{sizeof("opt") - 1, "opt", 0}, {MRB_SYM(opt), 0},
{sizeof("rest") - 1, "rest", 0}, {MRB_SYM(rest), 0},
{sizeof("req") - 1, "req", 0}, {MRB_SYM(req), 0},
{sizeof("block") - 1, "block", 0}, {MRB_SYM(keyrest), 0},
{0, NULL, 0} {MRB_SYM(block), 0},
{MRB_SYM(key), 0},
{0, 0}
}; };
const struct RProc *proc = mrb_proc_ptr(self); const struct RProc *proc = mrb_proc_ptr(self);
const struct mrb_irep *irep = proc->body.irep; const struct mrb_irep *irep = proc->body.irep;
mrb_aspec aspec; mrb_aspec aspec;
mrb_value parameters; mrb_value parameters;
mrb_value krest = mrb_nil_value();
mrb_value block = mrb_nil_value();
int i, j; int i, j;
int max = -1; int max = -1;
...@@ -124,10 +127,8 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) ...@@ -124,10 +127,8 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
} }
if (!MRB_PROC_STRICT_P(proc)) { if (!MRB_PROC_STRICT_P(proc)) {
parameters_list[0].len = sizeof("opt") - 1; parameters_list[0].name = MRB_SYM(opt);
parameters_list[0].name = "opt"; parameters_list[3].name = MRB_SYM(opt);
parameters_list[3].len = sizeof("opt") - 1;
parameters_list[3].name = "opt";
} }
aspec = PEEK_W(irep->iseq+1); aspec = PEEK_W(irep->iseq+1);
...@@ -135,13 +136,15 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) ...@@ -135,13 +136,15 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
parameters_list[1].size = MRB_ASPEC_OPT(aspec); parameters_list[1].size = MRB_ASPEC_OPT(aspec);
parameters_list[2].size = MRB_ASPEC_REST(aspec); parameters_list[2].size = MRB_ASPEC_REST(aspec);
parameters_list[3].size = MRB_ASPEC_POST(aspec); parameters_list[3].size = MRB_ASPEC_POST(aspec);
parameters_list[4].size = MRB_ASPEC_BLOCK(aspec); parameters_list[4].size = MRB_ASPEC_KDICT(aspec);
parameters_list[5].size = MRB_ASPEC_BLOCK(aspec);
parameters_list[6].size = MRB_ASPEC_KEY(aspec);
parameters = mrb_ary_new_capa(mrb, irep->nlocals-1); parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
max = irep->nlocals-1; max = irep->nlocals-1;
for (i = 0, p = parameters_list; p->name; p++) { for (i = 0, p = parameters_list; p->name; p++) {
mrb_value sname = mrb_symbol_value(mrb_intern_static(mrb, p->name, p->len)); mrb_value sname = mrb_symbol_value(p->name);
for (j = 0; j < p->size; i++, j++) { for (j = 0; j < p->size; i++, j++) {
mrb_value a; mrb_value a;
...@@ -159,9 +162,17 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self) ...@@ -159,9 +162,17 @@ mrb_proc_parameters(mrb_state *mrb, mrb_value self)
break; break;
} }
} }
if (p->name == MRB_SYM(block)) {
block = a; continue;
}
if (p->name == MRB_SYM(keyrest)) {
krest = a; continue;
}
mrb_ary_push(mrb, parameters, a); mrb_ary_push(mrb, parameters, a);
} }
} }
if (!mrb_nil_p(krest)) mrb_ary_push(mrb, parameters, krest);
if (!mrb_nil_p(block)) mrb_ary_push(mrb, parameters, block);
return parameters; return parameters;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment