From 01096bcafb90f307a82421bda08a6420c0235e76 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 11 Feb 2025 12:37:42 -0300 Subject: [PATCH] cgen: fix codegen for array fixed on if and match expr (fix #23577, fix #23589) (#23682) --- vlib/v/gen/c/assign.v | 13 +++++++++++- vlib/v/gen/c/cgen.v | 17 ++++++++++++++- vlib/v/gen/c/if.v | 3 +++ vlib/v/gen/c/match.v | 3 +++ vlib/v/tests/array_fixed_ternary_test.v | 28 +++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/array_fixed_ternary_test.v diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index c670928cb0a3be..602bd24df6ba5e 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -526,7 +526,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } else { g.write('{${styp} _ = ') } - g.expr(val) + if val in [ast.MatchExpr, ast.IfExpr] && unaliased_right_sym.info is ast.ArrayFixed { + tmp_var := g.expr_with_var(val, var_type, false) + g.fixed_array_var_init(tmp_var, false, unaliased_right_sym.info.elem_type, + unaliased_right_sym.info.size) + } else { + g.expr(val) + } g.writeln(';}') } } else if node.op == .assign && !g.pref.translated && (is_fixed_array_init @@ -911,6 +917,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { g.array_init(val, c_name(ident.name)) } else if val_type.has_flag(.shared_f) { g.expr_with_cast(val, val_type, var_type) + } else if val in [ast.MatchExpr, ast.IfExpr] + && unaliased_right_sym.info is ast.ArrayFixed { + tmp_var := g.expr_with_var(val, var_type, false) + g.fixed_array_var_init(tmp_var, false, unaliased_right_sym.info.elem_type, + unaliased_right_sym.info.size) } else { g.expr(val) } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index a19e7da8daa378..f12be502cef295 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2114,6 +2114,9 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool { g.stmt(stmt) } } else { + mut is_array_fixed_init := false + mut ret_type := ast.void_type + g.set_current_pos_as_last_stmt_pos() g.skip_stmt_pos = true mut is_noreturn := false @@ -2121,11 +2124,23 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool { is_noreturn = true } else if stmt is ast.ExprStmt { is_noreturn = is_noreturn_callexpr(stmt.expr) + if stmt.expr is ast.ArrayInit && stmt.expr.is_fixed { + is_array_fixed_init = true + ret_type = stmt.expr.typ + } } if !is_noreturn { - g.write('${tmp_var} = ') + if is_array_fixed_init { + g.write('memcpy(${tmp_var}, (${g.styp(ret_type)})') + } else { + g.write('${tmp_var} = ') + } } g.stmt(stmt) + if is_array_fixed_init { + lines := g.go_before_last_stmt().trim_right('; \n') + g.writeln('${lines}, sizeof(${tmp_var}));') + } if !g.out.last_n(2).contains(';') { g.writeln(';') } diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index d19389ade4b837..f9fa855d7c9d00 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -20,6 +20,9 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool { if branch.stmts.len == 1 { if branch.stmts[0] is ast.ExprStmt { stmt := branch.stmts[0] as ast.ExprStmt + if stmt.expr is ast.ArrayInit && stmt.expr.is_fixed { + return true + } if g.need_tmp_var_in_expr(stmt.expr) { return true } diff --git a/vlib/v/gen/c/match.v b/vlib/v/gen/c/match.v index babaaccb600dd7..920778460ae677 100644 --- a/vlib/v/gen/c/match.v +++ b/vlib/v/gen/c/match.v @@ -25,6 +25,9 @@ fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool { if branch.stmts.len == 1 { if branch.stmts[0] is ast.ExprStmt { stmt := branch.stmts[0] as ast.ExprStmt + if stmt.expr is ast.ArrayInit && stmt.expr.is_fixed { + return true + } if g.need_tmp_var_in_expr(stmt.expr) { return true } diff --git a/vlib/v/tests/array_fixed_ternary_test.v b/vlib/v/tests/array_fixed_ternary_test.v new file mode 100644 index 00000000000000..0f327eae416965 --- /dev/null +++ b/vlib/v/tests/array_fixed_ternary_test.v @@ -0,0 +1,28 @@ +fn test_main() { + _ := if true { [0]! } else { [1]! } + _ := if true { [0] } else { [1] } + + a := if true { [0]! } else { [1]! } + b := if true { [0] } else { [1] } + assert a.str() == '[0]' + assert b.str() == '[0]' +} + +fn test_match() { + grid_size := 1 + + _ := match grid_size { + 3 { ['Small', '3x3']! } + 4 { ['Classic', '4x4']! } + 5 { ['Big', '5x5']! } + else { ['Large', '6x6']! } + } + + w := match grid_size { + 3 { ['Small', '3x3']! } + 4 { ['Classic', '4x4']! } + 5 { ['Big', '5x5']! } + else { ['Large', '6x6']! } + } + assert w.str() == "['Large', '6x6']" +}