mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix multi return assignment with option (#17676)
This commit is contained in:
@@ -174,7 +174,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
if return_type != ast.void_type && return_type != 0 {
|
if return_type != ast.void_type && return_type != 0 {
|
||||||
sym := g.table.sym(return_type)
|
sym := g.table.sym(return_type)
|
||||||
if sym.kind == .multi_return {
|
if sym.kind == .multi_return {
|
||||||
g.gen_multi_return_assign(node, return_type)
|
g.gen_multi_return_assign(node, return_type, sym)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,7 +668,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Type) {
|
fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Type, return_sym ast.TypeSymbol) {
|
||||||
// multi return
|
// multi return
|
||||||
// TODO Handle in if_expr
|
// TODO Handle in if_expr
|
||||||
mr_var_name := 'mr_${node.pos.pos}'
|
mr_var_name := 'mr_${node.pos.pos}'
|
||||||
@@ -681,6 +681,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
|
|||||||
g.write('${mr_styp} ${mr_var_name} = ')
|
g.write('${mr_styp} ${mr_var_name} = ')
|
||||||
g.expr(node.right[0])
|
g.expr(node.right[0])
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
|
mr_types := (return_sym.info as ast.MultiReturn).types
|
||||||
for i, lx in node.left {
|
for i, lx in node.left {
|
||||||
mut is_auto_heap := false
|
mut is_auto_heap := false
|
||||||
mut ident := ast.Ident{
|
mut ident := ast.Ident{
|
||||||
@@ -702,8 +703,26 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
|
|||||||
if lx.is_auto_deref_var() {
|
if lx.is_auto_deref_var() {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
}
|
}
|
||||||
g.expr(lx)
|
|
||||||
noscan := if is_auto_heap { g.check_noscan(return_type) } else { '' }
|
noscan := if is_auto_heap { g.check_noscan(return_type) } else { '' }
|
||||||
|
if node.left_types[i].has_flag(.option) {
|
||||||
|
base_typ := g.base_type(node.left_types[i])
|
||||||
|
tmp_var := if is_auto_heap {
|
||||||
|
'HEAP${noscan}(${styp}, ${mr_var_name}.arg${i})'
|
||||||
|
} else if is_option {
|
||||||
|
'(*((${g.base_type(return_type)}*)${mr_var_name}.data)).arg${i}'
|
||||||
|
} else {
|
||||||
|
'${mr_var_name}.arg${i}'
|
||||||
|
}
|
||||||
|
if mr_types[i].has_flag(.option) {
|
||||||
|
g.expr(lx)
|
||||||
|
g.write(' = ${tmp_var};')
|
||||||
|
} else {
|
||||||
|
g.write('_option_ok(&(${base_typ}[]) { ${tmp_var} }, (${option_name}*)(&')
|
||||||
|
g.expr(lx)
|
||||||
|
g.writeln('), sizeof(${base_typ}));')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.expr(lx)
|
||||||
if g.is_arraymap_set {
|
if g.is_arraymap_set {
|
||||||
if is_auto_heap {
|
if is_auto_heap {
|
||||||
g.writeln('HEAP${noscan}(${styp}, ${mr_var_name}.arg${i}) });')
|
g.writeln('HEAP${noscan}(${styp}, ${mr_var_name}.arg${i}) });')
|
||||||
@@ -722,6 +741,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if g.is_arraymap_set {
|
if g.is_arraymap_set {
|
||||||
g.is_arraymap_set = false
|
g.is_arraymap_set = false
|
||||||
}
|
}
|
||||||
|
|||||||
41
vlib/v/tests/option_multi_ret_test.v
Normal file
41
vlib/v/tests/option_multi_ret_test.v
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
struct Test {
|
||||||
|
mut:
|
||||||
|
a ?int
|
||||||
|
b ?string
|
||||||
|
c ?[]int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mr_1() (?int, string, []int) {
|
||||||
|
return 456, 'foo', [1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mr_2() (?int, string, []int) {
|
||||||
|
return none, 'zoo', [99]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mr_3() ([]?int, ?int) {
|
||||||
|
return [?int(456)], none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mr_first_option() {
|
||||||
|
mut t := Test{}
|
||||||
|
t.a, t.b, t.c = mr_1()
|
||||||
|
assert t.a? == 456
|
||||||
|
assert t.b? == 'foo'
|
||||||
|
assert t.c? == [1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mr_first_option_none() {
|
||||||
|
mut t := Test{}
|
||||||
|
t.a, t.b, t.c = mr_2()
|
||||||
|
assert t.a == none
|
||||||
|
assert t.b? == 'zoo'
|
||||||
|
assert t.c? == [99]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mr_first_option_array() {
|
||||||
|
a, b := mr_3()
|
||||||
|
t := a[0]
|
||||||
|
assert t? == 456
|
||||||
|
assert b == none
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user