all: `for mut val in vals {` (part 1)

pull/6613/head
Alexander Medvednikov 2020-10-13 16:27:24 +02:00
parent d316f78f94
commit a07f31feae
4 changed files with 33 additions and 5 deletions

View File

@ -600,6 +600,8 @@ pub:
high Expr // `10` in `for i in 0..10 {` high Expr // `10` in `for i in 0..10 {`
stmts []Stmt stmts []Stmt
pos token.Position 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: pub mut:
key_type table.Type key_type table.Type
val_type table.Type val_type table.Type

View File

@ -2357,17 +2357,24 @@ fn (mut c Checker) stmt(node ast.Stmt) {
node.key_type = key_type node.key_type = key_type
scope.update_var_type(node.key_var, 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 value_type == table.void_type || typ.has_flag(.optional) {
if typ != table.void_type { if typ != table.void_type {
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', c.error('for in: cannot index `${c.table.type_to_str(typ)}`',
node.cond.position()) node.cond.position())
} }
} }
// if node.val_is_mut {
// value_type = value_type.to_ptr()
// }
node.cond_type = typ node.cond_type = typ
node.kind = sym.kind node.kind = sym.kind
node.val_type = value_type 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.stmts(node.stmts)
c.in_for_count-- c.in_for_count--

View File

@ -25,10 +25,11 @@ fn (mut p Parser) for_stmt() ast.Stmt {
pos: pos pos: pos
is_inf: true 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 { } else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon {
// `for i := 0; i < 10; i++ {` // `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 init := ast.Stmt{}
mut cond := p.new_true_expr() mut cond := p.new_true_expr()
mut inc := ast.Stmt{} mut inc := ast.Stmt{}
@ -68,8 +69,13 @@ fn (mut p Parser) for_stmt() ast.Stmt {
inc: inc inc: inc
pos: pos 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` // `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() key_var_pos := p.tok.position()
mut val_var_pos := p.tok.position() mut val_var_pos := p.tok.position()
mut key_var_name := '' mut key_var_name := ''
@ -124,6 +130,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
p.scope.register(val_var_name, ast.Var{ p.scope.register(val_var_name, ast.Var{
name: val_var_name name: val_var_name
pos: val_var_pos pos: val_var_pos
is_mut: val_is_mut
}) })
} }
p.inside_for = false p.inside_for = false
@ -138,6 +145,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
high: high_expr high: high_expr
is_range: is_range is_range: is_range
pos: pos pos: pos
val_is_mut: val_is_mut
} }
} }
// `for cond {` // `for cond {`

View File

@ -54,3 +54,14 @@ fn test_for_char_in_map() {
} }
assert acc == 'a: b, c: d, ' 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)
*/
}