Skip to content

Commit e106dc3

Browse files
authored
cgen: fix match_return with complex expr stmts (#8876)
1 parent 44177c4 commit e106dc3

File tree

2 files changed

+89
-22
lines changed

2 files changed

+89
-22
lines changed

vlib/v/gen/c/cgen.v

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3488,18 +3488,44 @@ fn (mut g Gen) lock_expr(node ast.LockExpr) {
34883488
}
34893489
}
34903490

3491+
fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool {
3492+
if node.is_expr && node.return_type != table.void_type && node.return_type != 0 {
3493+
sym := g.table.get_type_symbol(node.return_type)
3494+
if sym.kind == .multi_return {
3495+
return false
3496+
}
3497+
for branch in node.branches {
3498+
if branch.stmts.len > 1 {
3499+
return true
3500+
}
3501+
if branch.stmts.len == 1 {
3502+
if branch.stmts[0] is ast.ExprStmt {
3503+
stmt := branch.stmts[0] as ast.ExprStmt
3504+
if stmt.expr is ast.CallExpr || stmt.expr is ast.IfExpr
3505+
|| stmt.expr is ast.MatchExpr {
3506+
return true
3507+
}
3508+
}
3509+
}
3510+
}
3511+
}
3512+
return false
3513+
}
3514+
34913515
fn (mut g Gen) match_expr(node ast.MatchExpr) {
34923516
// println('match expr typ=$it.expr_type')
34933517
// TODO
34943518
if node.cond_type == 0 {
34953519
g.writeln('// match 0')
34963520
return
34973521
}
3522+
need_tmp_var := g.need_tmp_var_in_match(node)
34983523
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary > 0
34993524
mut cond_var := ''
3500-
if is_expr {
3525+
mut tmp_var := ''
3526+
mut cur_line := ''
3527+
if is_expr && !need_tmp_var {
35013528
g.inside_ternary++
3502-
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
35033529
}
35043530
if node.cond is ast.Ident || node.cond is ast.SelectorExpr || node.cond is ast.IntegerLiteral
35053531
|| node.cond is ast.StringLiteral || node.cond is ast.FloatLiteral {
@@ -3509,7 +3535,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
35093535
g.out.go_back(cond_var.len)
35103536
cond_var = cond_var.trim_space()
35113537
} else {
3512-
cur_line := if is_expr {
3538+
line := if is_expr {
35133539
g.empty_line = true
35143540
g.go_before_stmt(0)
35153541
} else {
@@ -3519,34 +3545,44 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
35193545
g.write('${g.typ(node.cond_type)} $cond_var = ')
35203546
g.expr(node.cond)
35213547
g.writeln('; ')
3522-
g.write(cur_line)
3548+
g.write(line)
3549+
}
3550+
if need_tmp_var {
3551+
g.empty_line = true
3552+
cur_line = g.go_before_stmt(0)
3553+
tmp_var = g.new_tmp_var()
3554+
g.writeln('\t${g.typ(node.return_type)} $tmp_var;')
35233555
}
35243556

3525-
if is_expr {
3557+
if is_expr && !need_tmp_var {
35263558
// brackets needed otherwise '?' will apply to everything on the left
35273559
g.write('(')
35283560
}
35293561
if node.is_sum_type {
3530-
g.match_expr_sumtype(node, is_expr, cond_var)
3562+
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
35313563
} else {
3532-
g.match_expr_classic(node, is_expr, cond_var)
3564+
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
35333565
}
3534-
if is_expr {
3566+
g.write(cur_line)
3567+
if need_tmp_var {
3568+
g.write('$tmp_var')
3569+
}
3570+
if is_expr && !need_tmp_var {
35353571
g.write(')')
35363572
g.decrement_inside_ternary()
35373573
}
35383574
}
35393575

3540-
fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string) {
3576+
fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
35413577
for j, branch in node.branches {
35423578
mut sumtype_index := 0
35433579
// iterates through all types in sumtype branches
35443580
for {
35453581
g.aggregate_type_idx = sumtype_index
35463582
is_last := j == node.branches.len - 1
35473583
sym := g.table.get_type_symbol(node.cond_type)
3548-
if branch.is_else || (node.is_expr && is_last) {
3549-
if is_expr {
3584+
if branch.is_else || (node.is_expr && is_last && tmp_var.len == 0) {
3585+
if is_expr && tmp_var.len == 0 {
35503586
// TODO too many branches. maybe separate ?: matches
35513587
g.write(' : ')
35523588
} else {
@@ -3556,15 +3592,15 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
35563592
}
35573593
} else {
35583594
if j > 0 || sumtype_index > 0 {
3559-
if is_expr {
3595+
if is_expr && tmp_var.len == 0 {
35603596
g.write(' : ')
35613597
} else {
35623598
g.writeln('')
35633599
g.write_v_source_line_info(branch.pos)
35643600
g.write('else ')
35653601
}
35663602
}
3567-
if is_expr {
3603+
if is_expr && tmp_var.len == 0 {
35683604
g.write('(')
35693605
} else {
35703606
if j == 0 && sumtype_index == 0 {
@@ -3584,13 +3620,13 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
35843620
g.write('._interface_idx == ')
35853621
}
35863622
g.expr(branch.exprs[sumtype_index])
3587-
if is_expr {
3623+
if is_expr && tmp_var.len == 0 {
35883624
g.write(') ? ')
35893625
} else {
35903626
g.writeln(') {')
35913627
}
35923628
}
3593-
g.stmts(branch.stmts)
3629+
g.stmts_with_tmp_var(branch.stmts, tmp_var)
35943630
if g.inside_ternary == 0 {
35953631
g.write('}')
35963632
}
@@ -3604,13 +3640,13 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
36043640
}
36053641
}
36063642

3607-
fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string) {
3643+
fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
36083644
type_sym := g.table.get_type_symbol(node.cond_type)
36093645
for j, branch in node.branches {
36103646
is_last := j == node.branches.len - 1
3611-
if branch.is_else || (node.is_expr && is_last) {
3647+
if branch.is_else || (node.is_expr && is_last && tmp_var.len == 0) {
36123648
if node.branches.len > 1 {
3613-
if is_expr {
3649+
if is_expr && tmp_var.len == 0 {
36143650
// TODO too many branches. maybe separate ?: matches
36153651
g.write(' : ')
36163652
} else {
@@ -3621,15 +3657,15 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
36213657
}
36223658
} else {
36233659
if j > 0 {
3624-
if is_expr {
3660+
if is_expr && tmp_var.len == 0 {
36253661
g.write(' : ')
36263662
} else {
36273663
g.writeln('')
36283664
g.write_v_source_line_info(branch.pos)
36293665
g.write('else ')
36303666
}
36313667
}
3632-
if is_expr {
3668+
if is_expr && tmp_var.len == 0 {
36333669
g.write('(')
36343670
} else {
36353671
if j == 0 {
@@ -3678,13 +3714,13 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
36783714
g.expr(expr)
36793715
}
36803716
}
3681-
if is_expr {
3717+
if is_expr && tmp_var.len == 0 {
36823718
g.write(') ? ')
36833719
} else {
36843720
g.writeln(') {')
36853721
}
36863722
}
3687-
g.stmts(branch.stmts)
3723+
g.stmts_with_tmp_var(branch.stmts, tmp_var)
36883724
if g.inside_ternary == 0 && node.branches.len > 1 {
36893725
g.write('}')
36903726
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
type Arr = []int | []string
2+
3+
fn test_match_with_array_map_in_branches() {
4+
arr := Arr([0, 1])
5+
ret := match arr {
6+
[]int {
7+
arr.map(fn(s int) string { return s.str() }).str()
8+
}
9+
else {
10+
''
11+
}
12+
}
13+
println(ret)
14+
assert ret == "['0', '1']"
15+
}
16+
17+
fn test_match_expr_of_multi_expr_stmts() {
18+
a := 1
19+
ret := match a {
20+
1 {
21+
mut m := map[string]int{}
22+
m['two'] = 2
23+
m['two']
24+
}
25+
else {
26+
int(0)
27+
}
28+
}
29+
println(ret)
30+
assert ret == 2
31+
}

0 commit comments

Comments
 (0)