mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Allow destructuring in formal arguments.
e.g. ``` def m(a,(b,c),d); p [a,b,c,d]; end m(1,[2,3],4) # => [1,2,3,4] ``` mruby limitation: Destructured arguments (`b` and `c` in above example) cannot be accessed from the default expression of optional arguments and keyword arguments, since actual assignment is done after the evaluation of those default expressions. Thus: ``` def f(a,(b,c),d=b) p [a,b,c,d] end f(1,[2,3]) ``` raises `NoMethodError` for `b` in mruby.
This commit is contained in:
@@ -734,15 +734,13 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
mrb_aspec a;
|
||||
int ma, oa, ra, pa, ka, kd, ba;
|
||||
int pos, i;
|
||||
node *n, *opt;
|
||||
node *opt;
|
||||
node *margs, *pargs;
|
||||
node *tail;
|
||||
|
||||
/* mandatory arguments */
|
||||
ma = node_len(tree->car->car);
|
||||
n = tree->car->car;
|
||||
while (n) {
|
||||
n = n->cdr;
|
||||
}
|
||||
margs = tree->car->car;
|
||||
tail = tree->car->cdr->cdr->cdr->cdr;
|
||||
|
||||
/* optional arguments */
|
||||
@@ -751,6 +749,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
ra = tree->car->cdr->cdr->car ? 1 : 0;
|
||||
/* mandatory arugments after rest argument */
|
||||
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;
|
||||
/* keyword dictionary? */
|
||||
@@ -798,6 +797,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
dispatch(s, pos+i*3+1);
|
||||
}
|
||||
|
||||
/* keyword arguments */
|
||||
if (tail) {
|
||||
node *kwds = tail->cdr->car;
|
||||
int kwrest = 0;
|
||||
@@ -836,7 +836,34 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
genop_0(s, OP_KEYEND);
|
||||
}
|
||||
}
|
||||
|
||||
/* argument destructuring */
|
||||
if (margs) {
|
||||
node *n = margs;
|
||||
|
||||
pos = 1;
|
||||
while (n) {
|
||||
if (nint(n->car->car) == NODE_MASGN) {
|
||||
gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
|
||||
}
|
||||
pos++;
|
||||
n = n->cdr;
|
||||
}
|
||||
}
|
||||
if (pargs) {
|
||||
node *n = margs;
|
||||
|
||||
pos = ma+oa+ra+1;
|
||||
while (n) {
|
||||
if (nint(n->car->car) == NODE_MASGN) {
|
||||
gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
|
||||
}
|
||||
pos++;
|
||||
n = n->cdr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codegen(s, tree->cdr->car, VAL);
|
||||
pop();
|
||||
if (s->pc > 0) {
|
||||
@@ -1066,6 +1093,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
|
||||
idx = new_sym(s, nsym(tree));
|
||||
genop_2(s, OP_SETGV, sp, idx);
|
||||
break;
|
||||
case NODE_ARG:
|
||||
case NODE_LVAR:
|
||||
idx = lv_idx(s, nsym(tree));
|
||||
if (idx > 0) {
|
||||
@@ -1173,7 +1201,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
|
||||
pop_n(post+1);
|
||||
genop_3(s, OP_APOST, cursp(), n, post);
|
||||
n = 1;
|
||||
if (t->car) { /* rest */
|
||||
if (t->car && t->car != (node*)-1) { /* rest */
|
||||
gen_assignment(s, t->car, cursp(), NOVAL);
|
||||
}
|
||||
if (t->cdr && t->cdr->car) {
|
||||
|
||||
@@ -682,6 +682,25 @@ new_arg(parser_state *p, mrb_sym sym)
|
||||
return cons((node*)NODE_ARG, nsym(sym));
|
||||
}
|
||||
|
||||
static void
|
||||
local_add_margs(parser_state *p, node *n)
|
||||
{
|
||||
while (n) {
|
||||
if (n->car->car == (node*)NODE_MASGN) {
|
||||
node *t = n->car->cdr->cdr;
|
||||
|
||||
n->car->cdr->cdr = NULL;
|
||||
while (t) {
|
||||
local_add_f(p, sym(t->car));
|
||||
t = t->cdr;
|
||||
}
|
||||
local_add_margs(p, n->car->cdr->car->car);
|
||||
local_add_margs(p, n->car->cdr->car->cdr->cdr->car);
|
||||
}
|
||||
n = n->cdr;
|
||||
}
|
||||
}
|
||||
|
||||
/* (m o r m2 tail) */
|
||||
/* m: (a b c) */
|
||||
/* o: ((a . e1) (b . e2)) */
|
||||
@@ -693,6 +712,8 @@ new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail
|
||||
{
|
||||
node *n;
|
||||
|
||||
local_add_margs(p, m);
|
||||
local_add_margs(p, m2);
|
||||
n = cons(m2, tail);
|
||||
n = cons(nsym(rest), n);
|
||||
n = cons(opt, n);
|
||||
@@ -3275,9 +3296,15 @@ f_arg_item : f_norm_arg
|
||||
{
|
||||
$$ = new_arg(p, $1);
|
||||
}
|
||||
| tLPAREN f_margs rparen
|
||||
| tLPAREN
|
||||
{
|
||||
$$ = new_masgn(p, $2, 0);
|
||||
$<nd>$ = local_switch(p);
|
||||
}
|
||||
f_margs rparen
|
||||
{
|
||||
$$ = new_masgn(p, $3, p->locals->car);
|
||||
local_resume(p, $<nd>2);
|
||||
local_add_f(p, 0);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user