@@ -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