From a07f31feae4b6846afe0dd16e817405ec400be5b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 13 Oct 2020 16:27:24 +0200 Subject: [PATCH] all: `for mut val in vals {` (part 1) --- vlib/v/ast/ast.v | 2 ++ vlib/v/checker/checker.v | 11 +++++++++-- vlib/v/parser/for.v | 14 +++++++++++--- vlib/v/tests/for_loops_test.v | 11 +++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index da9975dac8..34f0f35929 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -600,6 +600,8 @@ pub: high Expr // `10` in `for i in 0..10 {` stmts []Stmt pos token.Position + val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array + // and the array cannot be indexed inside the loop pub mut: key_type table.Type val_type table.Type diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 116038f63d..bf0f660f93 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2357,17 +2357,24 @@ fn (mut c Checker) stmt(node ast.Stmt) { node.key_type = key_type scope.update_var_type(node.key_var, key_type) } - value_type := c.table.value_type(typ) + mut value_type := c.table.value_type(typ) if value_type == table.void_type || typ.has_flag(.optional) { if typ != table.void_type { c.error('for in: cannot index `${c.table.type_to_str(typ)}`', node.cond.position()) } } + // if node.val_is_mut { + // value_type = value_type.to_ptr() + // } node.cond_type = typ node.kind = sym.kind node.val_type = value_type - scope.update_var_type(node.val_var, value_type) + if node.val_is_mut { + scope.update_var_type(node.val_var, value_type.to_ptr()) + } else { + scope.update_var_type(node.val_var, value_type) + } } c.stmts(node.stmts) c.in_for_count-- diff --git a/vlib/v/parser/for.v b/vlib/v/parser/for.v index fb93886207..20cde3fbaf 100644 --- a/vlib/v/parser/for.v +++ b/vlib/v/parser/for.v @@ -25,10 +25,11 @@ fn (mut p Parser) for_stmt() ast.Stmt { pos: pos is_inf: true } - } else if p.tok.kind == .key_mut { - p.error('`mut` is not needed in for loops') } else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon { // `for i := 0; i < 10; i++ {` + if p.tok.kind == .key_mut { + p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`') + } mut init := ast.Stmt{} mut cond := p.new_true_expr() mut inc := ast.Stmt{} @@ -68,8 +69,13 @@ fn (mut p Parser) for_stmt() ast.Stmt { inc: inc pos: pos } - } else if p.peek_tok.kind in [.key_in, .comma] { + } else if p.peek_tok.kind in [.key_in, .comma] || + (p.tok.kind == .key_mut && p.peek_tok2.kind in [.key_in, .comma]) { // `for i in vals`, `for i in start .. end` + val_is_mut := p.tok.kind == .key_mut + if val_is_mut { + p.next() + } key_var_pos := p.tok.position() mut val_var_pos := p.tok.position() mut key_var_name := '' @@ -124,6 +130,7 @@ fn (mut p Parser) for_stmt() ast.Stmt { p.scope.register(val_var_name, ast.Var{ name: val_var_name pos: val_var_pos + is_mut: val_is_mut }) } p.inside_for = false @@ -138,6 +145,7 @@ fn (mut p Parser) for_stmt() ast.Stmt { high: high_expr is_range: is_range pos: pos + val_is_mut: val_is_mut } } // `for cond {` diff --git a/vlib/v/tests/for_loops_test.v b/vlib/v/tests/for_loops_test.v index 4ce5efdef0..92c0c67e21 100644 --- a/vlib/v/tests/for_loops_test.v +++ b/vlib/v/tests/for_loops_test.v @@ -54,3 +54,14 @@ fn test_for_char_in_map() { } assert acc == 'a: b, c: d, ' } + +fn test_mut_for() { + /* + mut vals := [1,2,3] + for mut val in vals { + (*val)++ + } + assert vals == [2,3,4] + println(vals) + */ +}