cgen: fix map_complex_high_order_fixed_array (#8329)

pull/8338/head
yuyi 2021-01-25 20:40:53 +08:00 committed by GitHub
parent 965ae9cb91
commit 1c9950c84a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 55 deletions

View File

@ -61,10 +61,11 @@ mut:
is_assign_lhs bool // inside left part of assign expr (for array_set(), etc) 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_assign_rhs bool // inside right part of assign after `=` (val expr)
is_array_set bool is_array_set bool
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc 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_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_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_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 vlines_path string // set to the proper path for generating #line directives
optionals []string // to avoid duplicates TODO perf, use map optionals []string // to avoid duplicates TODO perf, use map
chan_pop_optionals []string // types for `x := <-ch or {...}` 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 { } else if is_fixed_array_init && assign_stmt.op == .assign {
right := val as ast.ArrayInit right := val as ast.ArrayInit
if right.has_val { v_var := g.new_tmp_var()
for j, expr in right.exprs { arr_typ := styp.trim('*')
if !is_decl && left is ast.Ident g.write('$arr_typ $v_var = ')
&& g.for_in_mul_val_name == (left as ast.Ident).name { g.expr(right)
g.write('(*') g.writeln(';')
g.expr(left) pos := g.out.len
g.write(')') g.expr(left)
} else {
g.expr(left) if g.is_array_set && g.array_set_pos > 0 {
} g.out.go_back_to(g.array_set_pos)
if g.is_array_set { g.write(', &$v_var)')
g.out.go_back(2) g.is_array_set = false
} else { g.array_set_pos = 0
g.write('[$j] = ')
}
g.expr(expr)
if g.is_array_set {
g.writeln(')')
g.is_array_set = false
} else {
g.writeln(';')
}
}
} else { } else {
fixed_array := right_sym.info as table.ArrayFixed g.out.go_back_to(pos)
for j in 0 .. fixed_array.size { is_var_mut := !is_decl && left is ast.Ident
if !is_decl && left is ast.Ident && g.for_in_mul_val_name == (left as ast.Ident).name
&& g.for_in_mul_val_name == (left as ast.Ident).name { addr := if is_var_mut { '' } else { '&' }
g.write('(*') g.writeln('')
g.expr(left) g.write('memcpy($addr')
g.write(')') g.expr(left)
} else { g.writeln(', &$v_var, sizeof($arr_typ));')
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.is_assign_lhs = false g.is_assign_lhs = false
} else { } else {
@ -2142,7 +2114,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if is_fixed_array_copy { if is_fixed_array_copy {
i_var := g.new_tmp_var() i_var := g.new_tmp_var()
fixed_array := right_sym.info as table.ArrayFixed 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.expr(left)
g.write('[$i_var] = ') g.write('[$i_var] = ')
g.expr(val) g.expr(val)
@ -4271,6 +4243,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
if elem_typ.kind == .function { if elem_typ.kind == .function {
g.write(', &(voidptr[]) { ') g.write(', &(voidptr[]) { ')
} else { } else {
g.array_set_pos = g.out.len
g.write(', &($elem_type_str[]) { ') g.write(', &($elem_type_str[]) { ')
} }
if g.assign_op != .assign && info.value_type != table.string_type { if g.assign_op != .assign && info.value_type != table.string_type {

View File

@ -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
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}]]}"
}