mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
compiler: multiple return - allow mut decl & disallow assignment with deceleration (#2251)
This commit is contained in:
parent
ac5241b5bd
commit
8fea5170be
@ -1425,28 +1425,32 @@ fn (p mut Parser) var_decl() {
|
|||||||
p.check(.key_static)
|
p.check(.key_static)
|
||||||
p.fspace()
|
p.fspace()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut var_token_idxs := [p.cur_tok_index()]
|
||||||
|
mut var_mut := [is_mut] // add first var mut
|
||||||
|
mut var_names := [p.check_name()] // add first variable
|
||||||
|
|
||||||
mut names := []string
|
p.scanner.validate_var_name(var_names[0])
|
||||||
mut vtoken_idxs := []int
|
// mut new_vars := 0
|
||||||
|
// if var_names[0] != '_' && !p.known_var(var_names[0]) {
|
||||||
vtoken_idxs << p.cur_tok_index()
|
// new_vars++
|
||||||
// first variable
|
// }
|
||||||
names << p.check_name()
|
|
||||||
p.scanner.validate_var_name(names[0])
|
|
||||||
mut new_vars := 0
|
|
||||||
if names[0] != '_' && !p.known_var(names[0]) {
|
|
||||||
new_vars++
|
|
||||||
}
|
|
||||||
// more than 1 vars (multiple returns)
|
// more than 1 vars (multiple returns)
|
||||||
for p.tok == .comma {
|
for p.tok == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
vtoken_idxs << p.cur_tok_index()
|
if p.tok == .key_mut {
|
||||||
name := p.check_name()
|
p.check(.key_mut)
|
||||||
names << name
|
var_mut << true
|
||||||
p.scanner.validate_var_name(name)
|
} else {
|
||||||
if name != '_' && !p.known_var(name) {
|
var_mut << false
|
||||||
new_vars++
|
|
||||||
}
|
}
|
||||||
|
var_token_idxs << p.cur_tok_index()
|
||||||
|
var_name := p.check_name()
|
||||||
|
p.scanner.validate_var_name(var_name)
|
||||||
|
// if var_name != '_' && !p.known_var(var_name) {
|
||||||
|
// new_vars++
|
||||||
|
// }
|
||||||
|
var_names << var_name
|
||||||
}
|
}
|
||||||
is_assign := p.tok == .assign
|
is_assign := p.tok == .assign
|
||||||
is_decl_assign := p.tok == .decl_assign
|
is_decl_assign := p.tok == .decl_assign
|
||||||
@ -1458,72 +1462,78 @@ fn (p mut Parser) var_decl() {
|
|||||||
p.error('expected `=` or `:=`')
|
p.error('expected `=` or `:=`')
|
||||||
}
|
}
|
||||||
// all vars on left of `:=` already defined
|
// all vars on left of `:=` already defined
|
||||||
if is_decl_assign && names.len > 1 && new_vars == 0 {
|
// if is_decl_assign && var_names.len > 1 && new_vars == 0 {
|
||||||
p.error('no new variables on left side of `:=`')
|
// p.error_with_token_index('no new variables on left side of `:=`', var_token_idxs.last())
|
||||||
}
|
// }
|
||||||
p.var_decl_name = if names.len > 1 { '__ret_'+names.join('_') } else { names[0] }
|
p.var_decl_name = if var_names.len > 1 { '_V_mret_'+var_names.join('_') } else { var_names[0] }
|
||||||
t := p.gen_var_decl(p.var_decl_name, is_static)
|
t := p.gen_var_decl(p.var_decl_name, is_static)
|
||||||
mut types := [t]
|
mut var_types := [t]
|
||||||
// multiple returns types
|
// multiple returns types
|
||||||
if names.len > 1 {
|
if var_names.len > 1 {
|
||||||
// should we register __ret var?
|
var_types = t.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_')
|
||||||
types = t.replace('_V_MulRet_', '').replace('_PTR_', '*').split('_V_')
|
|
||||||
}
|
}
|
||||||
for i, name in names {
|
// mismatched number of return & assignment vars
|
||||||
var_token_idx := vtoken_idxs[i]
|
if var_names.len != var_types.len {
|
||||||
if name == '_' {
|
mr_fn := p.cgen.cur_line.find_between('=', '(').trim_space()
|
||||||
|
p.error_with_token_index('assignment mismatch: ${var_names.len} variables but `$mr_fn` returns $var_types.len values', var_token_idxs.last())
|
||||||
|
}
|
||||||
|
for i, var_name in var_names {
|
||||||
|
var_token_idx := var_token_idxs[i]
|
||||||
|
if var_name == '_' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
typ := types[i]
|
var_is_mut := var_mut[i]
|
||||||
// println('var decl tok=${p.strtok()} ismut=$is_mut')
|
var_type := var_types[i]
|
||||||
|
known_var := p.known_var(var_name)
|
||||||
|
// println('var decl tok=${p.strtok()} name=type=$var_name type=$var_type ismut=$var_is_mut')
|
||||||
|
// var decl, already exists (shadowing is not allowed)
|
||||||
// Don't allow declaring a variable with the same name. Even in a child scope
|
// Don't allow declaring a variable with the same name. Even in a child scope
|
||||||
// (shadowing is not allowed)
|
// if var_names.len == 1 && !p.builtin_mod && known_var {
|
||||||
known_var := p.known_var(name)
|
if is_decl_assign && known_var {
|
||||||
// single var decl, already exists
|
p.error_with_token_index('redefinition of `$var_name`', var_token_idx)
|
||||||
if names.len == 1 && !p.builtin_mod && known_var {
|
}
|
||||||
p.error_with_token_index('redefinition of `$name`', var_token_idx)
|
// mut specified with assignment
|
||||||
|
if /*is_assign && implicit*/ known_var && var_is_mut {
|
||||||
|
p.error_with_token_index('cannot specify mutability for existing var `$var_name`, only for new vars', var_token_idx)
|
||||||
}
|
}
|
||||||
// assignment, but var does not exist
|
// assignment, but var does not exist
|
||||||
if names.len > 1 && is_assign && !known_var {
|
if is_assign && !known_var {
|
||||||
suggested := p.find_misspelled_local_var(name, 50)
|
suggested := p.find_misspelled_local_var(var_name, 50)
|
||||||
if suggested != '' {
|
if suggested != '' {
|
||||||
p.error_with_token_index('undefined: `$name`. did you mean:$suggested', var_token_idx)
|
p.error_with_token_index('undefined: `$var_name`. did you mean:$suggested', var_token_idx)
|
||||||
}
|
}
|
||||||
p.error_with_token_index('undefined: `$name`.', var_token_idx)
|
p.error_with_token_index('undefined: `$var_name`.', var_token_idx)
|
||||||
}
|
}
|
||||||
if name.len > 1 && contains_capital(name) {
|
if var_name.len > 1 && contains_capital(var_name) {
|
||||||
p.error_with_token_index('variable names cannot contain uppercase letters, use snake_case instead', var_token_idx)
|
p.error_with_token_index('variable names cannot contain uppercase letters, use snake_case instead', var_token_idx)
|
||||||
}
|
}
|
||||||
// mismatched number of return & assignment vars
|
|
||||||
if names.len != types.len {
|
|
||||||
mr_fn := p.cgen.cur_line.find_between('=', '(').trim_space()
|
|
||||||
p.error_with_token_index('assignment mismatch: ${names.len} variables but `$mr_fn` returns $types.len values', var_token_idx)
|
|
||||||
}
|
|
||||||
// multiple return
|
// multiple return
|
||||||
if names.len > 1 {
|
if var_names.len > 1 {
|
||||||
p.gen(';\n')
|
p.gen(';\n')
|
||||||
// assigment
|
// assigment
|
||||||
if !p.builtin_mod && known_var {
|
// if !p.builtin_mod && known_var {
|
||||||
v := p.find_var(name) or {
|
if known_var {
|
||||||
p.error_with_token_index('cannot find `$name`', var_token_idx)
|
v := p.find_var(var_name) or {
|
||||||
|
p.error_with_token_index('cannot find `$var_name`', var_token_idx)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
p.check_types_with_token_index(typ, v.typ, var_token_idx)
|
p.check_types_with_token_index(var_type, v.typ, var_token_idx)
|
||||||
if !v.is_mut {
|
if !v.is_mut {
|
||||||
p.error_with_token_index('`$v.name` is immutable', var_token_idx)
|
p.error_with_token_index('`$v.name` is immutable', var_token_idx)
|
||||||
}
|
}
|
||||||
|
p.mark_var_used(v)
|
||||||
p.mark_var_changed(v)
|
p.mark_var_changed(v)
|
||||||
p.gen('$name = ${p.var_decl_name}.var_$i')
|
p.gen('$var_name = ${p.var_decl_name}.var_$i')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// decleration
|
// decleration
|
||||||
p.gen('$typ $name = ${p.var_decl_name}.var_$i')
|
p.gen('$var_type $var_name = ${p.var_decl_name}.var_$i')
|
||||||
}
|
}
|
||||||
p.register_var(Var {
|
p.register_var(Var {
|
||||||
name: name
|
name: var_name
|
||||||
typ: typ
|
typ: var_type
|
||||||
is_mut: is_mut
|
is_mut: var_is_mut
|
||||||
is_alloc: p.is_alloc || typ.starts_with('array_')
|
is_alloc: p.is_alloc || var_type.starts_with('array_')
|
||||||
line_nr: p.tokens[ var_token_idx ].line_nr
|
line_nr: p.tokens[ var_token_idx ].line_nr
|
||||||
token_idx: var_token_idx
|
token_idx: var_token_idx
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user