mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: simplify fixed arr return (#18380)
This commit is contained in:
parent
1de6523da5
commit
7a25c03aa7
@ -2538,9 +2538,11 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
|
|||||||
tsym := c.table.sym(unwrapped_expr_type)
|
tsym := c.table.sym(unwrapped_expr_type)
|
||||||
if tsym.kind == .array_fixed {
|
if tsym.kind == .array_fixed {
|
||||||
info := tsym.info as ast.ArrayFixed
|
info := tsym.info as ast.ArrayFixed
|
||||||
// for dumping fixed array we must registed the fixed array struct to return from function
|
if !info.is_fn_ret {
|
||||||
c.table.find_or_register_array_fixed(info.elem_type, info.size, info.size_expr,
|
// for dumping fixed array we must register the fixed array struct to return from function
|
||||||
true)
|
c.table.find_or_register_array_fixed(info.elem_type, info.size, info.size_expr,
|
||||||
|
true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
type_cname := if node.expr_type.has_flag(.option) {
|
type_cname := if node.expr_type.has_flag(.option) {
|
||||||
'_option_${tsym.cname}'
|
'_option_${tsym.cname}'
|
||||||
|
@ -636,13 +636,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
} else if is_fixed_array_var {
|
} else if is_fixed_array_var {
|
||||||
// TODO Instead of the translated check, check if it's a pointer already
|
// TODO Instead of the translated check, check if it's a pointer already
|
||||||
// and don't generate memcpy &
|
// and don't generate memcpy &
|
||||||
right_is_fixed_ret := !(val is ast.CallExpr
|
|
||||||
&& (val as ast.CallExpr).or_block.kind == .propagate_option)
|
|
||||||
&& ((right_sym.info is ast.ArrayFixed
|
|
||||||
&& (right_sym.info as ast.ArrayFixed).is_fn_ret)
|
|
||||||
|| (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed)
|
|
||||||
|| (val is ast.CallExpr
|
|
||||||
&& g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed))
|
|
||||||
typ_str := g.typ(val_type).trim('*')
|
typ_str := g.typ(val_type).trim('*')
|
||||||
final_typ_str := if is_fixed_array_var { '' } else { '(${typ_str}*)' }
|
final_typ_str := if is_fixed_array_var { '' } else { '(${typ_str}*)' }
|
||||||
final_ref_str := if is_fixed_array_var {
|
final_ref_str := if is_fixed_array_var {
|
||||||
@ -661,9 +654,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
|||||||
g.expr(left)
|
g.expr(left)
|
||||||
g.write(', ${final_ref_str}')
|
g.write(', ${final_ref_str}')
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
if right_is_fixed_ret {
|
|
||||||
g.write('.ret_arr')
|
|
||||||
}
|
|
||||||
g.write(', sizeof(${typ_str})) /*assign*/')
|
g.write(', sizeof(${typ_str})) /*assign*/')
|
||||||
}
|
}
|
||||||
} else if is_decl {
|
} else if is_decl {
|
||||||
|
@ -649,15 +649,15 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
|
|||||||
is_elem_ptr := typ.is_ptr()
|
is_elem_ptr := typ.is_ptr()
|
||||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||||
elem_str_fn_name := g.get_str_fn(typ)
|
elem_str_fn_name := g.get_str_fn(typ)
|
||||||
|
def_arg := if info.is_fn_ret { '${g.typ(typ)} a[${info.size}]' } else { '${styp} a' }
|
||||||
|
|
||||||
g.definitions.writeln('static string ${str_fn_name}(${styp} a); // auto')
|
g.definitions.writeln('static string ${str_fn_name}(); // auto')
|
||||||
g.auto_str_funcs.writeln('static string ${str_fn_name}(${styp} a) { return indent_${str_fn_name}(a, 0);}')
|
g.auto_str_funcs.writeln('static string ${str_fn_name}(${def_arg}) { return indent_${str_fn_name}(a, 0);}')
|
||||||
g.definitions.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count); // auto')
|
g.definitions.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count); // auto')
|
||||||
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count) {')
|
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count) {')
|
||||||
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(${info.size} * 10);')
|
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(${info.size} * 10);')
|
||||||
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));')
|
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));')
|
||||||
g.auto_str_funcs.writeln('\tfor (int i = 0; i < ${info.size}; ++i) {')
|
g.auto_str_funcs.writeln('\tfor (int i = 0; i < ${info.size}; ++i) {')
|
||||||
suffix := if info.is_fn_ret { '.ret_arr' } else { '' }
|
|
||||||
if sym.kind == .function {
|
if sym.kind == .function {
|
||||||
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);')
|
||||||
@ -666,30 +666,30 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
|
|||||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
if is_elem_ptr {
|
if is_elem_ptr {
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("${deref_label}"));')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("${deref_label}"));')
|
||||||
g.auto_str_funcs.writeln('\t\tif ( 0 == a${suffix}[i] ) {')
|
g.auto_str_funcs.writeln('\t\tif ( 0 == a[i] ) {')
|
||||||
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, _SLIT("0"));')
|
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, _SLIT("0"));')
|
||||||
g.auto_str_funcs.writeln('\t\t}else{')
|
g.auto_str_funcs.writeln('\t\t}else{')
|
||||||
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
|
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
|
||||||
g.auto_str_funcs.writeln('\t\t}')
|
g.auto_str_funcs.writeln('\t\t}')
|
||||||
} else {
|
} else {
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
|
||||||
}
|
}
|
||||||
} else if sym.kind in [.f32, .f64] {
|
} else if sym.kind in [.f32, .f64] {
|
||||||
if sym.kind == .f32 {
|
if sym.kind == .f32 {
|
||||||
field_str := str_intp_g32('a${suffix}[i]')
|
field_str := str_intp_g32('a[i]')
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
|
||||||
} else {
|
} else {
|
||||||
field_str := str_intp_g64('a${suffix}[i]')
|
field_str := str_intp_g64('a[i]')
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
|
||||||
}
|
}
|
||||||
} else if sym.kind == .string {
|
} else if sym.kind == .string {
|
||||||
field_str := str_intp_sq('a${suffix}[i]')
|
field_str := str_intp_sq('a[i]')
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str});')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str});')
|
||||||
} else if sym.kind == .rune {
|
} else if sym.kind == .rune {
|
||||||
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a${suffix}[i])')
|
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a[i])')
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});')
|
||||||
} else {
|
} else {
|
||||||
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]));')
|
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]));')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {')
|
g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {')
|
||||||
|
@ -138,6 +138,7 @@ mut:
|
|||||||
inside_or_block bool
|
inside_or_block bool
|
||||||
inside_call bool
|
inside_call bool
|
||||||
inside_curry_call bool // inside foo()()!, foo()()?, foo()()
|
inside_curry_call bool // inside foo()()!, foo()()?, foo()()
|
||||||
|
expected_fixed_arr bool
|
||||||
inside_for_c_stmt bool
|
inside_for_c_stmt bool
|
||||||
inside_comptime_for_field bool
|
inside_comptime_for_field bool
|
||||||
inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls)
|
inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls)
|
||||||
@ -2452,11 +2453,6 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||||||
}
|
}
|
||||||
// no cast
|
// no cast
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if expr is ast.CallExpr && !(expr as ast.CallExpr).is_fn_var && !expected_type.has_flag(.option)
|
|
||||||
&& exp_sym.kind == .array_fixed {
|
|
||||||
// it's non-option fixed array, requires accessing .ret_arr member to get the array
|
|
||||||
g.write('.ret_arr')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_octal_escape(mut b strings.Builder, c u8) {
|
fn write_octal_escape(mut b strings.Builder, c u8) {
|
||||||
@ -4989,12 +4985,16 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
|||||||
g.writeln('{0};')
|
g.writeln('{0};')
|
||||||
if node.exprs[0] is ast.Ident {
|
if node.exprs[0] is ast.Ident {
|
||||||
g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}, sizeof(${g.typ(node.types[0])})) /*ret*/')
|
g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}, sizeof(${g.typ(node.types[0])})) /*ret*/')
|
||||||
} else {
|
} else if node.exprs[0] is ast.ArrayInit {
|
||||||
tmpvar2 := g.new_tmp_var()
|
tmpvar2 := g.new_tmp_var()
|
||||||
g.write('${g.typ(node.types[0])} ${tmpvar2} = ')
|
g.write('${g.typ(node.types[0])} ${tmpvar2} = ')
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.typ(node.types[0])})) /*ret*/')
|
g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.typ(node.types[0])})) /*ret*/')
|
||||||
|
} else {
|
||||||
|
g.write('memcpy(${tmpvar}.ret_arr, ')
|
||||||
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
|
g.write(', sizeof(${g.typ(node.types[0])})) /*ret*/')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
|
@ -67,6 +67,10 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
|
|||||||
g.inside_opt_or_res = old_inside_opt_or_res
|
g.inside_opt_or_res = old_inside_opt_or_res
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_flag(.option)
|
||||||
|
&& g.table.type_kind(expr_type) == .array_fixed {
|
||||||
|
g.write('.ret_arr')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) dump_expr_definitions() {
|
fn (mut g Gen) dump_expr_definitions() {
|
||||||
@ -106,8 +110,13 @@ fn (mut g Gen) dump_expr_definitions() {
|
|||||||
dump_typedefs['typedef ${str_tdef};'] = true
|
dump_typedefs['typedef ${str_tdef};'] = true
|
||||||
str_dumparg_ret_type = str_dumparg_type
|
str_dumparg_ret_type = str_dumparg_type
|
||||||
} else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
|
} else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
|
||||||
// fixed array returned from function
|
if (dump_sym.info as ast.ArrayFixed).is_fn_ret {
|
||||||
str_dumparg_ret_type = '_v_' + str_dumparg_type
|
str_dumparg_ret_type = str_dumparg_type
|
||||||
|
str_dumparg_type = str_dumparg_type.trim_string_left('_v_')
|
||||||
|
} else {
|
||||||
|
// fixed array returned from function
|
||||||
|
str_dumparg_ret_type = '_v_' + str_dumparg_type
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
str_dumparg_ret_type = str_dumparg_type
|
str_dumparg_ret_type = str_dumparg_type
|
||||||
}
|
}
|
||||||
|
@ -1474,6 +1474,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||||||
g.write(', ${array_depth}')
|
g.write(', ${array_depth}')
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
if node.return_type != 0 && !node.return_type.has_flag(.option)
|
||||||
|
&& g.table.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')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) fn_call(node ast.CallExpr) {
|
fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
@ -1776,6 +1781,11 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||||||
if name != '&' {
|
if name != '&' {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
if node.return_type != 0 && !node.return_type.has_flag(.option)
|
||||||
|
&& g.table.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')
|
||||||
|
}
|
||||||
if tmp_cnt_save >= 0 {
|
if tmp_cnt_save >= 0 {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
g.keep_alive_call_postgen(node, tmp_cnt_save)
|
g.keep_alive_call_postgen(node, tmp_cnt_save)
|
||||||
@ -1916,6 +1926,10 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) call_args(node ast.CallExpr) {
|
fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||||
|
g.expected_fixed_arr = true
|
||||||
|
defer {
|
||||||
|
g.expected_fixed_arr = false
|
||||||
|
}
|
||||||
args := if g.is_js_call {
|
args := if g.is_js_call {
|
||||||
if node.args.len < 1 {
|
if node.args.len < 1 {
|
||||||
g.error('node should have at least 1 arg', node.pos)
|
g.error('node should have at least 1 arg', node.pos)
|
||||||
|
@ -368,10 +368,6 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
|
|||||||
} else {
|
} else {
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
}
|
}
|
||||||
if node.left is ast.CallExpr && sym.kind == .array_fixed
|
|
||||||
&& (sym.info as ast.ArrayFixed).is_fn_ret {
|
|
||||||
g.write('.ret_arr')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g.write('[')
|
g.write('[')
|
||||||
if g.is_direct_array_access || g.pref.translated || node.index is ast.IntegerLiteral {
|
if g.is_direct_array_access || g.pref.translated || node.index is ast.IntegerLiteral {
|
||||||
|
@ -8,6 +8,10 @@ import v.token
|
|||||||
import v.util
|
import v.util
|
||||||
|
|
||||||
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
|
g.expected_fixed_arr = true
|
||||||
|
defer {
|
||||||
|
g.expected_fixed_arr = false
|
||||||
|
}
|
||||||
if node.auto_locked != '' {
|
if node.auto_locked != '' {
|
||||||
g.writeln('sync__RwMutex_lock(&${node.auto_locked}->mtx);')
|
g.writeln('sync__RwMutex_lock(&${node.auto_locked}->mtx);')
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,10 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
|
|||||||
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
|
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
|
||||||
old_inside_opt_or_res := g.inside_opt_or_res
|
old_inside_opt_or_res := g.inside_opt_or_res
|
||||||
g.inside_opt_or_res = true
|
g.inside_opt_or_res = true
|
||||||
|
g.expected_fixed_arr = true
|
||||||
defer {
|
defer {
|
||||||
g.inside_opt_or_res = old_inside_opt_or_res
|
g.inside_opt_or_res = old_inside_opt_or_res
|
||||||
|
g.expected_fixed_arr = false
|
||||||
}
|
}
|
||||||
is_shared := etype.has_flag(.shared_f)
|
is_shared := etype.has_flag(.shared_f)
|
||||||
mut typ := etype
|
mut typ := etype
|
||||||
|
52
vlib/v/tests/fixed_array_2_test.v
Normal file
52
vlib/v/tests/fixed_array_2_test.v
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
struct Test {}
|
||||||
|
|
||||||
|
fn (t Test) conversion_error(value u16) [4]u8 {
|
||||||
|
return conversion_error(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arr_opt() ?[2]int {
|
||||||
|
return [1, 2]!
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conversion_error(value u16) [4]u8 {
|
||||||
|
mut return_value := [4]u8{}
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
return_value[i] = u8(value)
|
||||||
|
}
|
||||||
|
return return_value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_assign() {
|
||||||
|
// -- Block below works fine
|
||||||
|
value := conversion_error(42)
|
||||||
|
println(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_assign_method() {
|
||||||
|
value2 := Test{}.conversion_error(42)
|
||||||
|
println(value2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_ret() {
|
||||||
|
// -- Block above works fine
|
||||||
|
println(conversion_error(42))
|
||||||
|
println(Test{}.conversion_error(42))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_assign_dump() {
|
||||||
|
y := dump(conversion_error(42))
|
||||||
|
dump(y)
|
||||||
|
y2 := dump(Test{}.conversion_error(42))
|
||||||
|
dump(y2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_assert() {
|
||||||
|
a := [1, 2]!
|
||||||
|
assert dump(a) == [1, 2]!
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_call() {
|
||||||
|
conversion_error(42)
|
||||||
|
Test{}.conversion_error(42)
|
||||||
|
dump(arr_opt())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user