cgen: fix for_in fixed_array (#9129)

pull/9133/head
yuyi 2021-03-05 20:35:09 +08:00 committed by GitHub
parent 9ba312066e
commit cbbfb460a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 16 deletions

View File

@ -1414,37 +1414,52 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
} }
} }
} else if node.kind == .array_fixed { } else if node.kind == .array_fixed {
atmp := g.new_tmp_var() mut cond_var := ''
atmp_type := g.typ(node.cond_type).trim('*') needs_tmp_var := node.cond_type.is_ptr() || node.cond is ast.ArrayInit
if node.cond_type.is_ptr() || node.cond is ast.ArrayInit { if needs_tmp_var {
cond_var = g.new_tmp_var()
cond_var_type := g.typ(node.cond_type).trim('*')
if !node.cond.is_lvalue() { if !node.cond.is_lvalue() {
g.write('$atmp_type *$atmp = (($atmp_type)') g.write('$cond_var_type *$cond_var = (($cond_var_type)')
} else { } else {
g.write('$atmp_type *$atmp = (') g.write('$cond_var_type *$cond_var = (')
} }
g.expr(node.cond) g.expr(node.cond)
g.writeln(');') g.writeln(');')
} else {
pos := g.out.len
g.expr(node.cond)
cond_var = g.out.after(pos)
g.out.go_back(cond_var.len)
cond_var = cond_var.trim_space()
} }
i := if node.key_var in ['', '_'] { g.new_tmp_var() } else { node.key_var } idx := if node.key_var in ['', '_'] { g.new_tmp_var() } else { node.key_var }
cond_sym := g.table.get_type_symbol(node.cond_type) cond_sym := g.table.get_type_symbol(node.cond_type)
info := cond_sym.info as table.ArrayFixed info := cond_sym.info as table.ArrayFixed
g.writeln('for (int $i = 0; $i != $info.size; ++$i) {') g.writeln('for (int $idx = 0; $idx != $info.size; ++$idx) {')
if node.val_var != '_' { if node.val_var != '_' {
val_sym := g.table.get_type_symbol(node.val_type) val_sym := g.table.get_type_symbol(node.val_type)
is_fixed_array := val_sym.kind == .array_fixed && !node.val_is_mut
if val_sym.kind == .function { if val_sym.kind == .function {
g.write('\t') g.write('\t')
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(node.val_var)) g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(node.val_var))
} else if is_fixed_array {
styp := g.typ(node.val_type)
g.writeln('\t$styp ${c_name(node.val_var)};')
g.writeln('\tmemcpy(*($styp*)${c_name(node.val_var)}, (byte*)$cond_var[$idx], sizeof($styp));')
} else { } else {
styp := g.typ(node.val_type) styp := g.typ(node.val_type)
g.write('\t$styp ${c_name(node.val_var)}') g.write('\t$styp ${c_name(node.val_var)}')
} }
if !is_fixed_array {
addr := if node.val_is_mut { '&' } else { '' } addr := if node.val_is_mut { '&' } else { '' }
if node.cond_type.is_ptr() || node.cond is ast.ArrayInit { if needs_tmp_var {
g.writeln(' = ${addr}(*$atmp)[$i];') g.writeln(' = ${addr}(*$cond_var)[$idx];')
} else { } else {
g.write(' = $addr') g.write(' = $addr')
g.expr(node.cond) g.expr(node.cond)
g.writeln('[$i];') g.writeln('[$idx];')
}
} }
} }
} else if node.kind == .map { } else if node.kind == .map {

View File

@ -1,4 +1,4 @@
fn test_for_in_containers_of_fixed_array() { fn test_for_in_array_of_fixed_array() {
mut rets := []string{} mut rets := []string{}
arr := [][2]int{len: 3} arr := [][2]int{len: 3}
@ -11,7 +11,7 @@ fn test_for_in_containers_of_fixed_array() {
assert rets[2] == '[0, 0]' assert rets[2] == '[0, 0]'
} }
fn test_for_mut_in_containers_of_fixed_array() { fn test_for_mut_in_array_of_fixed_array() {
mut rets := []string{} mut rets := []string{}
mut arr := [][2]int{len: 3} mut arr := [][2]int{len: 3}
@ -23,3 +23,29 @@ fn test_for_mut_in_containers_of_fixed_array() {
assert rets[1] == '[0, 0]' assert rets[1] == '[0, 0]'
assert rets[2] == '[0, 0]' assert rets[2] == '[0, 0]'
} }
fn test_for_in_fixed_array_of_fixed_array() {
mut rets := []string{}
arr := [[1, 2]!, [3, 4]!, [5, 6]!]!
for pair in arr {
println(pair)
rets << '$pair'
}
assert rets[0] == '[1, 2]'
assert rets[1] == '[3, 4]'
assert rets[2] == '[5, 6]'
}
fn test_for_mut_in_fixed_array_of_fixed_array() {
mut rets := []string{}
mut arr := [[1, 2]!, [3, 4]!, [5, 6]!]!
for mut pair in arr {
println(pair)
rets << '$pair'
}
assert rets[0] == '[1, 2]'
assert rets[1] == '[3, 4]'
assert rets[2] == '[5, 6]'
}