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:
parent
8be85e7590
commit
3aad5e2a8d
|
@ -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 {
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
23
vlib/v/tests/multi_line_with_optionals_test.v
Normal file
23
vlib/v/tests/multi_line_with_optionals_test.v
Normal 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user