Skip to content

Commit

Permalink
cgen: fix all the cases of struct field init with optional fixed array
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Dec 19, 2024
1 parent bc90058 commit 1c6b527
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 51 deletions.
3 changes: 2 additions & 1 deletion vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -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})')
}
Expand Down
12 changes: 0 additions & 12 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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}));')
}
Expand Down
31 changes: 6 additions & 25 deletions vlib/v/gen/c/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
66 changes: 53 additions & 13 deletions vlib/v/tests/structs/struct_field_init_with_fixed_array_opt_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -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]!
}

0 comments on commit 1c6b527

Please sign in to comment.