diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c35d5014c1..5b2df6f00d 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -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) {') - // 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] );') - } else { - g.writeln('\t$key_styp $key = /*kkkk*/ (($key_styp*)${keys_tmp}.data)[$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($atmp\.key_values.keys[$idx]);') + } else { + 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') diff --git a/vlib/v/tests/blank_ident_test.v b/vlib/v/tests/blank_ident_test.v index 5c6094bc6c..e2678b3811 100644 --- a/vlib/v/tests/blank_ident_test.v +++ b/vlib/v/tests/blank_ident_test.v @@ -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) { diff --git a/vlib/v/tests/for_loops_test.v b/vlib/v/tests/for_loops_test.v index 0072101349..75e0250596 100644 --- a/vlib/v/tests/for_loops_test.v +++ b/vlib/v/tests/for_loops_test.v @@ -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() {