Skip to content

Commit 359f16f

Browse files
parser: fixed parsing prototype function with recursive type (#13922)
1 parent 0cba579 commit 359f16f

File tree

5 files changed

+30
-2
lines changed

5 files changed

+30
-2
lines changed

vlib/v/ast/table.v

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import v.util
1111

1212
[heap]
1313
pub struct Table {
14+
mut:
15+
parsing_type string // name of the type to enable recursive type parsing
1416
pub mut:
1517
type_symbols []&TypeSymbol
1618
type_idxs map[string]int
@@ -830,7 +832,17 @@ pub fn (mut t Table) register_enum_decl(enum_decl EnumDecl) {
830832
}
831833

832834
pub fn (t &Table) known_type(name string) bool {
833-
return t.find_type_idx(name) != 0
835+
return t.find_type_idx(name) != 0 || t.parsing_type == name
836+
}
837+
838+
// start_parsing_type open the scope during the parsing of a type
839+
// where the type name must include the module prefix
840+
pub fn (mut t Table) start_parsing_type(type_name string) {
841+
t.parsing_type = type_name
842+
}
843+
844+
pub fn (mut t Table) reset_parsing_type() {
845+
t.parsing_type = ''
834846
}
835847

836848
pub fn (t &Table) known_type_idx(typ Type) bool {

vlib/v/parser/fn.v

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,13 +738,14 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
738738
} else {
739739
p.tok.lit
740740
}
741+
741742
types_only := p.tok.kind in [.amp, .ellipsis, .key_fn, .lsbr]
742743
|| (p.peek_tok.kind == .comma && p.table.known_type(argname))
743744
|| p.peek_tok.kind == .dot || p.peek_tok.kind == .rpar
744745
|| (p.tok.kind == .key_mut && (p.peek_token(2).kind == .comma
745746
|| p.peek_token(2).kind == .rpar || (p.peek_tok.kind == .name
746747
&& p.peek_token(2).kind == .dot)))
747-
// TODO copy pasta, merge 2 branches
748+
// TODO copy paste, merge 2 branches
748749
if types_only {
749750
mut arg_no := 1
750751
for p.tok.kind != .rpar {
@@ -800,6 +801,7 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
800801
p.error_with_pos('expecting `)`', p.prev_tok.pos())
801802
return []ast.Param{}, false, false
802803
}
804+
803805
if p.tok.kind == .comma {
804806
if is_variadic {
805807
p.error_with_pos('cannot use ...(variadic) with non-final parameter no $arg_no',

vlib/v/parser/struct.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
5151
p.error_with_pos('cannot register struct `IError`, it is builtin interface type',
5252
name_pos)
5353
}
54+
// append module name before any type of parsing to enable recursion parsing
55+
p.table.start_parsing_type(p.prepend_mod(name))
56+
defer {
57+
p.table.reset_parsing_type()
58+
}
5459
generic_types, _ := p.parse_generic_types()
5560
no_body := p.tok.kind != .lcbr
5661
if language == .v && no_body {

vlib/v/parser/tests/function_prototype_in_struct.out

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module main
2+
3+
struct Ok {
4+
alibaba fn (Ok, )
5+
}
6+
7+
struct OkInt {
8+
a fn (int, )
9+
}

0 commit comments

Comments
 (0)