1
2
3
4
5
6 #include <cmajor/symbols/ConceptSymbol.hpp>
7 #include <cmajor/symbols/ModuleCache.hpp>
8 #include <cmajor/symbols/Exception.hpp>
9 #include <cmajor/symbols/SymbolWriter.hpp>
10 #include <cmajor/symbols/SymbolReader.hpp>
11 #include <cmajor/symbols/SymbolTable.hpp>
12 #include <cmajor/symbols/SymbolCollector.hpp>
13 #include <cmajor/symbols/Module.hpp>
14 #include <soulng/util/Unicode.hpp>
15 #include <boost/uuid/uuid_generators.hpp>
16 #include <boost/uuid/uuid_io.hpp>
17
18 namespace cmajor { namespace symbols {
19
20 using namespace soulng::unicode;
21
22 ConceptGroupSymbol::ConceptGroupSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) : Symbol(SymbolType::conceptGroupSymbol, span_, sourceModuleId_, name_)
23 {
24 }
25
26 void ConceptGroupSymbol::AddConcept(ConceptSymbol* conceptSymbol)
27 {
28 Assert(conceptSymbol->GroupName() == Name(), "wrong concept group");
29 int arity = conceptSymbol->Arity();
30 auto it = arityConceptMap.find(arity);
31 if (it != arityConceptMap.cend())
32 {
33 throw Exception("concept group '" + ToUtf8(FullName()) + "' already has concept with arity " + std::to_string(arity), GetSpan(), SourceModuleId());
34 }
35 arityConceptMap[arity] = conceptSymbol;
36 conceptSymbol->SetConceptGroup(this);
37 }
38
39 void ConceptGroupSymbol::RemoveConcept(ConceptSymbol* conceptSymbol)
40 {
41 int arity = conceptSymbol->Arity();
42 arityConceptMap.erase(arity);
43 }
44
45 bool ConceptGroupSymbol::IsEmpty() const
46 {
47 return arityConceptMap.empty();
48 }
49
50 ConceptSymbol* ConceptGroupSymbol::GetConcept(int arity)
51 {
52 auto it = arityConceptMap.find(arity);
53 if (it != arityConceptMap.cend())
54 {
55 return it->second;
56 }
57 else
58 {
59 throw Exception("concept with arity " + std::to_string(arity) + " not found from concept group '" + ToUtf8(FullName()) + "'", GetSpan(), SourceModuleId());
60 }
61 }
62
63 bool ConceptGroupSymbol::HasProjectMembers() const
64 {
65 for (const auto& p : arityConceptMap)
66 {
67 ConceptSymbol* conceptSymbol = p.second;
68 if (conceptSymbol->IsProject())
69 {
70 return true;
71 }
72 }
73 return false;
74 }
75
76 void ConceptGroupSymbol::AppendChildElements(sngxml::dom::Element* element, TypeMap& typeMap) const
77 {
78 for (const auto& p : arityConceptMap)
79 {
80 ConceptSymbol* conceptSymbol = p.second;
81 if (conceptSymbol->IsProject())
82 {
83 std::unique_ptr<sngxml::dom::Element> conceptElement = conceptSymbol->ToDomElement(typeMap);
84 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(conceptElement.release()));
85 }
86 }
87 }
88
89 void ConceptGroupSymbol::Check()
90 {
91 Symbol::Check();
92 for (const auto& p : arityConceptMap)
93 {
94 if (!p.second)
95 {
96 throw SymbolCheckException("concept group symbol has no concept symbol", GetSpan(), SourceModuleId());
97 }
98 }
99 }
100
101 std::string ConceptGroupSymbol::GetSymbolHelp() const
102 {
103 if (arityConceptMap.size() == 1)
104 {
105 ConceptSymbol* cs = arityConceptMap.begin()->second;
106 return cs->GetSymbolHelp();
107 }
108 std::string help = "(";
109 help.append(GetSymbolCategoryDescription()).append(") ");
110 help.append(ToUtf8(FullName())).append(" (").append(std::to_string(arityConceptMap.size())).append(" concepts)");
111 return help;
112 }
113
114 ConceptSymbol::ConceptSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
115 ContainerSymbol(SymbolType::conceptSymbol, span_, sourceModuleId_, name_), refinedConcept(nullptr), typeId(boost::uuids::nil_uuid()), hasSource(false), conceptGroup(nullptr)
116 {
117 }
118
119 void ConceptSymbol::Write(SymbolWriter& writer)
120 {
121 ContainerSymbol::Write(writer);
122 Assert(!typeId.is_nil(), "type id not initialized");
123 writer.GetBinaryWriter().Write(typeId);
124 writer.GetBinaryWriter().Write(groupName);
125 boost::uuids::uuid refineConceptId = boost::uuids::nil_uuid();
126 if (refinedConcept)
127 {
128 refineConceptId = refinedConcept->TypeId();
129 }
130 writer.GetBinaryWriter().Write(refineConceptId);
131 uint32_t n = templateParameters.size();
132 writer.GetBinaryWriter().WriteULEB128UInt(n);
133 for (uint32_t i = 0; i < n; ++i)
134 {
135 TemplateParameterSymbol* templateParameter = templateParameters[i];
136 Assert(!templateParameter->TypeId().is_nil(), "type id not initialized");
137 writer.GetBinaryWriter().Write(templateParameter->TypeId());
138 }
139 Node* node = GetRootModuleForCurrentThread()->GetSymbolTable().GetNode(this);
140 Assert(node->IsConceptNode(), "concept node expected");
141 writer.GetAstWriter().Write(node);
142 writer.GetBinaryWriter().Write(hasSource);
143 }
144
145 void ConceptSymbol::Read(SymbolReader& reader)
146 {
147 ContainerSymbol::Read(reader);
148 reader.GetBinaryReader().ReadUuid(typeId);
149 reader.GetSymbolTable()->AddTypeOrConceptSymbolToTypeIdMap(this);
150 groupName = reader.GetBinaryReader().ReadUtf32String();
151 boost::uuids::uuid refinedConcepId;
152 reader.GetBinaryReader().ReadUuid(refinedConcepId);
153 if (!refinedConcepId.is_nil())
154 {
155 reader.GetSymbolTable()->EmplaceConceptRequest(reader, this, refinedConcepId);
156 }
157 uint32_t n = reader.GetBinaryReader().ReadULEB128UInt();
158 templateParameters.resize(n);
159 for (uint32_t i = 0; i < n; ++i)
160 {
161 boost::uuids::uuid templateParameterId;
162 reader.GetBinaryReader().ReadUuid(templateParameterId);
163 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, templateParameterId, i);
164 }
165 conceptNode.reset(reader.GetAstReader().ReadConceptNode());
166 hasSource = reader.GetBinaryReader().ReadBool();
167 }
168
169 void ConceptSymbol::EmplaceConcept(ConceptSymbol* conceptSymbol)
170 {
171 refinedConcept = conceptSymbol;
172 }
173
174 void ConceptSymbol::EmplaceType(TypeSymbol* typeSymbol, int index)
175 {
176 if (index >= 0 && index < templateParameters.size())
177 {
178 if (typeSymbol->GetSymbolType() == SymbolType::templateParameterSymbol)
179 {
180 TemplateParameterSymbol* templateParameter = static_cast<TemplateParameterSymbol*>(typeSymbol);
181 templateParameters[index] = templateParameter;
182 }
183 else
184 {
185 throw Exception("invalid emplace type", GetSpan(), SourceModuleId());
186 }
187 }
188 else
189 {
190 throw Exception("invalid emplace type index", GetSpan(), SourceModuleId());
191 }
192 }
193
194 void ConceptSymbol::Accept(SymbolCollector* collector)
195 {
196 if (IsProject() && Access() == SymbolAccess::public_)
197 {
198 collector->AddConcept(this);
199 }
200 }
201
202 void ConceptSymbol::Dump(CodeFormatter& formatter)
203 {
204 formatter.WriteLine(ToUtf8(Name()));
205 formatter.WriteLine("group name: " + ToUtf8(groupName));
206 formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
207 formatter.WriteLine("mangled name: " + ToUtf8(MangledName()));
208 formatter.WriteLine("typeid: " + boost::uuids::to_string(typeId));
209 if (refinedConcept)
210 {
211 formatter.WriteLine("refined concept: " + ToUtf8(refinedConcept->FullName()));
212 }
213 }
214
215 void ConceptSymbol::AddMember(Symbol* member)
216 {
217 ContainerSymbol::AddMember(member);
218 if (member->GetSymbolType() == SymbolType::templateParameterSymbol)
219 {
220 templateParameters.push_back(static_cast<TemplateParameterSymbol*>(member));
221 }
222 }
223
224 void ConceptSymbol::ComputeName()
225 {
226 std::u32string name = groupName;
227 bool first = true;
228 name.append(1, '<');
229 for (TemplateParameterSymbol* templateParameter : templateParameters)
230 {
231 if (first)
232 {
233 first = false;
234 }
235 else
236 {
237 name.append(U", ");
238 }
239 name.append(templateParameter->Name());
240 }
241 name.append(1, '>');
242 SetName(name);
243 ComputeMangledName();
244 }
245
246 void ConceptSymbol::SetSpecifiers(Specifiers specifiers)
247 {
248 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
249 SetAccess(accessSpecifiers);
250 if ((specifiers & Specifiers::static_) != Specifiers::none)
251 {
252 throw Exception("concept symbol cannot be static", GetSpan(), SourceModuleId());
253 }
254 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
255 {
256 throw Exception("concept symbol cannot be virtual", GetSpan(), SourceModuleId());
257 }
258 if ((specifiers & Specifiers::override_) != Specifiers::none)
259 {
260 throw Exception("concept symbol cannot be override", GetSpan(), SourceModuleId());
261 }
262 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
263 {
264 throw Exception("concept symbol cannot be abstract", GetSpan(), SourceModuleId());
265 }
266 if ((specifiers & Specifiers::inline_) != Specifiers::none)
267 {
268 throw Exception("concept symbol cannot be inline", GetSpan(), SourceModuleId());
269 }
270 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
271 {
272 throw Exception("concept symbol cannot be explicit", GetSpan(), SourceModuleId());
273 }
274 if ((specifiers & Specifiers::external_) != Specifiers::none)
275 {
276 throw Exception("concept symbol cannot be external", GetSpan(), SourceModuleId());
277 }
278 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
279 {
280 throw Exception("concept symbol cannot be suppressed", GetSpan(), SourceModuleId());
281 }
282 if ((specifiers & Specifiers::default_) != Specifiers::none)
283 {
284 throw Exception("concept symbol cannot be default", GetSpan(), SourceModuleId());
285 }
286 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
287 {
288 throw Exception("concept symbol cannot be constexpr", GetSpan(), SourceModuleId());
289 }
290 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
291 {
292 throw Exception("concept symbol cannot be decl", GetSpan(), SourceModuleId());
293 }
294 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
295 {
296 throw Exception("concept symbol cannot be nothrow", GetSpan(), SourceModuleId());
297 }
298 if ((specifiers & Specifiers::throw_) != Specifiers::none)
299 {
300 throw Exception("concept symbol cannot be throw", GetSpan(), SourceModuleId());
301 }
302 if ((specifiers & Specifiers::new_) != Specifiers::none)
303 {
304 throw Exception("concept symbol cannot be new", GetSpan(), SourceModuleId());
305 }
306 if ((specifiers & Specifiers::const_) != Specifiers::none)
307 {
308 throw Exception("concept symbol cannot be const", GetSpan(), SourceModuleId());
309 }
310 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
311 {
312 throw Exception("concept symbol cannot be unit_test", GetSpan(), SourceModuleId());
313 }
314 }
315
316 void ConceptSymbol::Check()
317 {
318 ContainerSymbol::Check();
319 if (typeId.is_nil())
320 {
321 throw SymbolCheckException("concept symbol has empty type id", GetSpan(), SourceModuleId());
322 }
323 if (groupName.empty())
324 {
325 throw SymbolCheckException("concept symbol has empty group name", GetSpan(), SourceModuleId());
326 }
327 for (TemplateParameterSymbol* templateParameter : templateParameters)
328 {
329 if (!templateParameter)
330 {
331 throw SymbolCheckException("concept symbol has no template parameter", GetSpan(), SourceModuleId());
332 }
333 }
334 }
335
336 std::std::unique_ptr<Symbol>ConceptSymbol::RemoveFromParent()
337 {
338 std::unique_ptr<Symbol> symbol = ContainerSymbol::RemoveFromParent();
339 if (conceptGroup)
340 {
341 conceptGroup->RemoveConcept(this);
342 if (conceptGroup->IsEmpty())
343 {
344 std::unique_ptr<Symbol> conceptGroupSymbol = conceptGroup->RemoveFromParent();
345 }
346 }
347 return symbol;
348 }
349
350 AxiomSymbol::AxiomSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId, const std::u32string& name_) :
351 ContainerSymbol(SymbolType::axiomSymbol, span_, sourceModuleId, name_)
352 {
353 }
354
355 } }