parser: support `mut:` section in the interface methods, and a mut interface fn modifier (#8092)
parent
1b09954622
commit
72168cd6bc
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/function_arg_mutable_err.vv:1:18: error: mutable arguments are only allowed for arrays, maps, structs and pointers
|
vlib/v/checker/tests/function_arg_mutable_err.vv:1:18: error: mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs
|
||||||
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
||||||
1 | fn mod_ptr(mut a int) {
|
1 | fn mod_ptr(mut a int) {
|
||||||
| ~~~
|
| ~~~
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/mut_int.vv:1:14: error: mutable arguments are only allowed for arrays, maps, structs and pointers
|
vlib/v/checker/tests/mut_int.vv:1:14: error: mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs
|
||||||
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
||||||
1 | fn foo(mut x int) {
|
1 | fn foo(mut x int) {
|
||||||
| ~~~
|
| ~~~
|
||||||
|
|
|
@ -700,10 +700,11 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
||||||
|
|
||||||
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
||||||
sym := p.table.get_type_symbol(typ)
|
sym := p.table.get_type_symbol(typ)
|
||||||
if sym.kind !in [.array, .array_fixed, .struct_, .map, .placeholder, .sum_type] &&
|
if sym.kind !in
|
||||||
|
[.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] &&
|
||||||
!typ.is_ptr() && !typ.is_pointer()
|
!typ.is_ptr() && !typ.is_pointer()
|
||||||
{
|
{
|
||||||
p.error_with_pos('mutable arguments are only allowed for arrays, maps, structs and pointers\n' +
|
p.error_with_pos('mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs\n' +
|
||||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,8 +462,18 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
ts.methods = []table.Fn{cap: 20}
|
ts.methods = []table.Fn{cap: 20}
|
||||||
// Parse methods
|
// Parse methods
|
||||||
mut methods := []ast.FnDecl{cap: 20}
|
mut methods := []ast.FnDecl{cap: 20}
|
||||||
|
mut is_mut := false
|
||||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||||
ts = p.table.get_type_symbol(typ) // removing causes memory bug visible by `v -silent test-fmt`
|
ts = p.table.get_type_symbol(typ) // removing causes memory bug visible by `v -silent test-fmt`
|
||||||
|
if p.tok.kind == .key_mut {
|
||||||
|
if is_mut {
|
||||||
|
p.error_with_pos('redefinition of `mut` section', p.tok.position())
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
p.check(.colon)
|
||||||
|
is_mut = true
|
||||||
|
}
|
||||||
method_start_pos := p.tok.position()
|
method_start_pos := p.tok.position()
|
||||||
line_nr := p.tok.line_nr
|
line_nr := p.tok.line_nr
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
|
@ -479,6 +489,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
args2, _, is_variadic := p.fn_args() // TODO merge table.Param and ast.Arg to avoid this
|
args2, _, is_variadic := p.fn_args() // TODO merge table.Param and ast.Arg to avoid this
|
||||||
mut args := [table.Param{
|
mut args := [table.Param{
|
||||||
name: 'x'
|
name: 'x'
|
||||||
|
is_mut: is_mut
|
||||||
typ: typ
|
typ: typ
|
||||||
is_hidden: true
|
is_hidden: true
|
||||||
}]
|
}]
|
||||||
|
|
|
@ -7,7 +7,7 @@ mut:
|
||||||
breed string
|
breed string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Cat) name() string {
|
fn (c &Cat) name() string {
|
||||||
if c.breed != '' {
|
if c.breed != '' {
|
||||||
assert c.breed == 'Persian'
|
assert c.breed == 'Persian'
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ fn test_perform_speak() {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_animal_breed(a &Animal, new string) {
|
fn change_animal_breed(mut a Animal, new string) {
|
||||||
a.set_breed(new)
|
a.set_breed(new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ fn test_interface_ptr_modification() {
|
||||||
breed: 'Persian'
|
breed: 'Persian'
|
||||||
}
|
}
|
||||||
// TODO Should fail and require `mut cat`
|
// TODO Should fail and require `mut cat`
|
||||||
change_animal_breed(cat, 'Siamese')
|
change_animal_breed(mut cat, 'Siamese')
|
||||||
assert cat.breed == 'Siamese'
|
assert cat.breed == 'Siamese'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,11 +218,9 @@ fn (mut b Boss) return_speaker2() ?Speaker2 {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_speaker2(sp Speaker2) Speaker2 {
|
fn return_speaker2(mut sp Speaker2) Speaker2 {
|
||||||
s := sp.return_speaker()
|
s := sp.return_speaker()
|
||||||
s2 := sp.return_speaker2() or {
|
s2 := sp.return_speaker2() or { return *sp }
|
||||||
return sp
|
|
||||||
}
|
|
||||||
s.speak()
|
s.speak()
|
||||||
s2.speak()
|
s2.speak()
|
||||||
return s2
|
return s2
|
||||||
|
@ -231,7 +229,7 @@ fn return_speaker2(sp Speaker2) Speaker2 {
|
||||||
fn test_interface_returning_interface() {
|
fn test_interface_returning_interface() {
|
||||||
mut b := Boss{'bob'}
|
mut b := Boss{'bob'}
|
||||||
assert b.name == 'bob'
|
assert b.name == 'bob'
|
||||||
s2 := return_speaker2(b)
|
s2 := return_speaker2(mut b)
|
||||||
if s2 is Boss {
|
if s2 is Boss {
|
||||||
assert s2.name == 'boss'
|
assert s2.name == 'boss'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue