mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
cgen: fix generated code for handling fn call with result/option return on match conditional (#21608)
This commit is contained in:
parent
5ac8249af7
commit
19c08f5e8c
2 changed files with 59 additions and 3 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
vlib/v/tests/match_expr_result_test.v
Normal file
23
vlib/v/tests/match_expr_result_test.v
Normal 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'
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue