Skip to content

Commit ac57626

Browse files
committed
[Tolk] Pattern matching for expressions (switch-like behavior)
`match` can also be used for constant expressions, similar to `switch`: > val nextValue = match (curValue) { > 1 => 0, > 0 => 1, > else => -1 > }; Only constant expressions are allowed on the left-hand side. `else` is required for expression form but optional for statement form.
1 parent 249badf commit ac57626

17 files changed

+551
-55
lines changed

tolk-tester/tests/if-else-tests.tolk

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,33 @@ fun test7() {
7272
// here we test that no "missing return" error
7373
}
7474

75+
fun withNoElse(op: int): int {
76+
if (op == 123) { return 100; }
77+
if (op == 234) { return 200; }
78+
if (op == 345) { return 300; }
79+
throw 0xFF;
80+
}
81+
82+
fun withElse(op: int): int {
83+
if (op == 123) { return 100; }
84+
else if (op == 234) { return 200; }
85+
else if (op == 345) { return 300; }
86+
return 0xFF;
87+
}
88+
89+
fun withMatch(op: int): int {
90+
match (op) {
91+
123 => return 100,
92+
234 => return 200,
93+
345 => return 300,
94+
}
95+
throw 0xFF;
96+
}
97+
98+
@method_id(108)
99+
fun test8(op: int) {
100+
return (withNoElse(op), withElse(op), withMatch(op));
101+
}
75102

76103
fun main() {
77104

@@ -96,6 +123,8 @@ fun main() {
96123
@testcase | 105 | 3 | 7 222
97124
@testcase | 106 | -5 | -1
98125
@testcase | 106 | 5 | 5000
126+
@testcase | 108 | 123 | 100 100 100
127+
@testcase | 108 | 345 | 300 300 300
99128

100129
@fif_codegen
101130
"""
@@ -111,4 +140,82 @@ fun main() {
111140
50 EQINT // x '5
112141
IFNOTJMP:<{ // x
113142
"""
143+
144+
@fif_codegen
145+
"""
146+
withNoElse PROC:<{
147+
// op
148+
DUP
149+
123 EQINT
150+
IFJMP:<{
151+
DROP
152+
100 PUSHINT
153+
}>
154+
DUP
155+
234 PUSHINT
156+
EQUAL
157+
IFJMP:<{
158+
DROP
159+
200 PUSHINT
160+
}>
161+
345 PUSHINT
162+
EQUAL
163+
IFJMP:<{
164+
300 PUSHINT
165+
}>
166+
255 THROW
167+
}>
168+
"""
169+
170+
@fif_codegen
171+
"""
172+
withElse PROC:<{
173+
// op
174+
DUP
175+
123 EQINT
176+
IFJMP:<{
177+
DROP
178+
100 PUSHINT
179+
}>
180+
DUP
181+
234 PUSHINT
182+
EQUAL
183+
IFJMP:<{
184+
DROP
185+
200 PUSHINT
186+
}>
187+
345 PUSHINT
188+
EQUAL
189+
IFJMP:<{
190+
300 PUSHINT
191+
}>
192+
8 PUSHPOW2DEC
193+
}>
194+
"""
195+
196+
@fif_codegen
197+
"""
198+
withMatch PROC:<{
199+
// op
200+
DUP
201+
123 EQINT
202+
IFJMP:<{
203+
DROP
204+
100 PUSHINT
205+
}>
206+
DUP
207+
234 PUSHINT
208+
EQUAL
209+
IFJMP:<{
210+
DROP
211+
200 PUSHINT
212+
}>
213+
345 PUSHINT
214+
EQUAL
215+
IFJMP:<{
216+
300 PUSHINT
217+
}>
218+
255 THROW
219+
}>
220+
"""
114221
*/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const C = match (10) { 10 => 0, else => -1 };
2+
3+
/**
4+
@compilation_should_fail
5+
@stderr not a constant expression
6+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun f(x: int): int {
2+
return match(x) {
3+
-1 => -1,
4+
f(0) => 0,
5+
else => 1,
6+
};
7+
}
8+
9+
/**
10+
@compilation_should_fail
11+
@stderr not a constant expression
12+
@stderr f(0) => 0
13+
*/
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
global g: int;
2+
3+
fun f(x: int): int {
4+
match(x) {
5+
-1 => -1,
6+
g => 0,
7+
};
8+
return 10;
9+
}
10+
11+
/**
12+
@compilation_should_fail
13+
@stderr symbol `g` is not a constant
14+
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun f(x: int) {
2+
return match(x) {
3+
-1 => -1,
4+
0 => 0
5+
};
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr `match` expression should have `else` branch
11+
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fun f(x: int) {
2+
return match(x) {
3+
-1 => -1,
4+
else => 0,
5+
0 => 0
6+
};
7+
}
8+
9+
/**
10+
@compilation_should_fail
11+
@stderr `else` branch should be the last
12+
*/

tolk-tester/tests/invalid-syntax/err-3457.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ fun main() {
1313

1414
/**
1515
@compilation_should_fail
16-
@stderr `match` by expression is not supported yet
16+
@stderr symbol `asdf` is not a constant
1717
@stderr asdf => 2
1818
*/
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fun f(x: int) {
2+
match(x) {
3+
-1 => -1,
4+
0 => 0,
5+
else => 0,
6+
else => -1
7+
};
8+
}
9+
10+
/**
11+
@compilation_should_fail
12+
@stderr duplicated `else` branch
13+
@stderr else => -1
14+
*/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fun f(x: bool) {
2+
return match (x) { true => 0, true => -1 };
3+
}
4+
5+
/**
6+
@compilation_should_fail
7+
@stderr `match` expression should have `else` branch
8+
*/

0 commit comments

Comments
 (0)