1
2
3
4
5
6 #include <cmajor/symbols/ContainerSymbol.hpp>
7 #include <cmajor/symbols/FunctionSymbol.hpp>
8 #include <cmajor/symbols/VariableSymbol.hpp>
9 #include <cmajor/symbols/SymbolTable.hpp>
10 #include <cmajor/symbols/SymbolWriter.hpp>
11 #include <cmajor/symbols/SymbolReader.hpp>
12 #include <cmajor/symbols/Module.hpp>
13 #include <cmajor/symbols/Exception.hpp>
14 #include <cmajor/symbols/ConceptSymbol.hpp>
15 #include <cmajor/symbols/DebugFlags.hpp>
16 #include <soulng/util/Unicode.hpp>
17
18 namespace cmajor { namespace symbols {
19
20 using namespace soulng::unicode;
21
22 ContainerSymbol::ContainerSymbol(SymbolType symbolType_, const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) : Symbol(symbolType_, span_, sourceModuleId_, name_)
23 {
24 containerScope.SetContainer(this);
25 }
26
27 void ContainerSymbol::Write(SymbolWriter& writer)
28 {
29 Symbol::Write(writer);
30 std::vector<Symbol*> exportSymbols;
31 for (const std::std::unique_ptr<Symbol>&member : members)
32 {
33 if (member->IsExportSymbol())
34 {
35 exportSymbols.push_back(member.get());
36 }
37 }
38 uint32_t n = uint32_t(exportSymbols.size());
39 writer.GetBinaryWriter().WriteULEB128UInt(n);
40 for (uint32_t i = 0; i < n; ++i)
41 {
42 writer.Write(exportSymbols[i]);
43 }
44 }
45
46 void ContainerSymbol::Read(SymbolReader& reader)
47 {
48 Symbol::Read(reader);
49 uint32_t n = reader.GetBinaryReader().ReadULEB128UInt();
50 for (uint32_t i = 0; i < n; ++i)
51 {
52 Symbol* symbol = reader.ReadSymbol(this);
53 AddMember(symbol);
54 }
55 }
56
57 void ContainerSymbol::AddMember(Symbol* member)
58 {
59 #ifdef IMMUTABLE_MODULE_CHECK
60
61
62
63
64 #endif
65 if (IsImmutable())
66 {
67 throw ModuleImmutableException(GetRootModuleForCurrentThread(), GetModule(), GetSpan(), member->GetSpan());
68 }
69 if (GetModule())
70 {
71 member->SetModule(GetModule());
72 }
73 member->SetParent(this);
74 member->SetSymbolIndex(members.size());
75 members.push_back(std::unique_ptr<Symbol>(member));
76 if (member->IsFunctionSymbol())
77 {
78 FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(member);
79 FunctionGroupSymbol* functionGroupSymbol = MakeFunctionGroupSymbol(functionSymbol->GroupName(), functionSymbol->GetSpan(), functionSymbol->SourceModuleId());
80 functionGroupSymbol->AddFunction(functionSymbol);
81 functionIndexMap[functionSymbol->GetIndex()] = functionSymbol;
82 }
83 else if (member->GetSymbolType() == SymbolType::conceptSymbol)
84 {
85 ConceptSymbol* conceptSymbol = static_cast<ConceptSymbol*>(member);
86 ConceptGroupSymbol* conceptGroupSymbol = MakeConceptGroupSymbol(conceptSymbol->GroupName(), conceptSymbol->GetSpan(), conceptSymbol->SourceModuleId());
87 conceptGroupSymbol->AddConcept(conceptSymbol);
88 }
89 else if (member->GetSymbolType() == SymbolType::classTypeSymbol || member->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
90 {
91 ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(member);
92 ClassGroupTypeSymbol* classGroupTypeSymbol = MakeClassGroupTypeSymbol(classTypeSymbol->GroupName(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
93 classGroupTypeSymbol->AddClass(classTypeSymbol);
94 }
95 else if (member->GetSymbolType() == SymbolType::globalVariableSymbol)
96 {
97 GlobalVariableSymbol* globalVariableSymbol = static_cast<GlobalVariableSymbol*>(member);
98 GlobalVariableGroupSymbol* globalVariableGroupSymbol = MakeGlobalVariableGroupSymbol(globalVariableSymbol->GroupName(), globalVariableSymbol->GetSpan(), globalVariableSymbol->SourceModuleId());
99 globalVariableGroupSymbol->AddGlobalVariable(globalVariableSymbol);
100 }
101 else
102 {
103 containerScope.Install(member);
104 }
105 }
106
107 void ContainerSymbol::AddOwnedMember(Symbol* ownedMember)
108 {
109 if (ownedMember->IsFunctionSymbol())
110 {
111 FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(ownedMember);
112 FunctionGroupSymbol* functionGroupSymbol = MakeFunctionGroupSymbol(functionSymbol->GroupName(), functionSymbol->GetSpan(), functionSymbol->SourceModuleId());
113 functionGroupSymbol->AddFunction(functionSymbol);
114 functionIndexMap[functionSymbol->GetIndex()] = functionSymbol;
115 }
116 else if (ownedMember->GetSymbolType() == SymbolType::conceptSymbol)
117 {
118 ConceptSymbol* conceptSymbol = static_cast<ConceptSymbol*>(ownedMember);
119 ConceptGroupSymbol* conceptGroupSymbol = MakeConceptGroupSymbol(conceptSymbol->GroupName(), conceptSymbol->GetSpan(), conceptSymbol->SourceModuleId());
120 conceptGroupSymbol->AddConcept(conceptSymbol);
121 }
122 else if (ownedMember->GetSymbolType() == SymbolType::classTypeSymbol || ownedMember->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
123 {
124 ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(ownedMember);
125 ClassGroupTypeSymbol* classGroupTypeSymbol = MakeClassGroupTypeSymbol(classTypeSymbol->GroupName(), classTypeSymbol->GetSpan(), classTypeSymbol->SourceModuleId());
126 classGroupTypeSymbol->AddClass(classTypeSymbol);
127 }
128 else if (ownedMember->GetSymbolType() == SymbolType::globalVariableSymbol)
129 {
130 GlobalVariableSymbol* globalVariableSymbol = static_cast<GlobalVariableSymbol*>(ownedMember);
131 GlobalVariableGroupSymbol* globalVariableGroupSymbol = MakeGlobalVariableGroupSymbol(globalVariableSymbol->GroupName(), globalVariableSymbol->GetSpan(), globalVariableSymbol->SourceModuleId());
132 globalVariableGroupSymbol->AddGlobalVariable(globalVariableSymbol);
133 }
134 else
135 {
136 containerScope.Install(ownedMember);
137 }
138 }
139
140 std::std::unique_ptr<Symbol>ContainerSymbol::RemoveMember(intsymbolIndex)
141 {
142 if (symbolIndex == -1)
143 {
144 throw std::runtime_error("internal error: ContainerSymboil::RemoveMember(): symbol index is -1");
145 }
146 std::unique_ptr<Symbol> symbol = std::move(members[symbolIndex]);
147 members.erase(members.begin() + symbolIndex);
148 for (int i = symbolIndex; i < members.size(); ++i)
149 {
150 members[i]->SetSymbolIndex(i);
151 }
152 if (symbol->IsInstalled())
153 {
154 containerScope.Uninstall(symbol.get());
155 }
156 return symbol;
157 }
158
159 void ContainerSymbol::Accept(SymbolCollector* collector)
160 {
161 if (IsProject())
162 {
163 for (std::std::unique_ptr<Symbol>&member : members)
164 {
165 member->Accept(collector);
166 }
167 }
168 }
169
170 void ContainerSymbol::Clear()
171 {
172 containerScope.Clear();
173 members.clear();
174 }
175
176 FunctionGroupSymbol* ContainerSymbol::MakeFunctionGroupSymbol(const std::u32string& groupName, const Span& span, const boost::uuids::uuid& sourceModuleId)
177 {
178 Symbol* symbol = containerScope.Lookup(groupName);
179 if (!symbol)
180 {
181 FunctionGroupSymbol* functionGroupSymbol = new FunctionGroupSymbol(span, sourceModuleId, groupName);
182 AddMember(functionGroupSymbol);
183 return functionGroupSymbol;
184 }
185 if (symbol->GetSymbolType() == SymbolType::functionGroupSymbol)
186 {
187 return static_cast<FunctionGroupSymbol*>(symbol);
188 }
189 else
190 {
191 throw Exception("name of symbol '" + ToUtf8(symbol->FullName()) + "' conflicts with a function group '" + ToUtf8(groupName) + "'", symbol->GetSpan(), symbol->SourceModuleId(), span, sourceModuleId);
192 }
193 }
194
195 ConceptGroupSymbol* ContainerSymbol::MakeConceptGroupSymbol(const std::u32string& groupName, const Span& span, const boost::uuids::uuid& sourceModuleId)
196 {
197 Symbol* symbol = containerScope.Lookup(groupName);
198 if (!symbol)
199 {
200 ConceptGroupSymbol* conceptGroupSymbol = new ConceptGroupSymbol(span, sourceModuleId, groupName);
201 AddMember(conceptGroupSymbol);
202 return conceptGroupSymbol;
203 }
204 if (symbol->GetSymbolType() == SymbolType::conceptGroupSymbol)
205 {
206 return static_cast<ConceptGroupSymbol*>(symbol);
207 }
208 else
209 {
210 throw Exception("name of symbol '" + ToUtf8(symbol->FullName()) + "' conflicts with a concept group '" + ToUtf8(groupName) + "'", symbol->GetSpan(), symbol->SourceModuleId(), span, sourceModuleId);
211 }
212 }
213
214 ClassGroupTypeSymbol* ContainerSymbol::MakeClassGroupTypeSymbol(const std::u32string& groupName, const Span& span, const boost::uuids::uuid& sourceModuleId)
215 {
216 Symbol* symbol = containerScope.Lookup(groupName);
217 if (!symbol)
218 {
219 ClassGroupTypeSymbol* classGroupTypeSymbol = new ClassGroupTypeSymbol(span, sourceModuleId, groupName);
220 GetRootModuleForCurrentThread()->GetSymbolTable().SetTypeIdFor(classGroupTypeSymbol);
221 AddMember(classGroupTypeSymbol);
222 return classGroupTypeSymbol;
223 }
224 if (symbol->GetSymbolType() == SymbolType::classGroupTypeSymbol)
225 {
226 return static_cast<ClassGroupTypeSymbol*>(symbol);
227 }
228 else
229 {
230 throw Exception("name of symbol '" + ToUtf8(symbol->FullName()) + "' conflicts with a class group '" + ToUtf8(groupName) + "'", symbol->GetSpan(), symbol->SourceModuleId(), span, sourceModuleId);
231 }
232 }
233
234 GlobalVariableGroupSymbol* ContainerSymbol::MakeGlobalVariableGroupSymbol(const std::u32string& groupName, const Span& span, const boost::uuids::uuid& sourceModuleId)
235 {
236 Symbol* symbol = containerScope.Lookup(groupName);
237 if (!symbol)
238 {
239 GlobalVariableGroupSymbol* globalVariableGroupSymbol = new GlobalVariableGroupSymbol(span, sourceModuleId, groupName);
240 AddMember(globalVariableGroupSymbol);
241 return globalVariableGroupSymbol;
242 }
243 if (symbol->GetSymbolType() == SymbolType::globalVariableGroupSymbol)
244 {
245 return static_cast<GlobalVariableGroupSymbol*>(symbol);
246 }
247 else
248 {
249 throw Exception("name of symbol '" + ToUtf8(symbol->FullName()) + "' conflicts with a global variable group '" + ToUtf8(groupName) + "'", symbol->GetSpan(), symbol->SourceModuleId(), span, sourceModuleId);
250 }
251 }
252
253 void ContainerSymbol::AppendChildElements(sngxml::dom::Element* element, TypeMap& typeMap) const
254 {
255 for (const std::std::unique_ptr<Symbol>&member : members)
256 {
257 if (member->IsFunctionSymbol()) continue;
258 if (member->IsClassTypeSymbol()) continue;
259 if (member->GetSymbolType() == SymbolType::conceptSymbol) continue;
260 if (member->GetSymbolType() == SymbolType::globalVariableSymbol) continue;
261 if (member->GetSymbolType() != SymbolType::namespaceSymbol && !member->IsProject()) continue;
262 if (member->GetSymbolType() == SymbolType::namespaceSymbol ||
263 member->GetSymbolType() == SymbolType::classGroupTypeSymbol ||
264 member->GetSymbolType() == SymbolType::functionGroupSymbol ||
265 member->GetSymbolType() == SymbolType::conceptGroupSymbol ||
266 member->GetSymbolType() == SymbolType::globalVariableGroupSymbol)
267 {
268 if (!member->HasProjectMembers()) continue;
269 }
270 std::unique_ptr<sngxml::dom::Element> memberElement = member->ToDomElement(typeMap);
271 if (memberElement)
272 {
273 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(memberElement.release()));
274 }
275 }
276 }
277 bool ContainerSymbol::HasProjectMembers() const
278 {
279 if (FullName() == U"System.Meta") return false;
280 for (const std::std::unique_ptr<Symbol>&member : members)
281 {
282 if (member->GetSymbolType() == SymbolType::namespaceSymbol ||
283 member->GetSymbolType() == SymbolType::classGroupTypeSymbol ||
284 member->GetSymbolType() == SymbolType::functionGroupSymbol ||
285 member->GetSymbolType() == SymbolType::conceptGroupSymbol ||
286 member->GetSymbolType() == SymbolType::globalVariableGroupSymbol)
287 {
288 if (member->HasProjectMembers()) return true;
289 }
290 else
291 {
292 if (member->IsFunctionSymbol())
293 {
294 FunctionSymbol* fun = static_cast<FunctionSymbol*>(member.get());
295 if (fun->IsTemplateSpecialization()) continue;
296 }
297 if (member->IsProject()) return true;
298 }
299 }
300 return false;
301 }
302
303 FunctionSymbol* ContainerSymbol::GetFunctionByIndex(int32_t functionIndex) const
304 {
305 auto it = functionIndexMap.find(functionIndex);
306 if (it != functionIndexMap.cend())
307 {
308 return it->second;
309 }
310 else
311 {
312 return nullptr;
313 }
314 }
315
316 void ContainerSymbol::Check()
317 {
318 Symbol::Check();
319 for (const auto& p : members)
320 {
321 p->Check();
322 }
323 for (const auto& p : functionIndexMap)
324 {
325 if (!p.second)
326 {
327 throw SymbolCheckException("container symbol has no function", GetSpan(), SourceModuleId());
328 }
329 }
330 }
331
332 void ContainerSymbol::CopyFrom(const Symbol* that)
333 {
334 Symbol::CopyFrom(that);
335 const ContainerSymbol* thatContainer = static_cast<const ContainerSymbol*>(that);
336 containerScope.SetParentScope(Parent()->GetContainerScope());
337 for (const std::std::pair<std::u32string, Symbol*>&p : thatContainer->containerScope.SymbolMap())
338 {
339 containerScope.Install(p.second);
340 }
341 }
342
343 DeclarationBlock::DeclarationBlock(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) : ContainerSymbol(SymbolType::declarationBlock, span_, sourceModuleId_, name_)
344 {
345 }
346
347 void DeclarationBlock::AddMember(Symbol* member)
348 {
349 ContainerSymbol::AddMember(member);
350 if (member->GetSymbolType() == SymbolType::localVariableSymbol)
351 {
352 FunctionSymbol* fun = Function();
353 if (fun)
354 {
355 fun->AddLocalVariable(static_cast<LocalVariableSymbol*>(member));
356 }
357 }
358 }
359
360 } }