Skip to content

Commit cb2756e

Browse files
authored
parser,checker: use keywords matcher trie for imported symbol presence checks, instead of x in p.imported_symbol (#25201)
1 parent 2ac3478 commit cb2756e

9 files changed

Lines changed: 41 additions & 16 deletions

File tree

‎vlib/v/ast/ast.v‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,9 +1019,10 @@ pub mut:
10191019
imports []Import // all the imports
10201020
auto_imports []string // imports that were implicitly added
10211021
used_imports []string
1022-
implied_imports []string // ​imports that the user's code uses but omitted to import explicitly, used by `vfmt`
1023-
embedded_files []EmbeddedFile // list of files to embed in the binary
1024-
imported_symbols map[string]string // used for `import {symbol}`, it maps symbol => module.symbol
1022+
implied_imports []string // ​imports that the user's code uses but omitted to import explicitly, used by `vfmt`
1023+
embedded_files []EmbeddedFile // list of files to embed in the binary
1024+
imported_symbols map[string]string // used for `import {symbol}`, it maps symbol => module.symbol
1025+
imported_symbols_trie token.KeywordsMatcherTrie // constructed from imported_symbols, to accelerate presense checks
10251026
imported_symbols_used map[string]bool
10261027
errors []errors.Error // all the checker errors in the file
10271028
warnings []errors.Warning // all the checker warnings in the file

‎vlib/v/checker/checker.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4261,7 +4261,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
42614261
}
42624262
mut name := node.name
42634263
// check for imported symbol
4264-
if name in c.file.imported_symbols {
4264+
if c.file.imported_symbols_trie.matches(name) {
42654265
name = c.file.imported_symbols[name]
42664266
}
42674267
// prepend mod to look for fn call or const

‎vlib/v/parser/enum.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
6161
end_pos)
6262
return ast.EnumDecl{}
6363
}
64-
if enum_name in p.imported_symbols {
64+
if p.is_imported_symbol(enum_name) {
6565
p.error_with_pos('cannot register enum `${enum_name}`, this type was already imported',
6666
end_pos)
6767
return ast.EnumDecl{}

‎vlib/v/parser/fn.v‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
8989
}
9090
or_kind = if is_not { .propagate_result } else { .propagate_option }
9191
}
92-
if fn_name in p.imported_symbols {
92+
if p.is_imported_symbol(fn_name) {
9393
check := !p.imported_symbols_used[fn_name]
9494
fn_name = p.imported_symbols[fn_name]
9595
if check {
@@ -152,7 +152,7 @@ fn (mut p Parser) call_args() []ast.CallArg {
152152
} else {
153153
expr = p.expr(0)
154154
if mut expr is ast.Ident {
155-
if expr.name in p.imported_symbols && !p.imported_symbols_used[expr.name] {
155+
if p.is_imported_symbol(expr.name) && !p.imported_symbols_used[expr.name] {
156156
// func call arg is another function call
157157
// import term { bright_cyan, colorize } ... colorize(bright_cyan, 'hello')
158158
p.register_used_import_for_symbol_name(p.imported_symbols[expr.name])
@@ -393,7 +393,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
393393
}
394394
}
395395
if !p.pref.is_fmt {
396-
if name in p.imported_symbols {
396+
if p.is_imported_symbol(name) {
397397
p.error_with_pos('cannot redefine imported function `${name}`', name_pos)
398398
return ast.FnDecl{
399399
scope: unsafe { nil }

‎vlib/v/parser/module.v‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn (mut p Parser) register_used_import(alias string) {
3636
fn (mut p Parser) register_used_import_for_symbol_name(sym_name string) {
3737
short_import_name := sym_name.all_before_last('.').all_after_last('.')
3838
short_symbol_name := sym_name.all_after_last('.')
39-
if short_symbol_name in p.imported_symbols {
39+
if p.is_imported_symbol(short_symbol_name) {
4040
p.imported_symbols_used[short_symbol_name] = true
4141
}
4242
for alias, mod in p.imports {
@@ -322,12 +322,13 @@ fn (mut p Parser) import_syms(mut parent ast.Import) {
322322
for p.tok.kind == .name {
323323
pos := p.tok.pos()
324324
alias := p.check_name()
325-
if alias in p.imported_symbols {
325+
if p.is_imported_symbol(alias) {
326326
p.error_with_pos('cannot register symbol `${alias}`, it was already imported',
327327
pos)
328328
return
329329
}
330330
p.imported_symbols[alias] = parent.mod + '.' + alias
331+
p.rebuild_imported_symbols_matcher(alias)
331332
// so we can work with this in fmt+checker
332333
parent.syms << ast.ImportSymbol{
333334
pos: pos
@@ -347,3 +348,12 @@ fn (mut p Parser) import_syms(mut parent ast.Import) {
347348
}
348349
p.next()
349350
}
351+
352+
fn (mut p Parser) rebuild_imported_symbols_matcher(name string) {
353+
p.imported_symbols_trie = token.new_keywords_matcher_from_array_trie(p.imported_symbols.keys())
354+
}
355+
356+
@[inline]
357+
fn (mut p Parser) is_imported_symbol(name string) bool {
358+
return p.imported_symbols_trie.matches(name)
359+
}

‎vlib/v/parser/parse_type.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_dot b
636636
} else if p.expr_mod != '' && !p.inside_generic_params {
637637
// p.expr_mod is from the struct and not from the generic parameter
638638
name = p.expr_mod + '.' + name
639-
} else if name in p.imported_symbols {
639+
} else if p.is_imported_symbol(name) {
640640
check := !p.imported_symbols_used[name]
641641
name = p.imported_symbols[name]
642642
if check {

‎vlib/v/parser/parser.v‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ mut:
8686
implied_imports []string // ​imports that the user's code uses but omitted to import explicitly, used by `vfmt`
8787
imported_symbols map[string]string
8888
imported_symbols_used map[string]bool
89+
imported_symbols_trie token.KeywordsMatcherTrie
8990
is_amp bool // for generating the right code for `&Foo{}`
9091
returns bool
9192
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
@@ -343,6 +344,7 @@ pub fn (mut p Parser) parse() &ast.File {
343344
mod: module_decl
344345
imports: p.ast_imports
345346
imported_symbols: p.imported_symbols
347+
imported_symbols_trie: token.new_keywords_matcher_from_array_trie(p.imported_symbols.keys())
346348
imported_symbols_used: p.imported_symbols_used
347349
auto_imports: p.auto_imports
348350
used_imports: p.used_imports
@@ -592,8 +594,7 @@ fn (mut p Parser) check_name() string {
592594
name := p.tok.lit
593595
if p.tok.kind != .name && p.peek_tok.kind == .dot && name in p.imports {
594596
p.register_used_import(name)
595-
} else if p.tok.kind == .name && p.peek_tok.kind == .dot && name in p.imported_symbols
596-
&& !p.imported_symbols_used[name] {
597+
} else if p.tok.kind == .name && p.is_imported_symbol(name) && !p.imported_symbols_used[name] {
597598
// symbols like Enum.field_name
598599
p.register_used_import_for_symbol_name(p.imported_symbols[name])
599600
}
@@ -2698,7 +2699,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
26982699
return ast.FnTypeDecl{}
26992700
}
27002701
}
2701-
if name in p.imported_symbols {
2702+
if p.is_imported_symbol(name) {
27022703
p.error_with_pos('cannot register alias `${name}`, this type was already imported',
27032704
end_pos)
27042705
return ast.AliasTypeDecl{}

‎vlib/v/parser/struct.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
7373
p.error_with_pos('struct names must have more than one character', name_pos)
7474
return ast.StructDecl{}
7575
}
76-
if name in p.imported_symbols {
76+
if p.is_imported_symbol(name) {
7777
p.error_with_pos('cannot register struct `${name}`, this type was already imported',
7878
name_pos)
7979
return ast.StructDecl{}
@@ -651,7 +651,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
651651
mut pre_comments := p.eat_comments()
652652
p.check(.lcbr)
653653
pre_comments << p.eat_comments()
654-
if modless_name in p.imported_symbols {
654+
if p.is_imported_symbol(modless_name) {
655655
p.error_with_pos('cannot register interface `${interface_name}`, this type was already imported',
656656
name_pos)
657657
return ast.InterfaceDecl{}

‎vlib/v/token/keywords_matcher_trie.v‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,26 @@ pub mut:
1111
max_len int
1212
}
1313

14+
// str returns a short representation of matcher
15+
pub fn (km &KeywordsMatcherTrie) str() string {
16+
return 'KeywordsMatcherTrie{ /* nodes.len: ${km.nodes.len} */ min_len: ${km.min_len}, max_len: ${km.max_len} }'
17+
}
18+
1419
// TrieNode is a single node from a trie, used by KeywordsMatcherTrie
1520
pub struct TrieNode {
1621
pub mut:
1722
children [123]&TrieNode
1823
value int = -1 // when != -1, it is a leaf node representing a match
1924
}
2025

26+
// str returns a string representation of the node content
27+
pub fn (node &TrieNode) str() string {
28+
if isnil(node) {
29+
return '&TrieNode(nil)'
30+
}
31+
return '&TrieNode{value: ${node.value}}'
32+
}
33+
2134
// find tries to find the given `word` in the set of all previously added words
2235
// to the KeywordsMatcherTrie instance. It returns -1 if the word was NOT found
2336
// there at all. If the word was found, find will return the `value` (value => 0),

0 commit comments

Comments
 (0)