cgen: fix generated code for handling fn call with result/option return on match conditional (#21608)

This commit is contained in:
Felipe Pena 2024-05-31 16:49:17 -03:00 committed by GitHub
parent 5ac8249af7
commit 19c08f5e8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 3 deletions

View file

@ -81,7 +81,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
''
}
cond_var = g.new_tmp_var()
g.write('${g.typ(node.cond_type)} /*A*/ ${cond_var} = ')
g.write('${g.typ(node.cond_type)} ${cond_var} = ')
g.expr(node.cond)
g.writeln(';')
g.set_current_pos_as_last_stmt_pos()
@ -419,6 +419,8 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
node_cond_type_unsigned := node.cond_type in [ast.u16_type, ast.u32_type, ast.u64_type]
type_sym := g.table.final_sym(node.cond_type)
use_ternary := is_expr && tmp_var == ''
mut reset_if := false
mut has_goto := false
for j, branch in node.branches {
is_last := j == node.branches.len - 1
if branch.is_else || (use_ternary && is_last) {
@ -439,7 +441,11 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
} else {
g.writeln('')
g.write_v_source_line_info(branch)
g.write('else ')
if !reset_if {
g.write('else ')
} else {
reset_if = false
}
}
}
if use_ternary {
@ -451,6 +457,7 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
g.write_v_source_line_info(branch)
g.write('if (')
}
reset_if = branch.exprs.any(g.match_must_reset_if(it))
for i, expr in branch.exprs {
if i > 0 {
g.write(' || ')
@ -532,7 +539,33 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str
g.stmts_with_tmp_var(branch.stmts, tmp_var)
g.expected_cast_type = 0
if g.inside_ternary == 0 && node.branches.len >= 1 {
g.write('}')
if reset_if {
has_goto = true
g.writeln('\tgoto end_block_${node.pos.line_nr};')
g.writeln('}')
g.set_current_pos_as_last_stmt_pos()
} else {
g.write('}')
}
}
}
if has_goto {
g.writeln('end_block_${node.pos.line_nr}: {}')
g.set_current_pos_as_last_stmt_pos()
}
}
// match_must_reset_if checks if codegen must break the if-elseif sequence in another if expr
fn (mut g Gen) match_must_reset_if(node ast.Expr) bool {
return match node {
ast.CallExpr {
node.or_block.kind != .absent
}
ast.InfixExpr {
g.match_must_reset_if(node.left) || g.match_must_reset_if(node.right)
}
else {
false
}
}
}

View file

@ -0,0 +1,23 @@
fn try(this string) !bool {
return true
}
fn test_case1() {
a, b := match true {
try('foo')! { 'a', 'b' }
try('bar')! { 'c', 'd' }
else { 'e', 'f' }
}
assert a == 'a'
assert b == 'b'
}
fn test_case2() {
a, b := match true {
try('foo')! && try('foo') or { false } { 'a', 'b' }
try('bar') or { false } { 'c', 'd' }
else { 'e', 'f' }
}
assert a == 'a'
assert b == 'b'
}