1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser, cgen: fix anon fn optional call in if expr (#16803)

This commit is contained in:
yuyi 2022-12-29 23:53:17 +08:00 committed by GitHub
parent cd4ea16609
commit 36ab78d6da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 1 deletions

View File

@ -652,7 +652,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
g.expr(node.left)
g.writeln(';')
g.write(tmp_var)
} else {
} else if node.or_block.kind == .absent {
g.expr(node.left)
}
} else if node.left is ast.IndexExpr && node.name == '' {
@ -695,6 +695,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
g.write('${tmp_opt} = ')
} else {
g.write('${styp} ${tmp_opt} = ')
if node.left is ast.AnonFn {
g.expr(node.left)
}
}
}
if node.is_method && !node.is_field {

View File

@ -387,11 +387,35 @@ pub fn (mut p Parser) check_expr(precedence int) !ast.Expr {
pos := p.tok.pos()
args := p.call_args()
p.check(.rpar)
mut or_kind := ast.OrKind.absent
mut or_stmts := []ast.Stmt{} // TODO remove unnecessary allocations by just using .absent
mut or_pos := p.tok.pos()
if p.tok.kind == .key_orelse {
// `foo() or {}``
or_kind = .block
or_stmts, or_pos = p.or_block(.with_err_var)
}
if p.tok.kind in [.question, .not] {
is_not := p.tok.kind == .not
// `foo()?`
p.next()
if p.inside_defer {
p.error_with_pos('error propagation not allowed inside `defer` blocks',
p.prev_tok.pos())
}
or_kind = if is_not { .propagate_result } else { .propagate_option }
}
node = ast.CallExpr{
name: 'anon'
left: node
args: args
pos: pos
or_block: ast.OrExpr{
stmts: or_stmts
kind: or_kind
pos: or_pos
}
scope: p.scope
}
}

View File

@ -0,0 +1,35 @@
fn test_anon_fn_optional_call_in_if_expr_1() {
if fn () ?bool {
return true
}() or { false }
{
println('ok')
assert true
} else {
assert false
}
}
fn test_anon_fn_optional_call_in_if_expr_2() {
if fn () ?bool {
return true
}()?
{
println('ok')
assert true
} else {
assert false
}
}
fn test_anon_fn_optional_call_in_if_expr_3() {
if fn () !bool {
return true
}()!
{
println('ok')
assert true
} else {
assert false
}
}