Skip to content

Commit 17cb498

Browse files
committed
Support matching list spread
1 parent 4e3783d commit 17cb498

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

ir.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,11 @@ def compile_match_pattern(self, env: Env, param: Instr, pattern: Object, success
555555
# the_list = self.emit(RefineType(param, CList()))
556556
the_list = param
557557
for i, pattern_item in enumerate(pattern.items):
558-
assert not isinstance(pattern_item, Spread)
558+
if isinstance(pattern_item, Spread):
559+
if pattern_item.name:
560+
updates[pattern_item.name] = the_list
561+
self.emit(Jump(success))
562+
return updates
559563
# Not enough elements
560564
is_empty = self.emit(IsEmptyList(the_list))
561565
is_nonempty_block = self.fn.cfg.new_block()
@@ -1422,6 +1426,68 @@ def test_match_two_item_list(self) -> None:
14221426
}""",
14231427
)
14241428

1429+
def test_match_list_spread(self) -> None:
1430+
compiler = Compiler()
1431+
compiler.compile_body({}, _parse("| [_, ...xs] -> xs"))
1432+
self.assertEqual(
1433+
compiler.fns[1].to_string(InstrId()),
1434+
"""\
1435+
fn1 {
1436+
bb0 {
1437+
v0 = Param<0; $clo>
1438+
v1 = Param<1; arg_0>
1439+
Jump bb2
1440+
}
1441+
bb2 {
1442+
v2 = IsList v1
1443+
CondBranch v2, bb4, bb1
1444+
}
1445+
bb4 {
1446+
v3 = IsEmptyList v1
1447+
CondBranch v3, bb1, bb5
1448+
}
1449+
bb5 {
1450+
v4 = ListFirst v1
1451+
Jump bb6
1452+
}
1453+
bb6 {
1454+
v5 = ListRest v1
1455+
Jump bb3
1456+
}
1457+
bb3 {
1458+
Return v5
1459+
}
1460+
bb1 {
1461+
MatchFail
1462+
}
1463+
}""",
1464+
)
1465+
CleanCFG(compiler.fns[1]).run()
1466+
self.assertEqual(
1467+
compiler.fns[1].to_string(InstrId()),
1468+
"""\
1469+
fn1 {
1470+
bb0 {
1471+
v0 = Param<0; $clo>
1472+
v1 = Param<1; arg_0>
1473+
v2 = IsList v1
1474+
CondBranch v2, bb4, bb1
1475+
}
1476+
bb4 {
1477+
v3 = IsEmptyList v1
1478+
CondBranch v3, bb1, bb5
1479+
}
1480+
bb5 {
1481+
v4 = ListFirst v1
1482+
v5 = ListRest v1
1483+
Return v5
1484+
}
1485+
bb1 {
1486+
MatchFail
1487+
}
1488+
}""",
1489+
)
1490+
14251491
def test_apply_fn(self) -> None:
14261492
compiler = Compiler()
14271493
compiler.compile_body({}, _parse("f 1 . f = x -> x + 1"))
@@ -1949,6 +2015,9 @@ def test_match_list(self) -> None:
19492015
self.assertEqual(_run("f [1, 2] . f = | [1, 2] -> 3 | [4, 5] -> 6"), "3\n")
19502016
self.assertEqual(_run("f [4, 5] . f = | [1, 2] -> 3 | [4, 5] -> 6"), "6\n")
19512017

2018+
def test_match_list_spread(self) -> None:
2019+
self.assertEqual(_run("f [4, 5] . f = | [_, ...xs] -> xs"), "[5]\n")
2020+
19522021
def test_var(self) -> None:
19532022
self.assertEqual(_run("a . a = 1"), "1\n")
19542023

0 commit comments

Comments
 (0)