Skip to content

Commit 0b0da6c

Browse files
Earlopainkddnewton
authored andcommitted
Correctly compile splats in for-loop index in prism
Fixes [Bug #21648] This is a followup to ruby#13597. The added test passed but didn't emit the same instructions. This also handles bare splats and aligns instructions for all cases
1 parent 308fb9c commit 0b0da6c

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

prism_compile.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5338,8 +5338,7 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
53385338
case PM_INSTANCE_VARIABLE_TARGET_NODE:
53395339
case PM_CONSTANT_PATH_TARGET_NODE:
53405340
case PM_CALL_TARGET_NODE:
5341-
case PM_INDEX_TARGET_NODE:
5342-
case PM_SPLAT_NODE: {
5341+
case PM_INDEX_TARGET_NODE: {
53435342
// For other targets, we need to potentially compile the parent or
53445343
// owning expression of this target, then retrieve the value, expand it,
53455344
// and then compile the necessary writes.
@@ -5359,6 +5358,7 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
53595358
pm_multi_target_state_update(&state);
53605359
break;
53615360
}
5361+
case PM_SPLAT_NODE:
53625362
case PM_MULTI_TARGET_NODE: {
53635363
DECL_ANCHOR(writes);
53645364
DECL_ANCHOR(cleanup);
@@ -5394,6 +5394,12 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
53945394
PUSH_INSN(ret, location, pop);
53955395

53965396
PUSH_LABEL(ret, not_single);
5397+
5398+
if (PM_NODE_TYPE_P(node, PM_SPLAT_NODE)) {
5399+
const pm_splat_node_t *cast = (const pm_splat_node_t *) node;
5400+
PUSH_INSN2(ret, location, expandarray, INT2FIX(0), INT2FIX(cast->expression == NULL ? 0 : 1));
5401+
}
5402+
53975403
PUSH_SEQ(ret, writes);
53985404
PUSH_SEQ(ret, cleanup);
53995405
break;

test/ruby/test_compile_prism.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,16 +1046,19 @@ def o.bar = @ret.length < 3
10461046
end
10471047

10481048
def test_ForNode
1049-
assert_prism_eval("for i in [1,2] do; i; end")
1050-
assert_prism_eval("for @i in [1,2] do; @i; end")
1051-
assert_prism_eval("for $i in [1,2] do; $i; end")
1049+
assert_prism_eval("r = []; for i in [1,2] do; r << i; end; r")
1050+
assert_prism_eval("r = []; for @i in [1,2] do; r << @i; end; r")
1051+
assert_prism_eval("r = []; for $i in [1,2] do; r << $i; end; r")
10521052

1053-
assert_prism_eval("for foo, in [1,2,3] do end")
1053+
assert_prism_eval("r = []; for foo, in [1,2,3] do r << foo end; r")
10541054

1055-
assert_prism_eval("for i, j in {a: 'b'} do; i; j; end")
1055+
assert_prism_eval("r = []; for i, j in {a: 'b'} do; r << [i, j]; end; r")
10561056

10571057
# Test splat node as index in for loop
1058-
assert_prism_eval("for *x in [[1,2], [3,4]] do; x; end")
1058+
assert_prism_eval("r = []; for *x in [[1,2], [3,4]] do; r << x; end; r")
1059+
assert_prism_eval("r = []; for * in [[1,2], [3,4]] do; r << 'ok'; end; r")
1060+
assert_prism_eval("r = []; for x, * in [[1,2], [3,4]] do; r << x; end; r")
1061+
assert_prism_eval("r = []; for x, *y in [[1,2], [3,4]] do; r << [x, y]; end; r")
10591062
end
10601063

10611064
############################################################################

0 commit comments

Comments
 (0)