From 1c9950c84a238b415b27d147cdeef6283df28542 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 25 Jan 2021 20:40:53 +0800 Subject: [PATCH] cgen: fix map_complex_high_order_fixed_array (#8329) --- vlib/v/gen/cgen.v | 83 +++++++-------------- vlib/v/tests/map_complex_fixed_array_test.v | 9 +++ 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 8ba1d5fe3f..92002bb076 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -61,10 +61,11 @@ mut: is_assign_lhs bool // inside left part of assign expr (for array_set(), etc) is_assign_rhs bool // inside right part of assign after `=` (val expr) is_array_set bool - is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc - is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc) - is_shared bool // for initialization of hidden mutex in `[rw]shared` literals - is_vlines_enabled bool // is it safe to generate #line directives when -g is passed + is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc + is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc) + is_shared bool // for initialization of hidden mutex in `[rw]shared` literals + is_vlines_enabled bool // is it safe to generate #line directives when -g is passed + array_set_pos int vlines_path string // set to the proper path for generating #line directives optionals []string // to avoid duplicates TODO perf, use map chan_pop_optionals []string // types for `x := <-ch or {...}` @@ -1976,57 +1977,28 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } } else if is_fixed_array_init && assign_stmt.op == .assign { right := val as ast.ArrayInit - if right.has_val { - for j, expr in right.exprs { - if !is_decl && left is ast.Ident - && g.for_in_mul_val_name == (left as ast.Ident).name { - g.write('(*') - g.expr(left) - g.write(')') - } else { - g.expr(left) - } - if g.is_array_set { - g.out.go_back(2) - } else { - g.write('[$j] = ') - } - g.expr(expr) - if g.is_array_set { - g.writeln(')') - g.is_array_set = false - } else { - g.writeln(';') - } - } + v_var := g.new_tmp_var() + arr_typ := styp.trim('*') + g.write('$arr_typ $v_var = ') + g.expr(right) + g.writeln(';') + pos := g.out.len + g.expr(left) + + if g.is_array_set && g.array_set_pos > 0 { + g.out.go_back_to(g.array_set_pos) + g.write(', &$v_var)') + g.is_array_set = false + g.array_set_pos = 0 } else { - fixed_array := right_sym.info as table.ArrayFixed - for j in 0 .. fixed_array.size { - if !is_decl && left is ast.Ident - && g.for_in_mul_val_name == (left as ast.Ident).name { - g.write('(*') - g.expr(left) - g.write(')') - } else { - g.expr(left) - } - if g.is_array_set { - g.out.go_back(2) - } else { - g.write('[$j] = ') - } - if right.has_default { - g.expr(right.default_expr) - } else { - g.write(g.type_default(right.elem_type)) - } - if g.is_array_set { - g.writeln(')') - g.is_array_set = false - } else { - g.writeln(';') - } - } + g.out.go_back_to(pos) + is_var_mut := !is_decl && left is ast.Ident + && g.for_in_mul_val_name == (left as ast.Ident).name + addr := if is_var_mut { '' } else { '&' } + g.writeln('') + g.write('memcpy($addr') + g.expr(left) + g.writeln(', &$v_var, sizeof($arr_typ));') } g.is_assign_lhs = false } else { @@ -2142,7 +2114,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { if is_fixed_array_copy { i_var := g.new_tmp_var() fixed_array := right_sym.info as table.ArrayFixed - g.write('for(int $i_var=0; $i_var<$fixed_array.size; $i_var++) {') + g.write('for (int $i_var=0; $i_var<$fixed_array.size; $i_var++) {') g.expr(left) g.write('[$i_var] = ') g.expr(val) @@ -4271,6 +4243,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { if elem_typ.kind == .function { g.write(', &(voidptr[]) { ') } else { + g.array_set_pos = g.out.len g.write(', &($elem_type_str[]) { ') } if g.assign_op != .assign && info.value_type != table.string_type { diff --git a/vlib/v/tests/map_complex_fixed_array_test.v b/vlib/v/tests/map_complex_fixed_array_test.v index 8afceb4954..68db45af84 100644 --- a/vlib/v/tests/map_complex_fixed_array_test.v +++ b/vlib/v/tests/map_complex_fixed_array_test.v @@ -17,3 +17,12 @@ fn test_innermost_value_of_map_fixed_array() { assert m['foo'][0][0]['bar'] == 1 assert '${m['foo'][0][0]['bar']}' == '1' } + +fn test_complex_map_high_order_fixed_array() { + mut m := {'foo': [[{'a': 1}]!]!, 'bar': [[{'b': 2}]!]!} + for _, mut j in m { + j = [[{'c': 3}]!]! + } + println(m) + assert '$m' == "{'foo': [[{'c': 3}]], 'bar': [[{'c': 3}]]}" +}