11from dataclasses import dataclass , field
2+ from itertools import chain
23from typing import TypeVar , Generic , Optional , List , Dict
34
45
@@ -33,14 +34,14 @@ def __hash__(self):
3334 def resolved (self ):
3435 return self .referred is not None
3536
36- def resolve (self , scope : 'Scope' ) -> bool :
37- self .referred = scope .lookup (symbol_name = self .name )
37+ def resolve (self , scope : 'Scope' , case_insensitive : bool = False ) -> bool :
38+ self .referred = scope .lookup (symbol_name = self .name , case_insensitive = case_insensitive )
3839 return self .resolved ()
3940
4041 def try_to_resolve (self , candidates : List [T ], case_insensitive : bool = False ) -> bool :
4142 """
4243 Try to resolve the reference by finding a named element with a matching name.
43- The name match is performed in a case sensitive or insensitive way depending on the value of caseInsensitive .
44+ The name match is performed in a case sensitive or insensitive way depending on the value of case_insensitive .
4445 """
4546
4647 def check_name (candidate : T ) -> bool :
@@ -60,10 +61,36 @@ class Symbol(PossiblyNamed):
6061class Scope :
6162 symbols : Dict [str , List [Symbol ]] = field (default_factory = list )
6263 parent : Optional ['Scope' ] = field (default = None )
64+ insensitive_map : Optional [Dict [str , List [str ]]] = field (default = None )
65+
66+ def lookup (self , symbol_name : str , symbol_type : type = Symbol , case_insensitive : bool = False ) -> Optional [Symbol ]:
67+ if case_insensitive :
68+ if self .insensitive_map is None :
69+ self .insensitive_map = {}
70+ for key in self .symbols .keys ():
71+ key_lower : str = key .lower ()
72+ self .insensitive_map [key_lower ] = self .insensitive_map .get (key_lower , []) + [key ]
73+
74+ symbol_name_lower : str = symbol_name .lower ()
75+
76+ return next (
77+ (
78+ symbol
79+ for symbol in chain .from_iterable (
80+ self .symbols .get (orig_symbol_name , [])
81+ for orig_symbol_name in self .insensitive_map [symbol_name_lower ]
82+ )
83+ if isinstance (symbol , symbol_type )
84+ ),
85+ self .parent .lookup (symbol_name , symbol_type ) if self .parent is not None else None
86+ )
6387
64- def lookup (self , symbol_name : str , symbol_type : type = Symbol ) -> Optional [Symbol ]:
6588 return next ((symbol for symbol in self .symbols .get (symbol_name , []) if isinstance (symbol , symbol_type )),
6689 self .parent .lookup (symbol_name , symbol_type ) if self .parent is not None else None )
6790
6891 def add (self , symbol : Symbol ):
6992 self .symbols [symbol .name ] = self .symbols .get (symbol .name , []) + [symbol ]
93+
94+ if self .insensitive_map is not None :
95+ symbol_name_lower : str = symbol .name .lower ()
96+ self .insensitive_map [symbol_name_lower ] = self .insensitive_map .get (symbol_name_lower , []) + [symbol .name ]
0 commit comments