summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c6
-rw-r--r--prism_compile.c68
-rw-r--r--test/ruby/test_compile_prism.rb27
3 files changed, 75 insertions, 26 deletions
diff --git a/compile.c b/compile.c
index bad3c079fc..9d09bef494 100644
--- a/compile.c
+++ b/compile.c
@@ -5274,7 +5274,6 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
int llen = 0;
int lpos = 0;
- int expand = 1;
while (lhsn_count) {
llen++;
@@ -5312,7 +5311,6 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
}
}
-
if (!state->nested) {
NO_CHECK(COMPILE(rhs, "normal masgn rhs", rhsn));
}
@@ -5320,9 +5318,7 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
if (!popped) {
ADD_INSN(rhs, node, dup);
}
- if (expand) {
- ADD_INSN2(rhs, node, expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
- }
+ ADD_INSN2(rhs, node, expandarray, INT2FIX(llen), INT2FIX(lhs_splat));
return COMPILE_OK;
}
diff --git a/prism_compile.c b/prism_compile.c
index 4350a346e3..ba59e6f04d 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -2925,42 +2925,53 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
case PM_MULTI_TARGET_NODE: {
pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node;
- for (size_t index = 0; index < cast->lefts.size; index++) {
- PM_COMPILE(cast->lefts.nodes[index]);
+
+ if (cast->lefts.size) {
+ int flag = (int) (bool) cast->rights.size;
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->lefts.size), INT2FIX(flag));
+ for (size_t index = 0; index < cast->lefts.size; index++) {
+ PM_COMPILE_NOT_POPPED(cast->lefts.nodes[index]);
+ }
+ }
+
+ if (cast->rights.size) {
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->rights.size), INT2FIX(2));
+ for (size_t index = 0; index < cast->rights.size; index++) {
+ PM_COMPILE_NOT_POPPED(cast->rights.nodes[index]);
+ }
}
return;
}
case PM_MULTI_WRITE_NODE: {
pm_multi_write_node_t *multi_write_node = (pm_multi_write_node_t *)node;
- pm_node_list_t *node_list = &multi_write_node->lefts;
+ pm_node_list_t *lefts = &multi_write_node->lefts;
+ pm_node_list_t *rights = &multi_write_node->rights;
// pre-process the left hand side of multi-assignments.
uint8_t pushed = 0;
- for (size_t index = 0; index < node_list->size; index++) {
- pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, node_list->nodes[index], ret, scope_node, pushed, false);
+ for (size_t index = 0; index < lefts->size; index++) {
+ pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, lefts->nodes[index], ret, scope_node, pushed, false);
}
PM_COMPILE_NOT_POPPED(multi_write_node->value);
-
- // TODO: int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
- int flag = 0x00;
-
PM_DUP_UNLESS_POPPED;
- ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(node_list->size), INT2FIX(flag));
- for (size_t index = 0; index < node_list->size; index++) {
- pm_node_t *considered_node = node_list->nodes[index];
+ if (lefts->size) {
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(lefts->size), INT2FIX((int) (bool) rights->size));
+ for (size_t index = 0; index < lefts->size; index++) {
+ pm_node_t *considered_node = lefts->nodes[index];
- if (PM_NODE_TYPE_P(considered_node, PM_CONSTANT_PATH_TARGET_NODE) && pushed > 0) {
- pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) considered_node;
- ID name = pm_constant_id_lookup(scope_node, ((pm_constant_read_node_t * ) cast->child)->name);
+ if (PM_NODE_TYPE_P(considered_node, PM_CONSTANT_PATH_TARGET_NODE) && pushed > 0) {
+ pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) considered_node;
+ ID name = pm_constant_id_lookup(scope_node, ((pm_constant_read_node_t * ) cast->child)->name);
- pushed -= 2;
+ pushed -= 2;
- ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(pushed));
- ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(name));
- } else {
- PM_COMPILE(node_list->nodes[index]);
+ ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(pushed));
+ ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(name));
+ } else {
+ PM_COMPILE(lefts->nodes[index]);
+ }
}
}
@@ -2971,6 +2982,23 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
+ if (multi_write_node->rest) {
+ RUBY_ASSERT(PM_NODE_TYPE_P(multi_write_node->rest, PM_SPLAT_NODE));
+
+ pm_splat_node_t *rest_splat = ((pm_splat_node_t *)multi_write_node->rest);
+ if (rest_splat->expression) {
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1));
+ PM_COMPILE(rest_splat->expression);
+ }
+ }
+
+ if (rights->size) {
+ ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(rights->size), INT2FIX(2));
+ for (size_t index = 0; index < rights->size; index++) {
+ PM_COMPILE(rights->nodes[index]);
+ }
+ }
+
return;
}
case PM_NEXT_NODE: {
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index 900c868f4c..911b126e73 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -330,8 +330,33 @@ module Prism
assert_prism_eval("pit, pit1 = 1")
end
+ def test_MultiTargetNode
+ assert_prism_eval("a, (b, c) = [1, 2, 3]")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; a")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; b")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; c")
+ assert_prism_eval("a, (b, c) = [1, [2, 3]]; c")
+ assert_prism_eval("(a, (b, c, d, e), f, g), h = [1, [2, 3]], 4, 5, [6, 7]; c")
+ end
+
def test_MultiWriteNode
- assert_prism_eval("foo, bar = [1,2]")
+ assert_prism_eval("foo, bar = [1, 2]")
+ assert_prism_eval("foo, *, bar = [1, 2]")
+ assert_prism_eval("foo, bar = 1, 2")
+ assert_prism_eval("foo, *, bar = 1, 2")
+ assert_prism_eval("foo, *, bar = 1, 2, 3, 4")
+ assert_prism_eval("a, b, *, d = 1, 2, 3, 4")
+ assert_prism_eval("a, b, *, d = 1, 2")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; a")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; b")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; c")
+ assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; a")
+ assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; c")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; b")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; d")
+ assert_prism_eval("((a, *, b), *, (c, *, (d, *, e, f, g))), *, ((h, i, *, j), *, (k, l, m, *, n, o, p), q, r) = 1; a")
end
############################################################################