Skip to content

Commit 2c5a2c8

Browse files
wasm: support basic match keyword handling (#26246)
1 parent 8018dde commit 2c5a2c8

File tree

6 files changed

+346
-1
lines changed

6 files changed

+346
-1
lines changed

vlib/v/gen/wasm/gen.v

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,90 @@ pub fn (mut g Gen) if_expr(ifexpr ast.IfExpr, expected ast.Type, existing_rvars
553553
g.if_branch(ifexpr, expected, params, 0, existing_rvars)
554554
}
555555

556+
pub fn (mut g Gen) match_expr(node ast.MatchExpr, expected ast.Type, existing_rvars []Var) {
557+
results := if expected == ast.void_type {
558+
[]wasm.ValType{}
559+
} else if existing_rvars.len == 0 {
560+
g.unpack_type(expected).map(g.get_wasm_type(it))
561+
} else {
562+
g.unpack_type(expected).filter(!g.is_param_type(it)).map(g.get_wasm_type(it))
563+
}
564+
g.match_branch(node, expected, results, 0, existing_rvars)
565+
}
566+
567+
fn (mut g Gen) match_branch(node ast.MatchExpr, expected ast.Type, unpacked_params []wasm.ValType, branch_idx int, existing_rvars []Var) {
568+
if branch_idx >= node.branches.len {
569+
return
570+
}
571+
572+
branch := node.branches[branch_idx]
573+
mut is_last_branch := branch_idx + 1 >= node.branches.len
574+
mut has_else := branch.is_else
575+
576+
if has_else {
577+
if branch.stmts.len > 0 {
578+
g.rvar_expr_stmts(branch.stmts, expected, existing_rvars)
579+
}
580+
return
581+
}
582+
583+
if branch.exprs.len > 0 {
584+
g.match_branch_exprs(node, expected, unpacked_params, branch_idx, 0, existing_rvars,
585+
branch)
586+
} else {
587+
if branch.stmts.len > 0 {
588+
g.rvar_expr_stmts(branch.stmts, expected, existing_rvars)
589+
}
590+
if !is_last_branch {
591+
g.match_branch(node, expected, unpacked_params, branch_idx + 1, existing_rvars)
592+
}
593+
}
594+
}
595+
596+
fn (mut g Gen) match_branch_exprs(node ast.MatchExpr, expected ast.Type, unpacked_params []wasm.ValType, branch_idx int, expr_idx int, existing_rvars []Var, branch ast.MatchBranch) {
597+
if expr_idx >= branch.exprs.len {
598+
return
599+
}
600+
601+
mut is_last_branch := branch_idx + 1 >= node.branches.len
602+
mut is_last_expr := expr_idx + 1 >= branch.exprs.len
603+
604+
wasm_type := g.as_numtype(g.get_wasm_type(node.cond_type))
605+
606+
expr := branch.exprs[expr_idx]
607+
608+
if expr is ast.RangeExpr {
609+
is_signed := node.cond_type.is_signed()
610+
611+
g.expr(node.cond, node.cond_type)
612+
g.expr(expr.high, node.cond_type)
613+
g.func.le(wasm_type, is_signed)
614+
} else {
615+
g.expr(node.cond, node.cond_type)
616+
g.expr(expr, node.cond_type)
617+
g.func.eq(wasm_type)
618+
}
619+
620+
blk := g.func.c_if([], unpacked_params)
621+
{
622+
if branch.stmts.len > 0 {
623+
g.rvar_expr_stmts(branch.stmts, expected, existing_rvars)
624+
}
625+
}
626+
{
627+
g.func.c_else(blk)
628+
if is_last_expr {
629+
if !is_last_branch {
630+
g.match_branch(node, expected, unpacked_params, branch_idx + 1, existing_rvars)
631+
}
632+
} else {
633+
g.match_branch_exprs(node, expected, unpacked_params, branch_idx, expr_idx + 1,
634+
existing_rvars, branch)
635+
}
636+
}
637+
g.func.c_end(blk)
638+
}
639+
556640
pub fn (mut g Gen) call_expr(node ast.CallExpr, expected ast.Type, existing_rvars []Var) {
557641
mut wasm_ns := ?string(none)
558642
mut name := node.name
@@ -850,7 +934,7 @@ pub fn (mut g Gen) expr(node ast.Expr, expected ast.Type) {
850934
g.cast(node.typ, expected)
851935
}
852936
ast.MatchExpr {
853-
g.w_error('wasm backend does not support match expressions yet')
937+
g.match_expr(node, expected, [])
854938
}
855939
ast.EnumVal {
856940
type_name := g.table.get_type_name(node.typ)

vlib/v/gen/wasm/mem.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,9 @@ pub fn (mut g Gen) set_with_multi_expr(init ast.Expr, expected ast.Type, existin
654654
ast.IfExpr {
655655
g.if_expr(init, expected, existing_rvars)
656656
}
657+
ast.MatchExpr {
658+
g.match_expr(init, expected, existing_rvars)
659+
}
657660
ast.CallExpr {
658661
g.call_expr(init, expected, existing_rvars)
659662
}

vlib/v/gen/wasm/tests/match.vv

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
enum BasicTestEnum {
2+
first_element
3+
second_element
4+
other_element
5+
}
6+
7+
fn function_matches(value u8) {
8+
match value {
9+
42 {
10+
println('function_matches: OK')
11+
}
12+
else {
13+
println('function_matches: Error')
14+
}
15+
}
16+
}
17+
18+
fn main() {
19+
a := 1
20+
match a {
21+
1 { println('1') }
22+
else { println('other') }
23+
}
24+
25+
b := 2
26+
match b {
27+
1 { println('1') }
28+
2 { println('2') }
29+
3 { println('3') }
30+
4 { println('4') }
31+
5 { println('5') }
32+
6 { println('6') }
33+
7 { println('7') }
34+
8 { println('8') }
35+
9 { println('9') }
36+
else { println('other') }
37+
}
38+
39+
c := 3
40+
match c {
41+
1, 2 { println('1 or 2') }
42+
else { println('other') }
43+
}
44+
45+
d := match a {
46+
1 { 10 }
47+
else { 30 }
48+
}
49+
println(d)
50+
51+
e := match b {
52+
1 { 100 }
53+
2 { 200 }
54+
3, 4 { 340 }
55+
else { 300 }
56+
}
57+
println(e)
58+
59+
println(match c {
60+
1, 2 { i64(1000) }
61+
else { i64(2000) }
62+
})
63+
64+
println('Enum matches -------')
65+
66+
f := BasicTestEnum.first_element
67+
println(match f {
68+
.first_element { 'First Element' }
69+
.second_element { 'Second Element' }
70+
else { 'Other Element' }
71+
})
72+
73+
println('Bool matches -------')
74+
75+
println(match true {
76+
true {
77+
'OK'
78+
}
79+
else {
80+
'ERROR'
81+
}
82+
})
83+
84+
g := false
85+
println(match g {
86+
false {
87+
'OK'
88+
}
89+
else {
90+
'ERROR'
91+
}
92+
})
93+
94+
println('Function calling matches -------')
95+
function_matches(42)
96+
97+
/*
98+
println("Strings matches -------")
99+
100+
// This doesn't work yet because string comparison is not ready (
101+
h := 'Hello'
102+
println(match h {
103+
'NotHello' { 'Not Hello string' }
104+
'Hello' { 'Hello string' }
105+
else { 'Unknown' }
106+
})
107+
*/
108+
}

vlib/v/gen/wasm/tests/match.vv.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
1
2+
2
3+
other
4+
10
5+
200
6+
2000
7+
Enum matches -------
8+
First Element
9+
Bool matches -------
10+
OK
11+
OK
12+
Function calling matches -------
13+
function_matches: OK
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
fn main() {
2+
g := 32
3+
result1 := match g {
4+
1...64 {
5+
'Right'
6+
}
7+
else {
8+
'Wrong'
9+
}
10+
}
11+
println(result1)
12+
13+
h := 100
14+
result2 := match h {
15+
1...64 {
16+
'Wrong'
17+
}
18+
else {
19+
'Right'
20+
}
21+
}
22+
println(result2)
23+
24+
i := 1
25+
result3 := match i {
26+
1...10 {
27+
'Right'
28+
}
29+
else {
30+
'Wrong'
31+
}
32+
}
33+
println(result3)
34+
35+
j := 10
36+
result4 := match j {
37+
1...10 {
38+
'Right'
39+
}
40+
else {
41+
'Wrong'
42+
}
43+
}
44+
println(result4)
45+
46+
k := 50
47+
result5 := match k {
48+
1...32 {
49+
'Wrong'
50+
}
51+
33...64 {
52+
'Right'
53+
}
54+
else {
55+
'Wrong'
56+
}
57+
}
58+
println(result5)
59+
60+
n := 15
61+
result6 := match n {
62+
1...10 {
63+
10
64+
}
65+
11...20 {
66+
20
67+
}
68+
else {
69+
0
70+
}
71+
}
72+
println(result6)
73+
74+
o := i64(500)
75+
result7 := match o {
76+
i64(1)...i64(1000) {
77+
'Right'
78+
}
79+
else {
80+
'Wrong'
81+
}
82+
}
83+
println(result7)
84+
85+
p := u32(50)
86+
result8 := match p {
87+
u32(0)...u32(100) {
88+
'Right'
89+
}
90+
else {
91+
'Wrong'
92+
}
93+
}
94+
println(result8)
95+
96+
r := -5
97+
result9 := match r {
98+
-10...-1 {
99+
'Right'
100+
}
101+
else {
102+
'Wrong'
103+
}
104+
}
105+
println(result9)
106+
107+
s := 0
108+
result10 := match s {
109+
-10...25 {
110+
'Right'
111+
}
112+
else {
113+
'Wrong'
114+
}
115+
}
116+
println(result10)
117+
118+
println(match 1234 {
119+
-1200...1 {
120+
'Wrong'
121+
}
122+
else {
123+
'Right'
124+
}
125+
})
126+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Right
2+
Right
3+
Right
4+
Right
5+
Right
6+
20
7+
Right
8+
Right
9+
Right
10+
Right
11+
Right

0 commit comments

Comments
 (0)