map: fix delete in for-in (#9336)
parent
149151b1e8
commit
2991cad4e8
|
@ -255,6 +255,78 @@ fn test_delete_size() {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_nested_for_in() {
|
||||
mut m := map[string]int{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i
|
||||
}
|
||||
mut i := 0
|
||||
for key1, _ in m {
|
||||
assert key1 == i.str()
|
||||
i++
|
||||
mut j := 0
|
||||
for key2, _ in m {
|
||||
assert key2 == j.str()
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_delete_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
assert key == i.str()
|
||||
m.delete(key)
|
||||
i++
|
||||
}
|
||||
assert m.str() == '{}'
|
||||
assert m.len == 0
|
||||
}
|
||||
|
||||
fn test_set_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 10 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut last_key := ''
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
m['10'] = '10'
|
||||
assert key == i.str()
|
||||
last_key = key
|
||||
i++
|
||||
}
|
||||
assert last_key == '10'
|
||||
}
|
||||
|
||||
fn test_delete_and_set_in_for_in() {
|
||||
mut m := map[string]string{}
|
||||
for i in 0 .. 1000 {
|
||||
m[i.str()] = i.str()
|
||||
}
|
||||
mut i := 0
|
||||
for key, _ in m {
|
||||
assert key == i.str()
|
||||
m.delete(key)
|
||||
m[key] = i.str()
|
||||
if i == 999 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
assert m.len == 1000
|
||||
i = 0
|
||||
for key, _ in m {
|
||||
assert m[key] == i.str()
|
||||
i++
|
||||
}
|
||||
assert i == 1000
|
||||
}
|
||||
|
||||
struct Mstruct1 {
|
||||
pub mut:
|
||||
mymap map[string]int
|
||||
|
@ -326,7 +398,7 @@ fn test_assign_directly() {
|
|||
}
|
||||
|
||||
fn test_map_in_directly() {
|
||||
for k, v in {
|
||||
for k, v in map{
|
||||
'aa': 1
|
||||
} {
|
||||
assert k == 'aa'
|
||||
|
|
|
@ -1475,40 +1475,51 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
|||
}
|
||||
arw_or_pt := if node.cond_type.is_ptr() { '->' } else { '.' }
|
||||
idx := g.new_tmp_var()
|
||||
map_len := g.new_tmp_var()
|
||||
g.empty_line = true
|
||||
g.writeln('for (int $idx = 0; $idx < $cond_var${arw_or_pt}key_values.len; ++$idx) {')
|
||||
g.writeln('int $map_len = $cond_var${arw_or_pt}key_values.len;')
|
||||
g.writeln('for (int $idx = 0; $idx < $map_len; ++$idx ) {')
|
||||
// TODO: don't have this check when the map has no deleted elements
|
||||
g.writeln('\tif (!DenseArray_has_index(&$cond_var${arw_or_pt}key_values, $idx)) {continue;}')
|
||||
g.indent++
|
||||
diff := g.new_tmp_var()
|
||||
g.writeln('int $diff = $cond_var${arw_or_pt}key_values.len - $map_len;')
|
||||
g.writeln('$map_len = $cond_var${arw_or_pt}key_values.len;')
|
||||
// TODO: optimize this
|
||||
g.writeln('if ($diff < 0) {')
|
||||
g.writeln('\t$idx = -1;')
|
||||
g.writeln('\tcontinue;')
|
||||
g.writeln('}')
|
||||
g.writeln('if (!DenseArray_has_index(&$cond_var${arw_or_pt}key_values, $idx)) {continue;}')
|
||||
if node.key_var != '_' {
|
||||
key_styp := g.typ(node.key_type)
|
||||
key := c_name(node.key_var)
|
||||
g.writeln('\t$key_styp $key = /*key*/ *($key_styp*)DenseArray_key(&$cond_var${arw_or_pt}key_values, $idx);')
|
||||
g.writeln('$key_styp $key = /*key*/ *($key_styp*)DenseArray_key(&$cond_var${arw_or_pt}key_values, $idx);')
|
||||
// TODO: analyze whether node.key_type has a .clone() method and call .clone() for all types:
|
||||
if node.key_type == table.string_type {
|
||||
g.writeln('\t$key = string_clone($key);')
|
||||
g.writeln('$key = string_clone($key);')
|
||||
}
|
||||
}
|
||||
if node.val_var != '_' {
|
||||
val_sym := g.table.get_type_symbol(node.val_type)
|
||||
if val_sym.kind == .function {
|
||||
g.write('\t')
|
||||
g.write_fn_ptr_decl(val_sym.info as table.FnType, c_name(node.val_var))
|
||||
g.write(' = (*(voidptr*)')
|
||||
g.writeln('DenseArray_value(&$cond_var${arw_or_pt}key_values, $idx));')
|
||||
} else if val_sym.kind == .array_fixed && !node.val_is_mut {
|
||||
val_styp := g.typ(node.val_type)
|
||||
g.writeln('\t$val_styp ${c_name(node.val_var)};')
|
||||
g.writeln('\tmemcpy(*($val_styp*)${c_name(node.val_var)}, (byte*)DenseArray_value(&$cond_var${arw_or_pt}key_values, $idx), sizeof($val_styp));')
|
||||
g.writeln('$val_styp ${c_name(node.val_var)};')
|
||||
g.writeln('memcpy(*($val_styp*)${c_name(node.val_var)}, (byte*)DenseArray_value(&$cond_var${arw_or_pt}key_values, $idx), sizeof($val_styp));')
|
||||
} else {
|
||||
val_styp := g.typ(node.val_type)
|
||||
if node.val_type.is_ptr() {
|
||||
g.write('\t$val_styp ${c_name(node.val_var)} = &(*($val_styp)')
|
||||
g.write('$val_styp ${c_name(node.val_var)} = &(*($val_styp)')
|
||||
} else {
|
||||
g.write('\t$val_styp ${c_name(node.val_var)} = (*($val_styp*)')
|
||||
g.write('$val_styp ${c_name(node.val_var)} = (*($val_styp*)')
|
||||
}
|
||||
g.writeln('DenseArray_value(&$cond_var${arw_or_pt}key_values, $idx));')
|
||||
}
|
||||
}
|
||||
g.indent--
|
||||
} else if node.kind == .string {
|
||||
cond := if node.cond is ast.StringLiteral || node.cond is ast.StringInterLiteral {
|
||||
ast.Expr(g.new_ctemp_var_then_gen(node.cond, table.string_type))
|
||||
|
@ -1557,6 +1568,16 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
|||
if node.label.len > 0 {
|
||||
g.writeln('\t${node.label}__continue: {}')
|
||||
}
|
||||
|
||||
if node.kind == .map {
|
||||
// diff := g.new_tmp_var()
|
||||
// g.writeln('int $diff = $cond_var${arw_or_pt}key_values.len - $map_len;')
|
||||
// g.writeln('if ($diff < 0) {')
|
||||
// g.writeln('\t$idx = -1;')
|
||||
// g.writeln('\t$map_len = $cond_var${arw_or_pt}key_values.len;')
|
||||
// g.writeln('}')
|
||||
}
|
||||
|
||||
g.writeln('}')
|
||||
if node.label.len > 0 {
|
||||
g.writeln('\t${node.label}__break: {}')
|
||||
|
|
Loading…
Reference in New Issue