cgen: fix match_return with complex expr stmts (#8876)
parent
44177c4e7c
commit
e106dc3ad5
|
@ -3488,6 +3488,30 @@ fn (mut g Gen) lock_expr(node ast.LockExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool {
|
||||||
|
if node.is_expr && node.return_type != table.void_type && node.return_type != 0 {
|
||||||
|
sym := g.table.get_type_symbol(node.return_type)
|
||||||
|
if sym.kind == .multi_return {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for branch in node.branches {
|
||||||
|
if branch.stmts.len > 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if branch.stmts.len == 1 {
|
||||||
|
if branch.stmts[0] is ast.ExprStmt {
|
||||||
|
stmt := branch.stmts[0] as ast.ExprStmt
|
||||||
|
if stmt.expr is ast.CallExpr || stmt.expr is ast.IfExpr
|
||||||
|
|| stmt.expr is ast.MatchExpr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
// println('match expr typ=$it.expr_type')
|
// println('match expr typ=$it.expr_type')
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -3495,11 +3519,13 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
g.writeln('// match 0')
|
g.writeln('// match 0')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
need_tmp_var := g.need_tmp_var_in_match(node)
|
||||||
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary > 0
|
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary > 0
|
||||||
mut cond_var := ''
|
mut cond_var := ''
|
||||||
if is_expr {
|
mut tmp_var := ''
|
||||||
|
mut cur_line := ''
|
||||||
|
if is_expr && !need_tmp_var {
|
||||||
g.inside_ternary++
|
g.inside_ternary++
|
||||||
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
|
|
||||||
}
|
}
|
||||||
if node.cond is ast.Ident || node.cond is ast.SelectorExpr || node.cond is ast.IntegerLiteral
|
if node.cond is ast.Ident || node.cond is ast.SelectorExpr || node.cond is ast.IntegerLiteral
|
||||||
|| node.cond is ast.StringLiteral || node.cond is ast.FloatLiteral {
|
|| node.cond is ast.StringLiteral || node.cond is ast.FloatLiteral {
|
||||||
|
@ -3509,7 +3535,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
g.out.go_back(cond_var.len)
|
g.out.go_back(cond_var.len)
|
||||||
cond_var = cond_var.trim_space()
|
cond_var = cond_var.trim_space()
|
||||||
} else {
|
} else {
|
||||||
cur_line := if is_expr {
|
line := if is_expr {
|
||||||
g.empty_line = true
|
g.empty_line = true
|
||||||
g.go_before_stmt(0)
|
g.go_before_stmt(0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3519,25 +3545,35 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||||
g.write('${g.typ(node.cond_type)} $cond_var = ')
|
g.write('${g.typ(node.cond_type)} $cond_var = ')
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.writeln('; ')
|
g.writeln('; ')
|
||||||
g.write(cur_line)
|
g.write(line)
|
||||||
|
}
|
||||||
|
if need_tmp_var {
|
||||||
|
g.empty_line = true
|
||||||
|
cur_line = g.go_before_stmt(0)
|
||||||
|
tmp_var = g.new_tmp_var()
|
||||||
|
g.writeln('\t${g.typ(node.return_type)} $tmp_var;')
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_expr {
|
if is_expr && !need_tmp_var {
|
||||||
// brackets needed otherwise '?' will apply to everything on the left
|
// brackets needed otherwise '?' will apply to everything on the left
|
||||||
g.write('(')
|
g.write('(')
|
||||||
}
|
}
|
||||||
if node.is_sum_type {
|
if node.is_sum_type {
|
||||||
g.match_expr_sumtype(node, is_expr, cond_var)
|
g.match_expr_sumtype(node, is_expr, cond_var, tmp_var)
|
||||||
} else {
|
} else {
|
||||||
g.match_expr_classic(node, is_expr, cond_var)
|
g.match_expr_classic(node, is_expr, cond_var, tmp_var)
|
||||||
}
|
}
|
||||||
if is_expr {
|
g.write(cur_line)
|
||||||
|
if need_tmp_var {
|
||||||
|
g.write('$tmp_var')
|
||||||
|
}
|
||||||
|
if is_expr && !need_tmp_var {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
g.decrement_inside_ternary()
|
g.decrement_inside_ternary()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string) {
|
fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
|
||||||
for j, branch in node.branches {
|
for j, branch in node.branches {
|
||||||
mut sumtype_index := 0
|
mut sumtype_index := 0
|
||||||
// iterates through all types in sumtype branches
|
// iterates through all types in sumtype branches
|
||||||
|
@ -3545,8 +3581,8 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.aggregate_type_idx = sumtype_index
|
g.aggregate_type_idx = sumtype_index
|
||||||
is_last := j == node.branches.len - 1
|
is_last := j == node.branches.len - 1
|
||||||
sym := g.table.get_type_symbol(node.cond_type)
|
sym := g.table.get_type_symbol(node.cond_type)
|
||||||
if branch.is_else || (node.is_expr && is_last) {
|
if branch.is_else || (node.is_expr && is_last && tmp_var.len == 0) {
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
// TODO too many branches. maybe separate ?: matches
|
// TODO too many branches. maybe separate ?: matches
|
||||||
g.write(' : ')
|
g.write(' : ')
|
||||||
} else {
|
} else {
|
||||||
|
@ -3556,7 +3592,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if j > 0 || sumtype_index > 0 {
|
if j > 0 || sumtype_index > 0 {
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write(' : ')
|
g.write(' : ')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
|
@ -3564,7 +3600,7 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.write('else ')
|
g.write('else ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
} else {
|
} else {
|
||||||
if j == 0 && sumtype_index == 0 {
|
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
|
||||||
g.write('._interface_idx == ')
|
g.write('._interface_idx == ')
|
||||||
}
|
}
|
||||||
g.expr(branch.exprs[sumtype_index])
|
g.expr(branch.exprs[sumtype_index])
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write(') ? ')
|
g.write(') ? ')
|
||||||
} else {
|
} else {
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.stmts(branch.stmts)
|
g.stmts_with_tmp_var(branch.stmts, tmp_var)
|
||||||
if g.inside_ternary == 0 {
|
if g.inside_ternary == 0 {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
|
@ -3604,13 +3640,13 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string) {
|
fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
|
||||||
type_sym := g.table.get_type_symbol(node.cond_type)
|
type_sym := g.table.get_type_symbol(node.cond_type)
|
||||||
for j, branch in node.branches {
|
for j, branch in node.branches {
|
||||||
is_last := j == node.branches.len - 1
|
is_last := j == node.branches.len - 1
|
||||||
if branch.is_else || (node.is_expr && is_last) {
|
if branch.is_else || (node.is_expr && is_last && tmp_var.len == 0) {
|
||||||
if node.branches.len > 1 {
|
if node.branches.len > 1 {
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
// TODO too many branches. maybe separate ?: matches
|
// TODO too many branches. maybe separate ?: matches
|
||||||
g.write(' : ')
|
g.write(' : ')
|
||||||
} else {
|
} else {
|
||||||
|
@ -3621,7 +3657,7 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write(' : ')
|
g.write(' : ')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
|
@ -3629,7 +3665,7 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.write('else ')
|
g.write('else ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
} else {
|
} else {
|
||||||
if j == 0 {
|
if j == 0 {
|
||||||
|
@ -3678,13 +3714,13 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_expr {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write(') ? ')
|
g.write(') ? ')
|
||||||
} else {
|
} else {
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.stmts(branch.stmts)
|
g.stmts_with_tmp_var(branch.stmts, tmp_var)
|
||||||
if g.inside_ternary == 0 && node.branches.len > 1 {
|
if g.inside_ternary == 0 && node.branches.len > 1 {
|
||||||
g.write('}')
|
g.write('}')
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
type Arr = []int | []string
|
||||||
|
|
||||||
|
fn test_match_with_array_map_in_branches() {
|
||||||
|
arr := Arr([0, 1])
|
||||||
|
ret := match arr {
|
||||||
|
[]int {
|
||||||
|
arr.map(fn(s int) string { return s.str() }).str()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(ret)
|
||||||
|
assert ret == "['0', '1']"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_match_expr_of_multi_expr_stmts() {
|
||||||
|
a := 1
|
||||||
|
ret := match a {
|
||||||
|
1 {
|
||||||
|
mut m := map[string]int{}
|
||||||
|
m['two'] = 2
|
||||||
|
m['two']
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(ret)
|
||||||
|
assert ret == 2
|
||||||
|
}
|
Loading…
Reference in New Issue