gen: more efficient `for in` with a map (#6961)
parent
5e59718970
commit
ea8adfdbf9
|
@ -1173,33 +1173,34 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
|
|||
} else if it.kind == .map {
|
||||
// `for key, val in map {`
|
||||
g.writeln('// FOR IN map')
|
||||
key_styp := g.typ(it.key_type)
|
||||
val_styp := g.typ(it.val_type)
|
||||
val_sym := g.table.get_type_symbol(it.val_type)
|
||||
keys_tmp := 'keys_' + g.new_tmp_var()
|
||||
idx := g.new_tmp_var()
|
||||
key := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
|
||||
zero := g.type_default(it.val_type)
|
||||
atmp := g.new_tmp_var()
|
||||
atmp_styp := g.typ(it.cond_type)
|
||||
g.write('$atmp_styp $atmp = ')
|
||||
g.expr(it.cond)
|
||||
g.writeln(';')
|
||||
g.writeln('array_$key_styp $keys_tmp = map_keys(&$atmp);')
|
||||
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; ++$idx) {')
|
||||
g.writeln('for (int $idx = 0; $idx < $atmp\.key_values.len; ++$idx) {')
|
||||
g.writeln('\tif ($atmp\.key_values.keys[$idx].str == 0) {continue;}')
|
||||
if it.key_var != '_' {
|
||||
key_styp := g.typ(it.key_type)
|
||||
key := c_name(it.key_var)
|
||||
// TODO: analyze whether it.key_type has a .clone() method and call .clone() for all types:
|
||||
if it.key_type == table.string_type {
|
||||
g.writeln('\t$key_styp $key = /*kkkk*/ string_clone( (($key_styp*)${keys_tmp}.data)[$idx] );')
|
||||
g.writeln('\t$key_styp $key = /*kkkk*/ string_clone($atmp\.key_values.keys[$idx]);')
|
||||
} else {
|
||||
g.writeln('\t$key_styp $key = /*kkkk*/ (($key_styp*)${keys_tmp}.data)[$idx];')
|
||||
g.writeln('\t$key_styp $key = /*kkkk*/ $atmp\.key_values.keys[$idx];')
|
||||
}
|
||||
}
|
||||
if it.val_var != '_' {
|
||||
val_sym := g.table.get_type_symbol(it.val_type)
|
||||
valstr := '(void*)($atmp\.key_values.values + $idx * (u32)($atmp\.value_bytes))'
|
||||
if val_sym.kind == .function {
|
||||
g.write('\t')
|
||||
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(it.val_var))
|
||||
g.writeln(' = (*(voidptr*)map_get($atmp, $key, &(voidptr[]){ $zero }));')
|
||||
g.writeln(' = (*(voidptr*)$valstr);')
|
||||
} else {
|
||||
g.writeln('\t$val_styp ${c_name(it.val_var)} = (*($val_styp*)map_get($atmp, $key, &($val_styp[]){ $zero }));')
|
||||
val_styp := g.typ(it.val_type)
|
||||
g.writeln('\t$val_styp ${c_name(it.val_var)} = (*($val_styp*)$valstr);')
|
||||
}
|
||||
}
|
||||
g.stmts(it.stmts)
|
||||
|
@ -1213,9 +1214,6 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
|
|||
if it.label.len > 0 {
|
||||
g.writeln('\t$it.label\__break: {}')
|
||||
}
|
||||
g.writeln('/*for in map cleanup*/')
|
||||
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; ++$idx) { string_free(&(($key_styp*)${keys_tmp}.data)[$idx]); }')
|
||||
g.writeln('array_free(&$keys_tmp);')
|
||||
return
|
||||
} else if it.cond_type.has_flag(.variadic) {
|
||||
g.writeln('// FOR IN cond_type/variadic')
|
||||
|
|
|
@ -103,9 +103,11 @@ fn test_for_in_map_val() {
|
|||
}
|
||||
|
||||
fn test_for_in_map_both() {
|
||||
mut i := 0
|
||||
for _, _ in m {
|
||||
assert true
|
||||
i++
|
||||
}
|
||||
assert i == 1
|
||||
}
|
||||
|
||||
fn test_nested_for_in_map_key() {
|
||||
|
@ -127,11 +129,13 @@ fn test_nested_for_in_map_val() {
|
|||
}
|
||||
|
||||
fn test_nested_for_in_map_both() {
|
||||
mut i := 0
|
||||
for _, _ in m {
|
||||
for _, _ in m {
|
||||
assert true
|
||||
i++
|
||||
}
|
||||
}
|
||||
assert i == 1
|
||||
}
|
||||
|
||||
fn fn_for_in_variadic_args_simple(arr ...string) {
|
||||
|
|
|
@ -43,16 +43,24 @@ fn test_for_char_in_string() {
|
|||
assert sum == 394 // ascii codes of `a` + `b` + `c` + `d`
|
||||
}
|
||||
|
||||
fn test_for_char_in_map() {
|
||||
fn test_for_string_in_map() {
|
||||
m := {
|
||||
'a': 'b'
|
||||
'c': 'd'
|
||||
}
|
||||
mut acc := ''
|
||||
for k, char in m {
|
||||
acc += '$k: $char, '
|
||||
for k, v in m {
|
||||
acc += '$k: $v, '
|
||||
}
|
||||
assert acc == 'a: b, c: d, '
|
||||
|
||||
mut m2 := {'a': 3, 'b': 4, 'c': 5}
|
||||
m2.delete('b')
|
||||
acc = ''
|
||||
for k, v in m2 {
|
||||
acc += '$k: $v, '
|
||||
}
|
||||
assert acc == 'a: 3, c: 5, '
|
||||
}
|
||||
|
||||
fn test_mut_for() {
|
||||
|
|
Loading…
Reference in New Issue