Skip to content

Commit 3f6b522

Browse files
committed
Fixes regression in match with qualified enums.
1 parent 6b43aed commit 3f6b522

File tree

8 files changed

+73
-5
lines changed

8 files changed

+73
-5
lines changed

src/core/inference.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,15 @@ let makeIfOfMatch env e cases =
17231723
(* Constant: create a constant reference for comparison *)
17241724
makeEq e Syntax.{ e = SEId id; loc }
17251725
| _ -> Error.raiseError ("Pattern '" ^ id ^ "' is not a valid enum constructor or constant") loc)
1726+
| _, { p = SPMember ({ p = SPId module_name; _ }, variant_name); loc } -> (
1727+
(* Handle qualified enum constructor patterns like Button.Push *)
1728+
let id_path : path = { id = variant_name; n = Some module_name; loc } in
1729+
match Env.lookupExpressionSymbol env id_path normal_context with
1730+
| ExprEnum (_, _, _) -> makeEq e Syntax.{ e = SEMember (Syntax.{ e = SEId module_name; loc }, variant_name); loc }
1731+
| _ -> Error.raiseError ("Pattern '" ^ module_name ^ "." ^ variant_name ^ "' is not a valid enum constructor") loc
1732+
)
1733+
| _, { p = SPMember _; loc } ->
1734+
Error.raiseError "Invalid qualified pattern. Only Module.Variant patterns are supported" loc
17261735
in
17271736
let if_stmt =
17281737
CCList.fold_right

src/driver/loader.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ module Dependencies = struct
9797
| SPId _ -> set
9898
| SPTuple elems -> list pattern set elems
9999
| SPGroup e -> pattern set e
100+
| SPMember (p, _) -> pattern set p
100101

101102

102103
let rec dexp set d =

src/pparser/parse.ml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -611,11 +611,16 @@ and pair_pattern (buffer : Stream.stream) (token : 'kind token) (left : pattern)
611611
{ p = SPTuple (elems1 @ elems2); loc = left.loc }
612612

613613

614-
and pattern_member (_ : Stream.stream) (token : 'kind token) (_ : pattern) : pattern =
615-
let message =
616-
Error.PointedError (token.loc, "Pattern member access is not supported. Use simple patterns in match expressions")
617-
in
618-
raise (ParserError message)
614+
and pattern_member (buffer : Stream.stream) (token : 'kind token) (left : pattern) : pattern =
615+
let right = pattern (getExpLbp token) buffer in
616+
match right.p with
617+
| SPMember (({ p = SPId id; _ } as i), n) -> { right with p = SPMember ({ i with p = SPMember (left, id) }, n) }
618+
| SPId id -> { right with p = SPMember (left, id) }
619+
| _ ->
620+
let message =
621+
Error.PointedError (token.loc, "Invalid pattern member access. Expected an identifier after the dot")
622+
in
623+
raise (ParserError message)
619624

620625

621626
and exp_member (buffer : Stream.stream) (token : 'kind token) (left : exp) : exp =

src/pparser/syntax.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ type pattern_d =
8989
| SPId of string
9090
| SPTuple of pattern list
9191
| SPGroup of pattern
92+
| SPMember of pattern * string
9293

9394
and pattern =
9495
{ p : pattern_d
@@ -335,6 +336,9 @@ module Print = struct
335336
| SPGroup e ->
336337
let e = pattern e in
337338
{%pla|(<#e#>)|}
339+
| SPMember (p, m) ->
340+
let p = pattern p in
341+
{%pla|<#p#>.<#m#s>|}
338342

339343

340344
let rec lexp (l : lexp) = lexp_d l.l
@@ -1498,6 +1502,7 @@ module SExpr = struct
14981502
| SPId id -> "(SPId " ^ id ^ ")"
14991503
| SPTuple lst -> "(SPTuple " ^ print_list print_pattern lst ^ ")"
15001504
| SPGroup p -> "(SPGroup " ^ print_pattern p ^ ")"
1505+
| SPMember (p, m) -> "(SPMember " ^ print_pattern p ^ " " ^ m ^ ")"
15011506
in
15021507
"(pattern " ^ p_str ^ ")"
15031508

src/pparser/syntaxSexp.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ and pattern_d (p : pattern_d) : string =
123123
let patterns_str = String.concat " " (List.map pattern patterns) in
124124
Printf.sprintf "(tuple %s)" patterns_str
125125
| SPGroup p -> Printf.sprintf "(group %s)" (pattern p)
126+
| SPMember (p, m) -> Printf.sprintf "(member %s %s)" (pattern p) m
126127

127128

128129
and lexp (l : lexp) : string = Printf.sprintf "(lexp %s %s)" (lexp_d l.l) (Loc.to_string l.loc)

test/interpreter/ButtonEnum.vult

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Module defining the Button enum for cross-module qualified pattern tests
2+
enum state {
3+
Push,
4+
Release,
5+
Hold
6+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Test for qualified enum patterns in match expressions
2+
// Tests cross-module access to enum variants like ButtonEnum.Push
3+
4+
// Test function using qualified enum patterns in match
5+
fun handleButton(b : ButtonEnum.state) : int {
6+
match (b) {
7+
ButtonEnum.Push -> return 1;
8+
ButtonEnum.Release -> return 2;
9+
ButtonEnum.Hold -> return 3;
10+
}
11+
}
12+
13+
// Test with mixed patterns (qualified and wildcard)
14+
fun handleButtonWithDefault(b : ButtonEnum.state) : int {
15+
match (b) {
16+
ButtonEnum.Push -> return 10;
17+
_ -> return 0;
18+
}
19+
}
20+
21+
// Main test function
22+
fun main() : int {
23+
// Test basic qualified enum patterns
24+
val result1 = handleButton(ButtonEnum.Push); // Should return 1
25+
val result2 = handleButton(ButtonEnum.Release); // Should return 2
26+
val result3 = handleButton(ButtonEnum.Hold); // Should return 3
27+
28+
// Test with default case
29+
val result4 = handleButtonWithDefault(ButtonEnum.Push); // Should return 10
30+
val result5 = handleButtonWithDefault(ButtonEnum.Release); // Should return 0
31+
32+
// Verify all results
33+
if (result1 == 1 && result2 == 2 && result3 == 3) {
34+
if (result4 == 10 && result5 == 0) {
35+
return 100; // All tests passed
36+
}
37+
}
38+
39+
return -1; // Some test failed
40+
}

test/test.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ let interpreter =
200200
; "instance_state.vult"
201201
; "int16_test.vult"
202202
; "memory_state.vult"
203+
; "qualified_enum_patterns.vult"
203204
; "strength_reduction.vult"
204205
]
205206

0 commit comments

Comments
 (0)