Skip to content

Commit ac6ca5f

Browse files
committed
all: make implements work with multiple interfaces
1 parent 3300e59 commit ac6ca5f

File tree

6 files changed

+61
-25
lines changed

6 files changed

+61
-25
lines changed

vlib/v/ast/ast.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@ pub:
417417
end_comments []Comment
418418
embeds []Embed
419419

420-
is_implements bool
421-
implements_type Type
420+
is_implements bool
421+
implements_types []Type
422422
pub mut:
423423
fields []StructField
424424
}

vlib/v/checker/struct.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
333333
// XTODO2
334334
// cgen error if I use `println(sym)` without handling the option with `or{}`
335335
struct_type := c.table.find_type_idx(node.name) // or { panic(err) }
336-
c.type_implements(struct_type, node.implements_type, node.pos)
336+
for t in node.implements_types {
337+
c.type_implements(struct_type, t, node.pos)
338+
}
337339
}
338340
}
339341

vlib/v/checker/tests/implements_keyword.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,17 @@ vlib/v/checker/tests/implements_keyword.vv:5:1: error: `CustomError` doesn't imp
55
| ~~~~~~~~~~~~~~~~~~
66
6 | }
77
7 |
8+
vlib/v/checker/tests/implements_keyword.vv:15:1: error: `CustomError2` doesn't implement method `print_error` of interface `MyError`
9+
13 | }
10+
14 |
11+
15 | struct CustomError2 implements MyError, MyError2 {
12+
| ~~~~~~~~~~~~~~~~~~~
13+
16 | }
14+
17 |
15+
vlib/v/checker/tests/implements_keyword.vv:15:1: error: `CustomError2` doesn't implement method `print_error2` of interface `MyError2`
16+
13 | }
17+
14 |
18+
15 | struct CustomError2 implements MyError, MyError2 {
19+
| ~~~~~~~~~~~~~~~~~~~
20+
16 | }
21+
17 |

vlib/v/checker/tests/implements_keyword.vv

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ struct CustomError implements MyError {
77

88
fn (e CustomError) print_error2() {
99
}
10+
11+
interface MyError2 {
12+
print_error2()
13+
}
14+
15+
struct CustomError2 implements MyError, MyError2 {
16+
}
17+
18+
fn (e CustomError2) print_error3() {
19+
}

vlib/v/fmt/struct.v

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
3333
mut field_types := []string{cap: node.fields.len}
3434
if node.is_implements {
3535
f.write(' implements ')
36-
f.write(f.table.type_to_str_using_aliases(node.implements_type, f.mod2alias))
36+
for i, t in node.implements_types {
37+
f.write(f.table.type_to_str_using_aliases(t, f.mod2alias))
38+
if i < node.implements_types.len - 1 {
39+
f.write(', ')
40+
}
41+
}
3742
}
3843
// Calculate the alignments first
3944
f.calculate_alignment(node.fields, mut type_align, mut comment_align, mut default_expr_align, mut

vlib/v/parser/struct.v

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,19 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
9494
mut is_field_pub := false
9595
mut is_field_global := false
9696
mut is_implements := false
97-
mut implements_type := ast.void_type
97+
mut implements_types := []ast.Type{cap: 3} // ast.void_type
9898
mut last_line := p.prev_tok.pos().line_nr + 1
9999
mut end_comments := []ast.Comment{}
100100
if !no_body {
101101
if p.tok.kind == .key_implements {
102-
p.next()
103-
implements_type = p.parse_type()
104102
is_implements = true
103+
for {
104+
p.next()
105+
implements_types << p.parse_type()
106+
if p.tok.kind != .comma {
107+
break
108+
}
109+
}
105110
}
106111
p.check(.lcbr)
107112
pre_comments << p.eat_comments()
@@ -378,24 +383,24 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
378383
}
379384
p.expr_mod = ''
380385
return ast.StructDecl{
381-
name: name
382-
is_pub: is_pub
383-
fields: ast_fields
384-
pos: start_pos.extend_with_last_line(name_pos, last_line)
385-
mut_pos: mut_pos
386-
pub_pos: pub_pos
387-
pub_mut_pos: pub_mut_pos
388-
global_pos: global_pos
389-
module_pos: module_pos
390-
language: language
391-
is_union: is_union
392-
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
393-
pre_comments: pre_comments
394-
end_comments: end_comments
395-
generic_types: generic_types
396-
embeds: embeds
397-
is_implements: is_implements
398-
implements_type: implements_type
386+
name: name
387+
is_pub: is_pub
388+
fields: ast_fields
389+
pos: start_pos.extend_with_last_line(name_pos, last_line)
390+
mut_pos: mut_pos
391+
pub_pos: pub_pos
392+
pub_mut_pos: pub_mut_pos
393+
global_pos: global_pos
394+
module_pos: module_pos
395+
language: language
396+
is_union: is_union
397+
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
398+
pre_comments: pre_comments
399+
end_comments: end_comments
400+
generic_types: generic_types
401+
embeds: embeds
402+
is_implements: is_implements
403+
implements_types: implements_types
399404
}
400405
}
401406

0 commit comments

Comments
 (0)