mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
parser,checker: use keywords matcher trie for imported symbol presence checks, instead of x in p.imported_symbol
(#25201)
This commit is contained in:
parent
2ac3478296
commit
cb2756e39c
9 changed files with 41 additions and 16 deletions
|
@ -1022,6 +1022,7 @@ pub mut:
|
||||||
implied_imports []string // imports that the user's code uses but omitted to import explicitly, used by `vfmt`
|
implied_imports []string // imports that the user's code uses but omitted to import explicitly, used by `vfmt`
|
||||||
embedded_files []EmbeddedFile // list of files to embed in the binary
|
embedded_files []EmbeddedFile // list of files to embed in the binary
|
||||||
imported_symbols map[string]string // used for `import {symbol}`, it maps symbol => module.symbol
|
imported_symbols map[string]string // used for `import {symbol}`, it maps symbol => module.symbol
|
||||||
|
imported_symbols_trie token.KeywordsMatcherTrie // constructed from imported_symbols, to accelerate presense checks
|
||||||
imported_symbols_used map[string]bool
|
imported_symbols_used map[string]bool
|
||||||
errors []errors.Error // all the checker errors in the file
|
errors []errors.Error // all the checker errors in the file
|
||||||
warnings []errors.Warning // all the checker warnings in the file
|
warnings []errors.Warning // all the checker warnings in the file
|
||||||
|
|
|
@ -4261,7 +4261,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||||
}
|
}
|
||||||
mut name := node.name
|
mut name := node.name
|
||||||
// check for imported symbol
|
// check for imported symbol
|
||||||
if name in c.file.imported_symbols {
|
if c.file.imported_symbols_trie.matches(name) {
|
||||||
name = c.file.imported_symbols[name]
|
name = c.file.imported_symbols[name]
|
||||||
}
|
}
|
||||||
// prepend mod to look for fn call or const
|
// prepend mod to look for fn call or const
|
||||||
|
|
|
@ -61,7 +61,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||||
end_pos)
|
end_pos)
|
||||||
return ast.EnumDecl{}
|
return ast.EnumDecl{}
|
||||||
}
|
}
|
||||||
if enum_name in p.imported_symbols {
|
if p.is_imported_symbol(enum_name) {
|
||||||
p.error_with_pos('cannot register enum `${enum_name}`, this type was already imported',
|
p.error_with_pos('cannot register enum `${enum_name}`, this type was already imported',
|
||||||
end_pos)
|
end_pos)
|
||||||
return ast.EnumDecl{}
|
return ast.EnumDecl{}
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
|
||||||
}
|
}
|
||||||
or_kind = if is_not { .propagate_result } else { .propagate_option }
|
or_kind = if is_not { .propagate_result } else { .propagate_option }
|
||||||
}
|
}
|
||||||
if fn_name in p.imported_symbols {
|
if p.is_imported_symbol(fn_name) {
|
||||||
check := !p.imported_symbols_used[fn_name]
|
check := !p.imported_symbols_used[fn_name]
|
||||||
fn_name = p.imported_symbols[fn_name]
|
fn_name = p.imported_symbols[fn_name]
|
||||||
if check {
|
if check {
|
||||||
|
@ -152,7 +152,7 @@ fn (mut p Parser) call_args() []ast.CallArg {
|
||||||
} else {
|
} else {
|
||||||
expr = p.expr(0)
|
expr = p.expr(0)
|
||||||
if mut expr is ast.Ident {
|
if mut expr is ast.Ident {
|
||||||
if expr.name in p.imported_symbols && !p.imported_symbols_used[expr.name] {
|
if p.is_imported_symbol(expr.name) && !p.imported_symbols_used[expr.name] {
|
||||||
// func call arg is another function call
|
// func call arg is another function call
|
||||||
// import term { bright_cyan, colorize } ... colorize(bright_cyan, 'hello')
|
// import term { bright_cyan, colorize } ... colorize(bright_cyan, 'hello')
|
||||||
p.register_used_import_for_symbol_name(p.imported_symbols[expr.name])
|
p.register_used_import_for_symbol_name(p.imported_symbols[expr.name])
|
||||||
|
@ -393,7 +393,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !p.pref.is_fmt {
|
if !p.pref.is_fmt {
|
||||||
if name in p.imported_symbols {
|
if p.is_imported_symbol(name) {
|
||||||
p.error_with_pos('cannot redefine imported function `${name}`', name_pos)
|
p.error_with_pos('cannot redefine imported function `${name}`', name_pos)
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
scope: unsafe { nil }
|
scope: unsafe { nil }
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn (mut p Parser) register_used_import(alias string) {
|
||||||
fn (mut p Parser) register_used_import_for_symbol_name(sym_name string) {
|
fn (mut p Parser) register_used_import_for_symbol_name(sym_name string) {
|
||||||
short_import_name := sym_name.all_before_last('.').all_after_last('.')
|
short_import_name := sym_name.all_before_last('.').all_after_last('.')
|
||||||
short_symbol_name := sym_name.all_after_last('.')
|
short_symbol_name := sym_name.all_after_last('.')
|
||||||
if short_symbol_name in p.imported_symbols {
|
if p.is_imported_symbol(short_symbol_name) {
|
||||||
p.imported_symbols_used[short_symbol_name] = true
|
p.imported_symbols_used[short_symbol_name] = true
|
||||||
}
|
}
|
||||||
for alias, mod in p.imports {
|
for alias, mod in p.imports {
|
||||||
|
@ -322,12 +322,13 @@ fn (mut p Parser) import_syms(mut parent ast.Import) {
|
||||||
for p.tok.kind == .name {
|
for p.tok.kind == .name {
|
||||||
pos := p.tok.pos()
|
pos := p.tok.pos()
|
||||||
alias := p.check_name()
|
alias := p.check_name()
|
||||||
if alias in p.imported_symbols {
|
if p.is_imported_symbol(alias) {
|
||||||
p.error_with_pos('cannot register symbol `${alias}`, it was already imported',
|
p.error_with_pos('cannot register symbol `${alias}`, it was already imported',
|
||||||
pos)
|
pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.imported_symbols[alias] = parent.mod + '.' + alias
|
p.imported_symbols[alias] = parent.mod + '.' + alias
|
||||||
|
p.rebuild_imported_symbols_matcher(alias)
|
||||||
// so we can work with this in fmt+checker
|
// so we can work with this in fmt+checker
|
||||||
parent.syms << ast.ImportSymbol{
|
parent.syms << ast.ImportSymbol{
|
||||||
pos: pos
|
pos: pos
|
||||||
|
@ -347,3 +348,12 @@ fn (mut p Parser) import_syms(mut parent ast.Import) {
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut p Parser) rebuild_imported_symbols_matcher(name string) {
|
||||||
|
p.imported_symbols_trie = token.new_keywords_matcher_from_array_trie(p.imported_symbols.keys())
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut p Parser) is_imported_symbol(name string) bool {
|
||||||
|
return p.imported_symbols_trie.matches(name)
|
||||||
|
}
|
||||||
|
|
|
@ -636,7 +636,7 @@ fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_dot b
|
||||||
} else if p.expr_mod != '' && !p.inside_generic_params {
|
} else if p.expr_mod != '' && !p.inside_generic_params {
|
||||||
// p.expr_mod is from the struct and not from the generic parameter
|
// p.expr_mod is from the struct and not from the generic parameter
|
||||||
name = p.expr_mod + '.' + name
|
name = p.expr_mod + '.' + name
|
||||||
} else if name in p.imported_symbols {
|
} else if p.is_imported_symbol(name) {
|
||||||
check := !p.imported_symbols_used[name]
|
check := !p.imported_symbols_used[name]
|
||||||
name = p.imported_symbols[name]
|
name = p.imported_symbols[name]
|
||||||
if check {
|
if check {
|
||||||
|
|
|
@ -86,6 +86,7 @@ mut:
|
||||||
implied_imports []string // imports that the user's code uses but omitted to import explicitly, used by `vfmt`
|
implied_imports []string // imports that the user's code uses but omitted to import explicitly, used by `vfmt`
|
||||||
imported_symbols map[string]string
|
imported_symbols map[string]string
|
||||||
imported_symbols_used map[string]bool
|
imported_symbols_used map[string]bool
|
||||||
|
imported_symbols_trie token.KeywordsMatcherTrie
|
||||||
is_amp bool // for generating the right code for `&Foo{}`
|
is_amp bool // for generating the right code for `&Foo{}`
|
||||||
returns bool
|
returns bool
|
||||||
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
|
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 {
|
||||||
mod: module_decl
|
mod: module_decl
|
||||||
imports: p.ast_imports
|
imports: p.ast_imports
|
||||||
imported_symbols: p.imported_symbols
|
imported_symbols: p.imported_symbols
|
||||||
|
imported_symbols_trie: token.new_keywords_matcher_from_array_trie(p.imported_symbols.keys())
|
||||||
imported_symbols_used: p.imported_symbols_used
|
imported_symbols_used: p.imported_symbols_used
|
||||||
auto_imports: p.auto_imports
|
auto_imports: p.auto_imports
|
||||||
used_imports: p.used_imports
|
used_imports: p.used_imports
|
||||||
|
@ -592,8 +594,7 @@ fn (mut p Parser) check_name() string {
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
if p.tok.kind != .name && p.peek_tok.kind == .dot && name in p.imports {
|
if p.tok.kind != .name && p.peek_tok.kind == .dot && name in p.imports {
|
||||||
p.register_used_import(name)
|
p.register_used_import(name)
|
||||||
} else if p.tok.kind == .name && p.peek_tok.kind == .dot && name in p.imported_symbols
|
} else if p.tok.kind == .name && p.is_imported_symbol(name) && !p.imported_symbols_used[name] {
|
||||||
&& !p.imported_symbols_used[name] {
|
|
||||||
// symbols like Enum.field_name
|
// symbols like Enum.field_name
|
||||||
p.register_used_import_for_symbol_name(p.imported_symbols[name])
|
p.register_used_import_for_symbol_name(p.imported_symbols[name])
|
||||||
}
|
}
|
||||||
|
@ -2698,7 +2699,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
return ast.FnTypeDecl{}
|
return ast.FnTypeDecl{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if name in p.imported_symbols {
|
if p.is_imported_symbol(name) {
|
||||||
p.error_with_pos('cannot register alias `${name}`, this type was already imported',
|
p.error_with_pos('cannot register alias `${name}`, this type was already imported',
|
||||||
end_pos)
|
end_pos)
|
||||||
return ast.AliasTypeDecl{}
|
return ast.AliasTypeDecl{}
|
||||||
|
|
|
@ -73,7 +73,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
|
||||||
p.error_with_pos('struct names must have more than one character', name_pos)
|
p.error_with_pos('struct names must have more than one character', name_pos)
|
||||||
return ast.StructDecl{}
|
return ast.StructDecl{}
|
||||||
}
|
}
|
||||||
if name in p.imported_symbols {
|
if p.is_imported_symbol(name) {
|
||||||
p.error_with_pos('cannot register struct `${name}`, this type was already imported',
|
p.error_with_pos('cannot register struct `${name}`, this type was already imported',
|
||||||
name_pos)
|
name_pos)
|
||||||
return ast.StructDecl{}
|
return ast.StructDecl{}
|
||||||
|
@ -651,7 +651,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
mut pre_comments := p.eat_comments()
|
mut pre_comments := p.eat_comments()
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
pre_comments << p.eat_comments()
|
pre_comments << p.eat_comments()
|
||||||
if modless_name in p.imported_symbols {
|
if p.is_imported_symbol(modless_name) {
|
||||||
p.error_with_pos('cannot register interface `${interface_name}`, this type was already imported',
|
p.error_with_pos('cannot register interface `${interface_name}`, this type was already imported',
|
||||||
name_pos)
|
name_pos)
|
||||||
return ast.InterfaceDecl{}
|
return ast.InterfaceDecl{}
|
||||||
|
|
|
@ -11,6 +11,11 @@ pub mut:
|
||||||
max_len int
|
max_len int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// str returns a short representation of matcher
|
||||||
|
pub fn (km &KeywordsMatcherTrie) str() string {
|
||||||
|
return 'KeywordsMatcherTrie{ /* nodes.len: ${km.nodes.len} */ min_len: ${km.min_len}, max_len: ${km.max_len} }'
|
||||||
|
}
|
||||||
|
|
||||||
// TrieNode is a single node from a trie, used by KeywordsMatcherTrie
|
// TrieNode is a single node from a trie, used by KeywordsMatcherTrie
|
||||||
pub struct TrieNode {
|
pub struct TrieNode {
|
||||||
pub mut:
|
pub mut:
|
||||||
|
@ -18,6 +23,14 @@ pub mut:
|
||||||
value int = -1 // when != -1, it is a leaf node representing a match
|
value int = -1 // when != -1, it is a leaf node representing a match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// str returns a string representation of the node content
|
||||||
|
pub fn (node &TrieNode) str() string {
|
||||||
|
if isnil(node) {
|
||||||
|
return '&TrieNode(nil)'
|
||||||
|
}
|
||||||
|
return '&TrieNode{value: ${node.value}}'
|
||||||
|
}
|
||||||
|
|
||||||
// find tries to find the given `word` in the set of all previously added words
|
// find tries to find the given `word` in the set of all previously added words
|
||||||
// to the KeywordsMatcherTrie instance. It returns -1 if the word was NOT found
|
// to the KeywordsMatcherTrie instance. It returns -1 if the word was NOT found
|
||||||
// there at all. If the word was found, find will return the `value` (value => 0),
|
// there at all. If the word was found, find will return the `value` (value => 0),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue