aboutsummaryrefslogtreecommitdiffstats
path: root/prism_compile.c
diff options
context:
space:
mode:
authorJemma Issroff <jemmaissroff@gmail.com>2023-11-01 15:22:08 -0300
committerJemma Issroff <jemmaissroff@gmail.com>2023-11-06 10:39:07 -0300
commitf6ba87ca8899cd753306ffbca475b16c367995a3 (patch)
treeb68e10e175ea4d9203dfca4577d4db7ee636e8fb /prism_compile.c
parent4a6bdbd6dc160c4614105f0478d398b2222429e0 (diff)
downloadruby-f6ba87ca8899cd753306ffbca475b16c367995a3.tar.gz
[PRISM] Implement compilation for MultiWriteNodes, fix MultiTargetNodes
Compilation now works for MultiWriteNodes and MultiTargetNodes, with nesting on MultiWrites. See the tests added in this commit for example behavior.
Diffstat (limited to 'prism_compile.c')
-rw-r--r--prism_compile.c68
1 files changed, 48 insertions, 20 deletions
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: {