1
2
3
4
5
6 #include <sngcpp/symbols/Scope.hpp>
7 #include <sngcpp/symbols/ContainerSymbol.hpp>
8 #include <sngcpp/ast/Visitor.hpp>
9 #include <sngcpp/ast/Expression.hpp>
10 #include <unordered_set>
11
12 namespace sngcpp { namespace symbols {
13
14 class NameResolver : public Visitor
15 {
16 public:
17 void Visit(IdentifierNode& identifierNode) override;
18 void Visit(NestedIdNode& nestedIdNode) override;
19 const std::std::vector<std::u32string>&NameSequence() const{returnnameSequence;}
20 private:
21 std::vector<std::u32string> nameSequence;
22 };
23
24 void NameResolver::Visit(IdentifierNode& identifierNode)
25 {
26 nameSequence.push_back(identifierNode.Identifier());
27 }
28
29 void NameResolver::Visit(NestedIdNode& nestedIdNode)
30 {
31 if (nestedIdNode.Left())
32 {
33 nestedIdNode.Left()->Accept(*this);
34 }
35 else
36 {
37 nameSequence.push_back(std::u32string());
38 }
39 nestedIdNode.Right()->Accept(*this);
40 }
41
42 Scope::Scope()
43 {
44 }
45
46 Scope::~Scope()
47 {
48 }
49
50 Symbol* Scope::Lookup(Node* nameNode)
51 {
52 return Lookup(nameNode, ScopeLookup::this_);
53 }
54
55 Symbol* Scope::Lookup(Node* nameNode, ScopeLookup scopeLookup)
56 {
57 NameResolver nameResolver;
58 nameNode->Accept(nameResolver);
59 if (nameResolver.NameSequence().empty())
60 {
61 return nullptr;
62 }
63 else if (nameResolver.NameSequence().size() == 1)
64 {
65 return Lookup(nameResolver.NameSequence().front(), scopeLookup);
66 }
67 else
68 {
69 return Lookup(nameResolver.NameSequence(), scopeLookup);
70 }
71 }
72
73 ContainerScope::ContainerScope() : container()
74 {
75 }
76
77 ContainerScope::ContainerScope(ContainerSymbol* container_) : container(container_)
78 {
79 }
80
81 ContainerSymbol* ContainerScope::GlobalNs()
82 {
83 ContainerSymbol* globalNs = container;
84 while (globalNs->Parent())
85 {
86 globalNs = globalNs->Parent();
87 }
88 return globalNs;
89 }
90
91 void ContainerScope::Install(Symbol* symbol)
92 {
93 symbolMap[symbol->Name()] = symbol;
94 }
95
96 Symbol* ContainerScope::Lookup(const std::u32string& name)
97 {
98 return Lookup(name, ScopeLookup::this_);
99 }
100
101 Symbol* ContainerScope::Lookup(const std::u32string& name, ScopeLookup scopeLookup)
102 {
103 auto it = symbolMap.find(name);
104 if (it != symbolMap.cend())
105 {
106 return it->second;
107 }
108 if ((scopeLookup & ScopeLookup::bases) != ScopeLookup::none)
109 {
110 int n = container->NumBases();
111 for (int i = 0; i < n; ++i)
112 {
113 ContainerSymbol* baseSymbol = container->GetBase(i);
114 ContainerScope* baseScope = baseSymbol->GetContainerScope();
115 Symbol* s = baseScope->Lookup(name, scopeLookup);
116 if (s)
117 {
118 return s;
119 }
120 }
121 }
122 if ((scopeLookup & ScopeLookup::parent) != ScopeLookup::none)
123 {
124 ContainerSymbol* parent = container->Parent();
125 if (parent)
126 {
127 ContainerScope* parentScope = parent->GetContainerScope();
128 Symbol* s = parentScope->Lookup(name, scopeLookup);
129 if (s)
130 {
131 return s;
132 }
133 }
134 }
135 return nullptr;
136 }
137
138 Symbol* ContainerScope::Lookup(const std::std::vector<std::u32string>&nameSequence, ScopeLookupscopeLoookup)
139 {
140 ContainerScope* scope = this;
141 Symbol* s = nullptr;
142 int n = nameSequence.size();
143 bool allComponentsMatched = true;
144 for (int i = 0; i < n; ++i)
145 {
146 const std::u32string& name = nameSequence[i];
147 if (name.empty())
148 {
149 scope = GlobalNs()->GetContainerScope();
150 }
151 else if (scope)
152 {
153 s = scope->Lookup(name, ScopeLookup::this_);
154 if (s)
155 {
156 scope = s->GetContainerScope();
157 }
158 else
159 {
160 allComponentsMatched = false;
161 }
162 }
163 }
164 if (!s || !allComponentsMatched)
165 {
166 if ((scopeLoookup & ScopeLookup::parent) != ScopeLookup::none)
167 {
168 ContainerSymbol* parent = container->Parent();
169 if (parent)
170 {
171 return parent->GetContainerScope()->Lookup(nameSequence, scopeLoookup);
172 }
173 else
174 {
175 return nullptr;
176 }
177 }
178 }
179 return s;
180 }
181
182 void FileScope::Install(ContainerScope* containerScope, UsingDirectiveNode& usingDirectiveNode)
183 {
184 Symbol* symbol = static_cast<Scope*>(containerScope)->Lookup(usingDirectiveNode.NamespaceName(), ScopeLookup::this_and_parent);
185 if (symbol)
186 {
187 if (symbol->IsNamespaceSymbol())
188 {
189 ContainerScope* containerScope = symbol->GetContainerScope();
190 if (containerScope)
191 {
192 for (ContainerScope* scope : containerScopes)
193 {
194 if (scope == containerScope) return;
195 }
196 containerScopes.push_back(containerScope);
197 }
198 else
199 {
200 throw std::runtime_error("container scope expected");
201 }
202 }
203 else
204 {
205 throw std::runtime_error("namespace symbol expected");
206 }
207 }
208 }
209
210 void FileScope::Install(ContainerScope* containerScope, UsingDeclarationNode& usingDeclarationNode)
211 {
212 Symbol* symbol = static_cast<Scope*>(containerScope)->Lookup(usingDeclarationNode.QualifiedId(), ScopeLookup::this_and_parent);
213 if (symbol)
214 {
215 aliasSymbolMap[symbol->Name()] = symbol;
216 }
217 }
218
219 Symbol* FileScope::Lookup(const std::u32string& name)
220 {
221 return Lookup(name, ScopeLookup::this_);
222 }
223
224 Symbol* FileScope::Lookup(const std::u32string& name, ScopeLookup scopeLookup)
225 {
226 if (scopeLookup != ScopeLookup::this_)
227 {
228 throw std::runtime_error("file scope supports only this scope lookup");
229 }
230 std::unordered_set<Symbol*> foundSymbols;
231 auto it = aliasSymbolMap.find(name);
232 if (it != aliasSymbolMap.cend())
233 {
234 Symbol* symbol = it->second;
235 foundSymbols.insert(symbol);
236 }
237 else
238 {
239 for (ContainerScope* containerScope : containerScopes)
240 {
241 Symbol* symbol = containerScope->Lookup(name, ScopeLookup::this_);
242 if (symbol)
243 {
244 foundSymbols.insert(symbol);
245 }
246 }
247 }
248 if (foundSymbols.empty())
249 {
250 return nullptr;
251 }
252 else if (foundSymbols.size() > 1)
253 {
254 return nullptr;
255 }
256 else
257 {
258 return *foundSymbols.begin();
259 }
260 }
261
262 Symbol* FileScope::Lookup(const std::std::vector<std::u32string>&nameSequence, ScopeLookupscopeLoookup)
263 {
264 std::unordered_set<Symbol*> foundSymbols;
265 for (ContainerScope* containerScope : containerScopes)
266 {
267 Symbol* symbol = containerScope->Lookup(nameSequence, ScopeLookup::this_);
268 if (symbol)
269 {
270 foundSymbols.insert(symbol);
271 }
272 }
273 if (foundSymbols.empty())
274 {
275 return nullptr;
276 }
277 else if (foundSymbols.size() > 1)
278 {
279 return nullptr;
280 }
281 else
282 {
283 return *foundSymbols.begin();
284 }
285 }
286
287 } }