diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 63f31d3cfd..cd5ead91fd 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -406,16 +406,18 @@ pub: pub struct ForInStmt { pub: - key_var string - val_var string - cond Expr - is_range bool - high Expr // `10` in `for i in 0..10 {` - stmts []Stmt - pos token.Position + key_var string + val_var string + cond Expr + is_range bool + high Expr // `10` in `for i in 0..10 {` + stmts []Stmt + pos token.Position mut: - element_type table.Type - kind table.Kind // array/map/string + key_type table.Type + val_type table.Type + cond_type table.Type + kind table.Kind // array/map/string } pub struct ForCStmt { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d93191ce8f..3c1f5cebe7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -590,6 +590,7 @@ fn (c mut Checker) stmt(node ast.Stmt) { else { table.int_type} } + it.key_type = key_type scope.override_var(ast.Var{ name: it.key_var typ: key_type @@ -600,8 +601,9 @@ fn (c mut Checker) stmt(node ast.Stmt) { typ_sym := c.table.get_type_symbol(typ) c.error('for in: cannot index $typ_sym.name', it.pos) } + it.cond_type = typ it.kind = sym.kind - it.element_type = value_type + it.val_type = value_type scope.override_var(ast.Var{ name: it.val_var typ: value_type diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 699ef8de5b..3eb0cae7c0 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -366,13 +366,34 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.write('for (int $i = 0; $i < ') g.expr(it.cond) g.writeln('.len; $i++) {') - styp := g.typ(it.element_type) + styp := g.typ(it.val_type) g.write('$styp $it.val_var = (($styp*)') g.expr(it.cond) g.writeln('.data)[$i];') g.stmts(it.stmts) g.writeln('}') } + else if it.kind == .map { + // `for num in nums {` + g.writeln('// FOR IN') + cond_styp := g.typ(it.cond_type) + key_styp := g.typ(it.key_type) + val_styp := g.typ(it.val_type) + keys_tmp := 'keys_' + g.new_tmp_var() + idx := g.new_tmp_var() + key := if it.key_var == '' { g.new_tmp_var() } else { it.key_var } + g.write('array_$key_styp $keys_tmp = map_keys(&') + g.expr(it.cond) + g.writeln(');') + g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {') + g.writeln('$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];') + zero := g.type_default(it.val_type) + g.write('$val_styp $it.val_var = (*($val_styp*)map_get3(') + g.expr(it.cond) + g.writeln(', $key, &($val_styp[]){ $zero }));') + g.stmts(it.stmts) + g.writeln('}') + } } ast.ForStmt { g.write('while (')