cgen: fix fixed array handling, on generic result return, and on or block (#20492)

This commit is contained in:
Felipe Pena 2024-01-11 22:31:01 -03:00 committed by GitHub
parent 554f21a29c
commit 0c4611fa4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 14 deletions

View File

@ -4965,7 +4965,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
fn_return_is_multi := sym.kind == .multi_return
fn_return_is_option := fn_ret_type.has_flag(.option)
fn_return_is_result := fn_ret_type.has_flag(.result)
fn_return_is_fixed_array := sym.is_array_fixed() && !fn_ret_type.has_flag(.option)
fn_return_is_fixed_array := sym.is_array_fixed() && !fn_ret_type.has_option_or_result()
mut has_semicolon := false
if node.exprs.len == 0 {
@ -5306,7 +5306,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
if g.fn_decl.return_type.has_flag(.option) {
g.expr_with_opt(node.exprs[0], node.types[0], g.fn_decl.return_type)
} else {
if fn_return_is_fixed_array && !node.types[0].has_flag(.option) {
if fn_return_is_fixed_array && !node.types[0].has_option_or_result() {
g.writeln('{0};')
if node.exprs[0] is ast.Ident {
typ := if expr0.is_auto_deref_var() {
@ -6394,15 +6394,27 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
g.writeln(';')
g.stmt_path_pos.delete_last()
} else {
mut is_array_fixed := false
if is_option {
is_array_fixed = expr_stmt.expr is ast.ArrayInit
&& g.table.final_sym(return_type).kind == .array_fixed
if !is_array_fixed {
g.write('*(${cast_typ}*) ${cvar_name}.data = ')
}
} else {
g.write('${cvar_name} = ')
}
if is_array_fixed {
g.write('memcpy(${cvar_name}.data, (${cast_typ})')
}
old_inside_opt_data := g.inside_opt_data
g.inside_opt_data = true
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_option_and_result())
g.inside_opt_data = old_inside_opt_data
if is_array_fixed {
g.write(', sizeof(${cast_typ}))')
}
g.writeln(';')
g.stmt_path_pos.delete_last()
}

View File

@ -76,8 +76,8 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
g.inside_opt_or_res = old_inside_opt_or_res
}
g.write(')')
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_flag(.option)
&& g.table.type_kind(expr_type) == .array_fixed {
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_option_or_result()
&& g.table.final_sym(expr_type).kind == .array_fixed {
g.write('.ret_arr')
}
}
@ -121,7 +121,7 @@ fn (mut g Gen) dump_expr_definitions() {
g.go_back(str_tdef.len)
dump_typedefs['typedef ${str_tdef};'] = true
str_dumparg_ret_type = str_dumparg_type
} else if !typ.has_flag(.option) && dump_sym.is_array_fixed() {
} else if !typ.has_option_or_result() && dump_sym.is_array_fixed() {
match dump_sym.kind {
.array_fixed {
if (dump_sym.info as ast.ArrayFixed).is_fn_ret {

View File

@ -228,10 +228,10 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
mut type_name := g.typ(g.unwrap_generic(node.return_type))
ret_sym := g.table.sym(g.unwrap_generic(node.return_type))
if node.return_type.has_flag(.generic) && !node.return_type.has_flag(.option)
if node.return_type.has_flag(.generic) && !node.return_type.has_option_or_result()
&& ret_sym.kind == .array_fixed {
type_name = '_v_${type_name}'
} else if ret_sym.kind == .alias && !node.return_type.has_flag(.option) {
} else if ret_sym.kind == .alias && !node.return_type.has_option_or_result() {
unalias_typ := g.table.unaliased_type(node.return_type)
unalias_sym := g.table.sym(unalias_typ)
if unalias_sym.kind == .array_fixed {
@ -1606,8 +1606,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.write(', ${array_depth}')
}
g.write(')')
if node.return_type != 0 && !node.return_type.has_flag(.option)
&& !node.return_type.has_flag(.result)
if node.return_type != 0 && !node.return_type.has_option_or_result()
&& g.table.final_sym(node.return_type).kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')
@ -1946,8 +1945,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
if name != '&' {
g.write(')')
}
if node.return_type != 0 && !node.return_type.has_flag(.option)
&& !node.return_type.has_flag(.result)
if node.return_type != 0 && !node.return_type.has_option_or_result()
&& g.table.final_sym(node.return_type).kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')

View File

@ -808,7 +808,7 @@ fn (mut g Gen) infix_expr_arithmetic_op(node ast.InfixExpr) {
}
g.write(')')
if left.typ != 0 && !left.typ.has_flag(.option) && !left.typ.has_flag(.result)
if left.typ != 0 && !left.typ.has_option_or_result()
&& g.table.final_sym(left.typ).kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')

View File

@ -2,9 +2,20 @@ fn example[T]() ?T {
return T{}
}
fn test_main() {
fn test_option() {
dump(example[[1]int]())
a := example[[1]int]()
assert a? == [0]!
}
fn example2[T]() !T {
return T{}
}
fn test_result() {
dump(example2[[1]int]()!)
a := example2[[1]int]()!
assert a == [0]!
}

View File

@ -0,0 +1,43 @@
type Abc = [2]int
// option
fn a() ?Abc {
return [1, 2]!
}
fn b() ?Abc {
return none
}
// result
fn aa() !Abc {
return [1, 2]!
}
fn bb() !Abc {
return error('b')
}
fn test_option() {
var_a := dump(a()?)
var_b := Abc([1, 2]!)
assert var_a == var_b
}
fn test_result() {
var_aa := dump(aa()!)
var_bb := Abc([1, 2]!)
assert var_aa == var_bb
}
fn test_opt_block() {
var_a := b() or { [0, 0]! }
dump(var_a)
assert var_a == Abc([0, 0]!)
}
fn test_res_block() {
var_a := bb() or { [0, 0]! }
dump(var_a)
assert var_a == Abc([0, 0]!)
}