From 1c6b527b0d49659e5b09032868dce9d836e9ee2b Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 19 Dec 2024 17:25:32 +0800 Subject: [PATCH] cgen: fix all the cases of struct field init with optional fixed array --- vlib/v/gen/c/array.v | 3 +- vlib/v/gen/c/assign.v | 12 ---- vlib/v/gen/c/cgen.v | 7 ++ vlib/v/gen/c/struct.v | 31 ++------- ...uct_field_init_with_fixed_array_opt_test.v | 66 +++++++++++++++---- 5 files changed, 68 insertions(+), 51 deletions(-) diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index f0c91673aca5e4..3bb1c362903aed 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -127,7 +127,8 @@ fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type, var_name st } is_none := node.is_option && !node.has_init && !node.has_val - if (g.inside_struct_init && g.inside_cast && !g.inside_memset) || (node.is_option && !is_none) { + if (g.inside_struct_init && g.inside_cast && !g.inside_memset && !g.inside_opt_or_res) + || (node.is_option && !is_none) { ret_typ_str := g.styp(node.typ) g.write('(${ret_typ_str})') } diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index cb055344df7fa3..1204a4ae7bfa10 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -157,18 +157,6 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type) return '' } -fn (mut g Gen) expr_with_fixed_array_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type) { - tmp_var := g.new_tmp_var() - stmt_str := g.go_before_last_stmt().trim_space() - styp := g.styp(expr_typ) - g.empty_line = true - g.writeln('${styp} ${tmp_var} = {.state = 0};') - g.write('memcpy(${tmp_var}.data, ') - g.expr(expr) - g.writeln(', sizeof(${g.styp(ret_typ)}));') - g.write2(stmt_str, tmp_var) -} - fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { mut node := unsafe { node_ } if node.is_static { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 2809b06530dca9..9fd80c4ba032f4 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2205,6 +2205,7 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T } else { g.writeln('${g.styp(ret_typ)} ${tmp_var};') } + mut expr_is_fixed_array_var := false if ret_typ_is_option { if expr_typ_is_option && expr in [ast.StructInit, ast.ArrayInit, ast.MapInit] { simple_assign = expr is ast.StructInit @@ -2226,6 +2227,10 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T && expr.right is ast.StructInit && (expr.right as ast.StructInit).init_fields.len == 0 { g.write('_option_none(&(${styp}[]) { ') + } else if expr in [ast.Ident, ast.SelectorExpr] + && final_expr_sym.kind == .array_fixed { + expr_is_fixed_array_var = true + g.write('_option_ok(&') } else { g.write('_option_ok(&(${styp}[]) { ') if final_expr_sym.info is ast.FnType { @@ -2248,6 +2253,8 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T if ret_typ_is_option { if simple_assign { g.writeln(';') + } else if expr_is_fixed_array_var { + g.writeln(', (${option_name}*)(&${tmp_var}), sizeof(${styp}));') } else { g.writeln(' }, (${option_name}*)(&${tmp_var}), sizeof(${styp}));') } diff --git a/vlib/v/gen/c/struct.v b/vlib/v/gen/c/struct.v index 86b905b83bc334..2103ba4fb1e1b3 100644 --- a/vlib/v/gen/c/struct.v +++ b/vlib/v/gen/c/struct.v @@ -685,35 +685,16 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua field_unwrap_typ := g.unwrap_generic(sfield.typ) field_unwrap_sym := g.table.final_sym(field_unwrap_typ) is_auto_deref_var := sfield.expr.is_auto_deref_var() - if field_unwrap_sym.info is ast.ArrayFixed { + if field_unwrap_sym.info is ast.ArrayFixed && !sfield.expected_type.has_flag(.option) { match sfield.expr { ast.Ident, ast.SelectorExpr { - if sfield.expected_type.has_flag(.option) { - if field_unwrap_typ.has_flag(.option) { - g.expr_with_opt(sfield.expr, sfield.expected_type, field_unwrap_typ) - } else { - g.expr_with_fixed_array_opt(sfield.expr, sfield.expected_type, - field_unwrap_typ) - } - } else { - g.fixed_array_var_init(g.expr_string(sfield.expr), is_auto_deref_var, - field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size) - } + g.fixed_array_var_init(g.expr_string(sfield.expr), is_auto_deref_var, + field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size) } ast.CastExpr, ast.CallExpr { - if sfield.expected_type.has_flag(.option) { - if field_unwrap_typ.has_flag(.option) { - g.expr_with_opt(sfield.expr, sfield.expected_type, field_unwrap_typ) - } else { - g.expr_with_fixed_array_opt(sfield.expr, sfield.expected_type, - field_unwrap_typ) - } - } else { - tmp_var := g.expr_with_var(sfield.expr, sfield.expected_type, - false) - g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type, - field_unwrap_sym.info.size) - } + tmp_var := g.expr_with_var(sfield.expr, sfield.expected_type, false) + g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type, + field_unwrap_sym.info.size) } ast.ArrayInit { if sfield.expr.has_index { diff --git a/vlib/v/tests/structs/struct_field_init_with_fixed_array_opt_test.v b/vlib/v/tests/structs/struct_field_init_with_fixed_array_opt_test.v index f07c2166da9efb..76e42f26ac49e9 100644 --- a/vlib/v/tests/structs/struct_field_init_with_fixed_array_opt_test.v +++ b/vlib/v/tests/structs/struct_field_init_with_fixed_array_opt_test.v @@ -6,27 +6,67 @@ struct Foo { } fn test_struct_field_init_with_fixed_array_opt() { - f1 := Foo{ + foo1 := Foo{ bar: 1 baz: Arr([u8(5), 4, 3, 2]!) } - println(f1) - assert f1.baz as Arr == [u8(5), 4, 3, 2]! + println(foo1) + assert foo1.baz as Arr == [u8(5), 4, 3, 2]! - f2 := Foo{ + foo11 := Foo{ + bar: 1 + baz: ?Arr([u8(5), 4, 3, 2]!) + } + println(foo11) + assert foo11.baz as Arr == [u8(5), 4, 3, 2]! + + foo12 := Foo{ + bar: 1 + baz: [u8(5), 4, 3, 2]! + } + println(foo12) + assert foo12.baz as Arr == [u8(5), 4, 3, 2]! + + foo2 := Foo{ bar: 1 baz: ?Arr(none) } - println(f2) - assert f2.bar == 1 - assert f2.baz == none + println(foo2) + assert foo2.bar == 1 + assert foo2.baz == none + + foo21 := Foo{ + bar: 1 + baz: none + } + println(foo21) + assert foo21.bar == 1 + assert foo21.baz == none + + arr1 := Arr([u8(5), 4, 3, 2]!) + foo3 := Foo{ + bar: 1 + baz: arr1 + } + println(foo3) + assert foo3.bar == 1 + assert foo3.baz as Arr == [u8(5), 4, 3, 2]! + + arr2 := ?Arr([u8(5), 4, 3, 2]!) + foo31 := Foo{ + bar: 1 + baz: arr2 + } + println(foo31) + assert foo31.bar == 1 + assert foo31.baz as Arr == [u8(5), 4, 3, 2]! - arr := Arr([u8(5), 4, 3, 2]!) - f3 := Foo{ + arr3 := [u8(5), 4, 3, 2]! + foo32 := Foo{ bar: 1 - baz: arr + baz: arr3 } - println(f3) - assert f3.bar == 1 - assert f3.baz as Arr == [u8(5), 4, 3, 2]! + println(foo32) + assert foo32.bar == 1 + assert foo32.baz as Arr == [u8(5), 4, 3, 2]! }