Skip to content

Commit b19b97e

Browse files
authored
generic: replace generic <> with [] part 1 - allow for both (#16532)
1 parent a9b41d2 commit b19b97e

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

vlib/v/parser/fn.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr
3535

3636
mut concrete_types := []ast.Type{}
3737
mut concrete_list_pos := p.tok.pos()
38-
if p.tok.kind == .lt {
38+
if p.tok.kind in [.lt, .lsbr] {
3939
// `foo<int>(10)`
4040
p.expr_mod = ''
4141
concrete_types = p.parse_concrete_types()

vlib/v/parser/parse_type.v

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,8 @@ pub fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_d
629629
if name.len == 1 && name[0].is_capital() {
630630
return p.parse_generic_type(name)
631631
}
632-
if p.tok.kind == .lt {
632+
if p.tok.kind in [.lt, .lsbr]
633+
&& p.tok.pos - p.prev_tok.pos == p.prev_tok.len {
633634
return p.parse_generic_inst_type(name)
634635
}
635636
return p.find_type_or_add_placeholder(name, language)
@@ -707,7 +708,7 @@ pub fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
707708
p.struct_init_generic_types = concrete_types
708709
}
709710
concrete_types_pos := start_pos.extend(p.tok.pos())
710-
p.check(.gt)
711+
p.next()
711712
p.inside_generic_params = false
712713
bs_name += '>'
713714
// fmt operates on a per-file basis, so is_instance might be not set correctly. Thus it's ignored.

vlib/v/parser/parser.v

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,32 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
21592159
}
21602160
}
21612161

2162+
fn (p &Parser) is_generic_struct_init() bool {
2163+
lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
2164+
if !lit0_is_capital || p.peek_tok.kind !in [.lt, .lsbr] {
2165+
return false
2166+
}
2167+
if p.peek_tok.kind == .lt {
2168+
return true
2169+
} else {
2170+
mut i := 2
2171+
for {
2172+
cur_tok := p.peek_token(i)
2173+
if cur_tok.kind == .eof || cur_tok.kind !in [.amp, .dot, .comma, .name, .lsbr, .rsbr] {
2174+
break
2175+
}
2176+
if cur_tok.kind == .rsbr {
2177+
if p.peek_token(i + 1).kind == .lcbr {
2178+
return true
2179+
}
2180+
break
2181+
}
2182+
i++
2183+
}
2184+
}
2185+
return false
2186+
}
2187+
21622188
fn (p &Parser) is_typename(t token.Token) bool {
21632189
return t.kind == .name && (t.lit[0].is_capital() || p.table.known_type(t.lit))
21642190
}
@@ -2177,7 +2203,7 @@ fn (p &Parser) is_typename(t token.Token) bool {
21772203
// see also test_generic_detection in vlib/v/tests/generics_test.v
21782204
fn (p &Parser) is_generic_call() bool {
21792205
lit0_is_capital := p.tok.kind != .eof && p.tok.lit.len > 0 && p.tok.lit[0].is_capital()
2180-
if lit0_is_capital || p.peek_tok.kind != .lt {
2206+
if lit0_is_capital || p.peek_tok.kind !in [.lt, .lsbr] {
21812207
return false
21822208
}
21832209
mut tok2 := p.peek_token(2)
@@ -2206,13 +2232,31 @@ fn (p &Parser) is_generic_call() bool {
22062232
// case 2
22072233
return true
22082234
}
2209-
return match kind3 {
2210-
.gt { true } // case 3
2211-
.lt { !(tok4.lit.len == 1 && tok4.lit[0].is_capital()) } // case 4
2212-
.comma { p.is_typename(tok2) } // case 5
2213-
// case 6 and 7
2214-
.dot { kind4 == .name && (kind5 == .gt || (kind5 == .comma && p.is_typename(tok4))) }
2215-
else { false }
2235+
if p.peek_tok.kind == .lt {
2236+
return match kind3 {
2237+
.gt { true } // case 3
2238+
.lt { !(tok4.lit.len == 1 && tok4.lit[0].is_capital()) } // case 4
2239+
.comma { p.is_typename(tok2) } // case 5
2240+
// case 6 and 7
2241+
.dot { kind4 == .name && (kind5 == .gt || (kind5 == .comma && p.is_typename(tok4))) }
2242+
else { false }
2243+
}
2244+
} else if p.peek_tok.kind == .lsbr {
2245+
mut i := 3
2246+
for {
2247+
cur_tok := p.peek_token(i)
2248+
if cur_tok.kind == .eof
2249+
|| cur_tok.kind !in [.amp, .dot, .comma, .name, .lsbr, .rsbr] {
2250+
break
2251+
}
2252+
if cur_tok.kind == .rsbr {
2253+
if p.peek_token(i + 1).kind == .lpar {
2254+
return true
2255+
}
2256+
break
2257+
}
2258+
i++
2259+
}
22162260
}
22172261
}
22182262
return false
@@ -2231,10 +2275,10 @@ fn (mut p Parser) is_generic_cast() bool {
22312275
i++
22322276
tok := p.peek_token(i)
22332277

2234-
if tok.kind == .lt {
2278+
if tok.kind in [.lt, .lsbr] {
22352279
lt_count++
22362280
level++
2237-
} else if tok.kind == .gt {
2281+
} else if tok.kind in [.gt, .rsbr] {
22382282
level--
22392283
}
22402284
if lt_count > 0 && level == 0 {
@@ -2414,6 +2458,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
24142458
is_optional := p.tok.kind == .question
24152459
is_generic_call := p.is_generic_call()
24162460
is_generic_cast := p.is_generic_cast()
2461+
is_generic_struct_init := p.is_generic_struct_init()
24172462
// p.warn('name expr $p.tok.lit $p.peek_tok.str()')
24182463
same_line := p.tok.line_nr == p.peek_tok.line_nr
24192464
// `(` must be on same line as name token otherwise it's a ParExpr
@@ -2494,7 +2539,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
24942539
}
24952540
}
24962541
}
2497-
} else if (p.peek_tok.kind == .lcbr || (p.peek_tok.kind == .lt && lit0_is_capital))
2542+
} else if (p.peek_tok.kind == .lcbr || is_generic_struct_init)
24982543
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
24992544
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
25002545
&& (!p.inside_for || p.inside_select) && !known_var {
@@ -2975,13 +3020,14 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
29753020
fn (mut p Parser) parse_generic_types() ([]ast.Type, []string) {
29763021
mut types := []ast.Type{}
29773022
mut param_names := []string{}
2978-
if p.tok.kind != .lt {
3023+
if p.tok.kind !in [.lt, .lsbr] {
29793024
return types, param_names
29803025
}
2981-
p.check(.lt)
3026+
end_kind := if p.tok.kind == .lt { token.Kind.gt } else { token.Kind.rsbr }
3027+
p.next()
29823028
mut first_done := false
29833029
mut count := 0
2984-
for p.tok.kind !in [.gt, .eof] {
3030+
for p.tok.kind !in [end_kind, .eof] {
29853031
if first_done {
29863032
p.check(.comma)
29873033
}
@@ -3018,25 +3064,26 @@ fn (mut p Parser) parse_generic_types() ([]ast.Type, []string) {
30183064
first_done = true
30193065
count++
30203066
}
3021-
p.check(.gt)
3067+
p.check(end_kind)
30223068
return types, param_names
30233069
}
30243070

30253071
fn (mut p Parser) parse_concrete_types() []ast.Type {
30263072
mut types := []ast.Type{}
3027-
if p.tok.kind != .lt {
3073+
if p.tok.kind !in [.lt, .lsbr] {
30283074
return types
30293075
}
3076+
end_kind := if p.tok.kind == .lt { token.Kind.gt } else { token.Kind.rsbr }
30303077
p.next() // `<`
30313078
mut first_done := false
3032-
for p.tok.kind !in [.eof, .gt] {
3079+
for p.tok.kind !in [.eof, end_kind] {
30333080
if first_done {
30343081
p.check(.comma)
30353082
}
30363083
types << p.parse_type()
30373084
first_done = true
30383085
}
3039-
p.check(.gt) // `>`
3086+
p.check(end_kind) // `>`
30403087
return types
30413088
}
30423089

0 commit comments

Comments
 (0)