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

cgen, checker: fix multi line return optional (#15428)

This commit is contained in:
Nikolai 2022-08-15 23:43:56 +03:00 committed by GitHub
parent 8be85e7590
commit 3aad5e2a8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 1 deletions

View File

@ -166,6 +166,12 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
if expr_required {
if branch.stmts.len > 0 && branch.stmts.last() is ast.ExprStmt {
mut last_expr := branch.stmts.last() as ast.ExprStmt
expr := last_expr.expr
if expr is ast.ConcatExpr {
for val in expr.vals {
c.check_expr_opt_call(val, c.expr(val))
}
}
c.expected_type = former_expected_type
if c.expected_type.has_flag(.optional) {
if node.typ == ast.void_type {

View File

@ -1434,6 +1434,7 @@ pub fn (mut g Gen) write_fn_typesymbol_declaration(sym ast.TypeSymbol) {
}
pub fn (mut g Gen) write_multi_return_types() {
start_pos := g.type_definitions.len
g.typedefs.writeln('\n// BEGIN_multi_return_typedefs')
g.type_definitions.writeln('\n// BEGIN_multi_return_structs')
for sym in g.table.type_symbols {
@ -1451,6 +1452,22 @@ pub fn (mut g Gen) write_multi_return_types() {
g.type_definitions.writeln('struct $sym.cname {')
for i, mr_typ in info.types {
type_name := g.typ(mr_typ)
if mr_typ.has_flag(.optional) {
// optional in multi_return
// Dont use g.typ() here because it will register
// optional and we dont want that
styp, base := g.optional_type_name(mr_typ)
lock g.done_optionals {
if base !in g.done_optionals {
g.done_optionals << base
last_text := g.type_definitions.after(start_pos).clone()
g.type_definitions.go_back_to(start_pos)
g.typedefs.writeln('typedef struct $styp $styp;')
g.type_definitions.writeln('${g.optional_type_text(styp, base)};')
g.type_definitions.write_string(last_text)
}
}
}
g.type_definitions.writeln('\t$type_name arg$i;')
}
g.type_definitions.writeln('};\n')

View File

@ -51,6 +51,15 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool {
if expr is ast.ParExpr {
return g.need_tmp_var_in_expr(expr.expr)
}
if expr is ast.ConcatExpr {
for val in expr.vals {
if val is ast.CallExpr {
if val.return_type.has_flag(.optional) {
return true
}
}
}
}
return false
}
@ -59,7 +68,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
g.comptime_if(node)
return
}
// For simpe if expressions we can use C's `?:`
// For simple if expressions we can use C's `?:`
// `if x > 0 { 1 } else { 2 }` => `(x > 0)? (1) : (2)`
// For if expressions with multiple statements or another if expression inside, it's much
// easier to use a temp var, than do C tricks with commas, introduce special vars etc

View File

@ -0,0 +1,23 @@
module main
fn has_optional() ?int {
return 51
}
fn test_optionals_multi_line() ? {
var11, var12, var13, var14, var15 := if true {
println('dd')
if true {
has_optional()?, has_optional()?, has_optional()?, 28, has_optional()?
} else {
has_optional()?, has_optional()?, has_optional()?, has_optional()?, has_optional()?
}
} else {
has_optional()?, 4, 4, 4, 4
}
println(var11)
println(var12)
println(var13)
println(var14)
println(var15)
}