Skip to content

Commit

Permalink
all: make implements work with multiple interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
medvednikov committed Sep 9, 2024
1 parent 3300e59 commit ac6ca5f
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 25 deletions.
4 changes: 2 additions & 2 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,8 @@ pub:
end_comments []Comment
embeds []Embed

is_implements bool
implements_type Type
is_implements bool
implements_types []Type
pub mut:
fields []StructField
}
Expand Down
4 changes: 3 additions & 1 deletion vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
// XTODO2
// cgen error if I use `println(sym)` without handling the option with `or{}`
struct_type := c.table.find_type_idx(node.name) // or { panic(err) }
c.type_implements(struct_type, node.implements_type, node.pos)
for t in node.implements_types {
c.type_implements(struct_type, t, node.pos)
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/implements_keyword.out
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,17 @@ vlib/v/checker/tests/implements_keyword.vv:5:1: error: `CustomError` doesn't imp
| ~~~~~~~~~~~~~~~~~~
6 | }
7 |
vlib/v/checker/tests/implements_keyword.vv:15:1: error: `CustomError2` doesn't implement method `print_error` of interface `MyError`
13 | }
14 |
15 | struct CustomError2 implements MyError, MyError2 {
| ~~~~~~~~~~~~~~~~~~~
16 | }
17 |
vlib/v/checker/tests/implements_keyword.vv:15:1: error: `CustomError2` doesn't implement method `print_error2` of interface `MyError2`
13 | }
14 |
15 | struct CustomError2 implements MyError, MyError2 {
| ~~~~~~~~~~~~~~~~~~~
16 | }
17 |
10 changes: 10 additions & 0 deletions vlib/v/checker/tests/implements_keyword.vv
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ struct CustomError implements MyError {

fn (e CustomError) print_error2() {
}

interface MyError2 {
print_error2()
}

struct CustomError2 implements MyError, MyError2 {
}

fn (e CustomError2) print_error3() {
}
7 changes: 6 additions & 1 deletion vlib/v/fmt/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) {
mut field_types := []string{cap: node.fields.len}
if node.is_implements {
f.write(' implements ')
f.write(f.table.type_to_str_using_aliases(node.implements_type, f.mod2alias))
for i, t in node.implements_types {
f.write(f.table.type_to_str_using_aliases(t, f.mod2alias))
if i < node.implements_types.len - 1 {
f.write(', ')
}
}
}
// Calculate the alignments first
f.calculate_alignment(node.fields, mut type_align, mut comment_align, mut default_expr_align, mut
Expand Down
47 changes: 26 additions & 21 deletions vlib/v/parser/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,19 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
mut is_field_pub := false
mut is_field_global := false
mut is_implements := false
mut implements_type := ast.void_type
mut implements_types := []ast.Type{cap: 3} // ast.void_type
mut last_line := p.prev_tok.pos().line_nr + 1
mut end_comments := []ast.Comment{}
if !no_body {
if p.tok.kind == .key_implements {
p.next()
implements_type = p.parse_type()
is_implements = true
for {
p.next()
implements_types << p.parse_type()
if p.tok.kind != .comma {
break
}
}
}
p.check(.lcbr)
pre_comments << p.eat_comments()
Expand Down Expand Up @@ -378,24 +383,24 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
}
p.expr_mod = ''
return ast.StructDecl{
name: name
is_pub: is_pub
fields: ast_fields
pos: start_pos.extend_with_last_line(name_pos, last_line)
mut_pos: mut_pos
pub_pos: pub_pos
pub_mut_pos: pub_mut_pos
global_pos: global_pos
module_pos: module_pos
language: language
is_union: is_union
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
pre_comments: pre_comments
end_comments: end_comments
generic_types: generic_types
embeds: embeds
is_implements: is_implements
implements_type: implements_type
name: name
is_pub: is_pub
fields: ast_fields
pos: start_pos.extend_with_last_line(name_pos, last_line)
mut_pos: mut_pos
pub_pos: pub_pos
pub_mut_pos: pub_mut_pos
global_pos: global_pos
module_pos: module_pos
language: language
is_union: is_union
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
pre_comments: pre_comments
end_comments: end_comments
generic_types: generic_types
embeds: embeds
is_implements: is_implements
implements_types: implements_types
}
}

Expand Down

0 comments on commit ac6ca5f

Please sign in to comment.