fix duplicated eval in op_asgn

`a` in `a.m += c` or `a[b] += c` should be evaluated only once.
parent 4979b52d
...@@ -1716,7 +1716,7 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1716,7 +1716,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_sym sym = sym(tree->cdr->car); mrb_sym sym = sym(tree->cdr->car);
mrb_int len; mrb_int len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len); const char *name = mrb_sym2name_len(s->mrb, sym, &len);
int idx; int idx, callargs = -1, vsp = -1;
if ((len == 2 && name[0] == '|' && name[1] == '|') && if ((len == 2 && name[0] == '|' && name[1] == '|') &&
((intptr_t)tree->car->car == NODE_CONST || ((intptr_t)tree->car->car == NODE_CONST ||
...@@ -1737,6 +1737,34 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1737,6 +1737,34 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADF, exc)); genop(s, MKOP_A(OP_LOADF, exc));
dispatch(s, noexc); dispatch(s, noexc);
} }
else if ((intptr_t)tree->car->car == NODE_CALL) {
node *n = tree->car->cdr;
if (val) {
vsp = cursp();
push();
}
codegen(s, n->car, VAL); /* receiver */
idx = new_msym(s, sym(n->cdr->car));
if (n->cdr->cdr->car) {
int i = gen_values(s, n->cdr->cdr->car->car, VAL);
if (i >= 0) {
pop_n(i);
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
}
genop(s, MKOP_AB(OP_MOVE, cursp()+1, cursp()-1));
genop(s, MKOP_AB(OP_MOVE, cursp()+2, cursp()));
push();
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, CALL_MAXARGS));
callargs = CALL_MAXARGS;
}
else {
genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
callargs = 1;
}
push();
}
else { else {
codegen(s, tree->car, VAL); codegen(s, tree->car, VAL);
} }
...@@ -1785,8 +1813,25 @@ codegen(codegen_scope *s, node *tree, int val) ...@@ -1785,8 +1813,25 @@ codegen(codegen_scope *s, node *tree, int val)
else { else {
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
} }
if (callargs < 0) {
gen_assignment(s, tree->car, cursp(), val);
}
else {
if (callargs == CALL_MAXARGS) {
genop(s, MKOP_AB(OP_ARYPUSH, cursp()-1, cursp()));
if (val) {
genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
}
pop();
}
else if (val) {
genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
}
pop();
idx = new_msym(s, attrsym(s,sym(tree->car->cdr->cdr->car)));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
}
} }
gen_assignment(s, tree->car, cursp(), val);
break; break;
case NODE_SUPER: case NODE_SUPER:
......
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