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:
@ -166,6 +166,12 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||||||
if expr_required {
|
if expr_required {
|
||||||
if branch.stmts.len > 0 && branch.stmts.last() is ast.ExprStmt {
|
if branch.stmts.len > 0 && branch.stmts.last() is ast.ExprStmt {
|
||||||
mut last_expr := branch.stmts.last() as 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
|
c.expected_type = former_expected_type
|
||||||
if c.expected_type.has_flag(.optional) {
|
if c.expected_type.has_flag(.optional) {
|
||||||
if node.typ == ast.void_type {
|
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() {
|
pub fn (mut g Gen) write_multi_return_types() {
|
||||||
|
start_pos := g.type_definitions.len
|
||||||
g.typedefs.writeln('\n// BEGIN_multi_return_typedefs')
|
g.typedefs.writeln('\n// BEGIN_multi_return_typedefs')
|
||||||
g.type_definitions.writeln('\n// BEGIN_multi_return_structs')
|
g.type_definitions.writeln('\n// BEGIN_multi_return_structs')
|
||||||
for sym in g.table.type_symbols {
|
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 {')
|
g.type_definitions.writeln('struct $sym.cname {')
|
||||||
for i, mr_typ in info.types {
|
for i, mr_typ in info.types {
|
||||||
type_name := g.typ(mr_typ)
|
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('\t$type_name arg$i;')
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('};\n')
|
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 {
|
if expr is ast.ParExpr {
|
||||||
return g.need_tmp_var_in_expr(expr.expr)
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +68,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
|||||||
g.comptime_if(node)
|
g.comptime_if(node)
|
||||||
return
|
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)`
|
// `if x > 0 { 1 } else { 2 }` => `(x > 0)? (1) : (2)`
|
||||||
// For if expressions with multiple statements or another if expression inside, it's much
|
// 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
|
// 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)
|
||||||
|
}
|
Reference in New Issue
Block a user