From b53cd3ce255f43164cae87f2abbd4f573676cbab Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 20 Jan 2022 20:09:36 +0900 Subject: [PATCH] codegen.c: fix evaluation order of attribute assignment. --- mrbgems/mruby-compiler/core/codegen.c | 74 ++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 7b8e55bb8..c36178c8b 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1788,8 +1788,6 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val) case NODE_CONST: case NODE_NIL: case NODE_MASGN: - case NODE_SCALL: - case NODE_CALL: if (rhs) { codegen(s, rhs, VAL); pop(); @@ -1798,6 +1796,8 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val) break; case NODE_COLON2: + case NODE_CALL: + case NODE_SCALL: /* keep evaluation order */ break; @@ -1855,11 +1855,71 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val) case NODE_CALL: case NODE_SCALL: - push(); - gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL, type == NODE_SCALL); - pop(); - if (val && cursp() != sp) { - gen_move(s, cursp(), sp, 0); + { + int noself = 0, safe = (type == NODE_SCALL), skip = 0, top, call, n = 0; + mrb_sym mid = nsym(tree->cdr->car); + + top = cursp(); + if (val || sp == cursp()) { + push(); /* room for retval */ + } + call = cursp(); + if (!tree->car) { + noself = 1; + push(); + } + else { + codegen(s, tree->car, VAL); /* receiver */ + } + if (safe) { + int recv = cursp()-1; + gen_move(s, cursp(), recv, 1); + skip = genjmp2_0(s, OP_JMPNIL, cursp(), val); + } + tree = tree->cdr->cdr->car; + if (tree) { + if (tree->car) { /* positional arguments */ + n = gen_values(s, tree->car, VAL, 0, (tree->cdr->car)?13:14); + if (n < 0) { /* variable length */ + n = 15; + push(); + } + } + if (tree->cdr->car) { /* keyword arguments */ + gen_hash(s, tree->cdr->car->cdr, VAL, 0); + if (n < 14) { + n++; + push(); + } + else { + pop(); + genop_2(s, OP_ARYPUSH, cursp(), 1); + } + } + } + if (rhs) { + codegen(s, rhs, VAL); + pop(); + } + else { + gen_move(s, cursp(), sp, 0); + } + if (val) { + gen_move(s, top, cursp(), 1); + } + if (n < 14) { + n++; + } + else { + pop(); + genop_2(s, OP_ARYPUSH, cursp(), 1); + } + s->sp = call; + genop_3(s, noself ? OP_SSEND : OP_SEND, cursp(), new_sym(s, attrsym(s, mid)), n); + if (safe) { + dispatch(s, skip); + } + s->sp = top; } break;