1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcpp/symbols/SymbolTable.hpp>
  7 #include <sngcpp/symbols/ParameterSymbol.hpp>
  8 #include <sngcpp/symbols/VariableSymbol.hpp>
  9 #include <sngcpp/symbols/TypedefSymbol.hpp>
 10 #include <sngcpp/symbols/ExternalTypeSymbol.hpp>
 11 #include <sngcpp/symbols/ClassTemplateSpecializationSymbol.hpp>
 12 #include <sngcpp/symbols/IntegerLiteralTypeSymbol.hpp>
 13 #include <sngcpp/symbols/LambdaExpressionSymbol.hpp>
 14 #include <sngcpp/symbols/GrammarSymbol.hpp>
 15 #include <sngcpp/ast/Class.hpp>
 16 #include <soulng/util/Unicode.hpp>
 17 #include <soulng/util/Sha1.hpp>
 18 #include <algorithm>
 19 
 20 namespace sngcpp { namespace symbols {
 21 
 22 using namespace soulng::unicode;
 23 using namespace soulng::util;
 24 
 25 SymbolTable::SymbolTable() : globalNs(Span()U"")container(&globalNs)blockNumber(0)gendocMode(false)
 26 {
 27     globalNs.SetAccess(Specifier::public_);
 28 }
 29 
 30 std::std::unique_ptr<sngxml::dom::Document>SymbolTable::ToDomDocument()
 31 {
 32     std::unique_ptr<sngxml::dom::Document> symbolTableDoc(new sngxml::dom::Document());
 33     symbolTableDoc->AppendChild(std::move(ToDomElement()));
 34     return symbolTableDoc;
 35 }
 36 
 37 std::std::unique_ptr<sngxml::dom::Element>SymbolTable::ToDomElement()
 38 {
 39     std::unique_ptr<sngxml::dom::Element> symbolTableElement(new sngxml::dom::Element(U"symbolTable"));
 40     std::unique_ptr<sngxml::dom::Element> globalNsElement = globalNs.ToDomElement();
 41     symbolTableElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(globalNsElement.release()));
 42     std::unique_ptr<sngxml::dom::Element> typesElement = CreateTypesElement();
 43     if (typesElement)
 44     {
 45         symbolTableElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(typesElement.release()));
 46     }
 47     return symbolTableElement;
 48 }
 49 
 50 std::std::unique_ptr<sngxml::dom::Element>SymbolTable::CreateTypesElement()
 51 {
 52     std::unique_ptr<sngxml::dom::Element> typesElement;
 53     if (!types.empty())
 54     {
 55         typesElement.reset(new sngxml::dom::Element(U"types"));
 56         std::vector<TypeSymbol*> typeSymbols;
 57         for (const std::std::unique_ptr<TypeSymbol>&type : types)
 58         {
 59             typeSymbols.push_back(type.get());
 60         }
 61         std::sort(typeSymbols.begin()typeSymbols.end()ByName());
 62         for (TypeSymbol* typeSymbol : typeSymbols)
 63         {
 64             std::unique_ptr<sngxml::dom::Element> typeElement = typeSymbol->ToDomElement();
 65             typesElement->AppendChild(std::unique_ptr<sngxml::dom::Node>(typeElement.release()));
 66         }
 67     }
 68     return typesElement;
 69 }
 70 
 71 void SymbolTable::BeginContainer(ContainerSymbol* container_)
 72 {
 73     containerStack.push(container);
 74     container = container_;
 75 }
 76 
 77 void SymbolTable::EndContainer()
 78 {
 79     container = containerStack.top();
 80     containerStack.pop();
 81 }
 82 
 83 int SymbolTable::BeginNameSequence(const std::std::vector<std::std::pair<std::u32stringint>>&nameSequence)
 84 {
 85     int result = 0;
 86     int n = nameSequence.size();
 87     for (int i = 0; i < n - 1; ++i)
 88     {
 89         if (nameSequence[i].first.empty())
 90         {
 91             BeginContainer(&globalNs);
 92             ++result;
 93         }
 94         else
 95         {
 96             Symbol* symbol = container->GetContainerScope()->Lookup(nameSequence[i].first);
 97             if (symbol)
 98             {
 99                 if (symbol->IsClassGroupSymbol())
100                 {
101                     ClassGroupSymbol* classGroup = static_cast<ClassGroupSymbol*>(symbol);
102                     ClassTypeSymbol* cls = classGroup->GetClass(nameSequence[i].second);
103                     if (cls)
104                     {
105                         BeginContainer(cls);
106                         ++result;
107                     }
108                 }
109                 else if (symbol->IsContainerSymbol())
110                 {
111                     ContainerSymbol* containerSymbol = static_cast<ContainerSymbol*>(symbol);
112                     BeginContainer(containerSymbol);
113                     ++result;
114                 }
115             }
116         }
117     }
118     return result;
119 }
120 
121 void SymbolTable::EndNameSequence(int n)
122 {
123     for (int i = 0; i < n; ++i)
124     {
125         EndContainer();
126     }
127 }
128 
129 void SymbolTable::BeginNamespace(const std::u32string& namespaceNameconst std::u32string& projectName)
130 {
131     if (namespaceName.empty())
132     {
133         BeginContainer(&globalNs);
134     }
135     else
136     {
137         Symbol* symbol = container->GetContainerScope()->Lookup(namespaceName);
138         if (symbol)
139         {
140             if (symbol->IsNamespaceSymbol())
141             {
142                 NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(symbol);
143                 if (!projectName.empty())
144                 {
145                     ns->AddProject(projectName);
146                 }
147                 BeginContainer(ns);
148             }
149             else
150             {
151                 throw std::runtime_error(ToUtf8(namespaceName) + " does not denote a namespace");
152             }
153         }
154         else
155         {
156             std::unique_ptr<NamespaceSymbol> newNs(new NamespaceSymbol(Span()namespaceName));
157             newNs->SetAccess(Specifier::public_);
158             NamespaceSymbol* ns = newNs.get();
159             if (!projectName.empty())
160             {
161                 ns->AddProject(projectName);
162             }
163             container->AddMember(std::move(newNs));
164             BeginContainer(ns);
165         }
166     }
167 }
168 
169 void SymbolTable::EndNamespace()
170 {
171     EndContainer();
172 }
173 
174 void SymbolTable::BeginClass(ClassNode* classNodeconst std::u32string& classNamestd::std::vector<std::std::unique_ptr<TypeSymbol>>&templateParametersconststd::u32string&projectName)
175 {
176     ClassTypeSymbol* classType = new ClassTypeSymbol(classNode->GetSpan()classNameclassNode->GetClassKey());
177     classType->SetProjectName(projectName);
178     MapNode(classNodeclassType);
179     for (std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
180     {
181         classType->AddTemplateParameter(std::move(templateParameter));
182     }
183     BeginContainer(classType);
184 }
185 
186 void SymbolTable::EndClass(const std::u32string& projectName)
187 {
188     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(container);
189     EndContainer();
190     container->AddMember(std::unique_ptr<Symbol>(classType));
191     if (container->IsNamespaceSymbol())
192     {
193         if (container->Name() == U"")
194         {
195             NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
196             ns->AddProject(projectName);
197         }
198     }
199 }
200 
201 void SymbolTable::BeginLambdaExpression(LambdaExpressionNode* lambdaExpressionNode)
202 {
203     LambdaExpressionSymbol* lambdaExpression = new LambdaExpressionSymbol(lambdaExpressionNode->GetSpan());
204     MapNode(lambdaExpressionNodelambdaExpression);
205     BeginContainer(lambdaExpression);
206 }
207 
208 void SymbolTable::EndLambdaExpression()
209 {
210     LambdaExpressionSymbol* lambdaExpression = static_cast<LambdaExpressionSymbol*>(container);
211     EndContainer();
212     container->AddMember(std::unique_ptr<Symbol>(lambdaExpression));
213 }
214 
215 void SymbolTable::BeginGrammar(const Span& spanconst std::u32string& grammarNameconst std::u32string& projectName)
216 {
217     GrammarSymbol* grammar = new GrammarSymbol(spangrammarName);
218     grammar->SetProjectName(projectName);
219     BeginContainer(grammar);
220 }
221 
222 void SymbolTable::EndGrammar(const std::u32string& projectName)
223 {
224     GrammarSymbol* grammar = static_cast<GrammarSymbol*>(container);
225     EndContainer();
226     container->AddMember(std::unique_ptr<Symbol>(grammar));
227     if (container->IsNamespaceSymbol() && container->Name() == U"")
228     {
229         NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
230         ns->AddProject(projectName);
231     }
232 }
233 
234 RuleSymbol* SymbolTable::AddRule(const Span& spanconst std::u32string& ruleName)
235 {
236     RuleSymbol* rule = new RuleSymbol(spanruleName);
237     container->AddMember(std::unique_ptr<Symbol>(rule));
238     return rule;
239 }
240 
241 void SymbolTable::BeginEnumType(EnumTypeNode* enumTypeNodeconst std::u32string& enumTypeNameconst std::u32string& projectName)
242 {
243     EnumTypeSymbol* enumType = new EnumTypeSymbol(enumTypeNode->GetSpan()enumTypeNameenumTypeNode->GetEnumKey());
244     enumType->SetProjectName(projectName);
245     MapNode(enumTypeNodeenumType);
246     BeginContainer(enumType);
247 }
248 
249 void SymbolTable::EndEnumType(const std::u32string& projectName)
250 {
251     EnumTypeSymbol* enumType = static_cast<EnumTypeSymbol*>(container);
252     EndContainer();
253     container->AddMember(std::unique_ptr<Symbol>(enumType));
254     if (container->IsNamespaceSymbol() && container->Name() == U"")
255     {
256         NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
257         ns->AddProject(projectName);
258     }
259 }
260 
261 void SymbolTable::AddEnumerator(EnumeratorNode* enumeratorNodeconst std::u32string& enumeratorNameconst std::u32string& enumeratorValue)
262 {
263     EnumeratorSymbol* enumeratorSymbol = new EnumeratorSymbol(enumeratorNode->GetSpan()enumeratorNameenumeratorValue);
264     MapNode(enumeratorNodeenumeratorSymbol);
265     container->AddMember(std::unique_ptr<Symbol>(enumeratorSymbol));
266 }
267 
268 void SymbolTable::BeginFunction(FunctionDeclaratorNode* functionDeclaratorNodeconst std::u32string& groupNameconst std::u32string& functionName
269     std::std::vector<std::std::unique_ptr<TypeSymbol>>&templateParametersSpecifierspecifiersconststd::u32string&projectName)
270 {
271     if (container->IsClassTypeSymbol() && groupName == U"destructor")
272     {
273         DestructorSymbol* destructorSymbol = new DestructorSymbol(functionDeclaratorNode->GetSpan()groupNamespecifiers);
274         destructorSymbol->SetProjectName(projectName);
275         MapNode(functionDeclaratorNodedestructorSymbol);
276         BeginContainer(destructorSymbol);
277     }
278     else if (container->IsClassTypeSymbol() && groupName == container->Name())
279     {
280         ConstructorSymbol* constructorSymbol = new ConstructorSymbol(functionDeclaratorNode->GetSpan()groupNamespecifiers);
281         constructorSymbol->SetProjectName(projectName);
282         MapNode(functionDeclaratorNodeconstructorSymbol);
283         BeginContainer(constructorSymbol);
284         for (std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
285         {
286             constructorSymbol->AddTemplateParameter(std::move(templateParameter));
287         }
288     }
289     else
290     {
291         FunctionSymbol* functionSymbol = new FunctionSymbol(functionDeclaratorNode->GetSpan()groupNamefunctionNamespecifiers);
292         functionSymbol->SetProjectName(projectName);
293         MapNode(functionDeclaratorNodefunctionSymbol);
294         BeginContainer(functionSymbol);
295         for (std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
296         {
297             functionSymbol->AddTemplateParameter(std::move(templateParameter));
298         }
299     }
300 }
301 
302 void SymbolTable::EndFunction(const std::u32string& projectName)
303 {
304     FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(container);
305     EndContainer();
306     container->AddMember(std::unique_ptr<Symbol>(functionSymbol));
307     if (container->IsNamespaceSymbol() && container->Name() == U"")
308     {
309         NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
310         ns->AddProject(projectName);
311     }
312 }
313 
314 void SymbolTable::BeginFunctionDeclaration(FunctionDeclaratorNode* functionDeclaratorNodeconst std::u32string& groupNameconst std::u32string& functionName
315     std::std::vector<std::std::unique_ptr<TypeSymbol>>&templateParametersSpecifierspecifiersconststd::u32string&projectName)
316 {
317     if (container->IsClassTypeSymbol() && groupName == container->Name())
318     {
319         ConstructorDeclarationSymbol* constructorDeclarationSymbol = new ConstructorDeclarationSymbol(functionDeclaratorNode->GetSpan()groupNamespecifiers);
320         constructorDeclarationSymbol->SetProjectName(projectName);
321         MapNode(functionDeclaratorNodeconstructorDeclarationSymbol);
322         BeginContainer(constructorDeclarationSymbol);
323         for (std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
324         {
325             constructorDeclarationSymbol->AddTemplateParameter(std::move(templateParameter));
326         }
327     }
328     else
329     {
330         FunctionDeclarationSymbol* functionDeclarationSymbol = new FunctionDeclarationSymbol(functionDeclaratorNode->GetSpan()groupNamefunctionNamespecifiers);
331         functionDeclarationSymbol->SetProjectName(projectName);
332         MapNode(functionDeclaratorNodefunctionDeclarationSymbol);
333         BeginContainer(functionDeclarationSymbol);
334         for (std::std::unique_ptr<TypeSymbol>&templateParameter : templateParameters)
335         {
336             functionDeclarationSymbol->AddTemplateParameter(std::move(templateParameter));
337         }
338     }
339 }
340 
341 void SymbolTable::EndFunctionDeclaration()
342 {
343     FunctionDeclarationSymbol* functionDeclarationSymbol = static_cast<FunctionDeclarationSymbol*>(container);
344     EndContainer();
345     container->AddMember(std::unique_ptr<Symbol>(functionDeclarationSymbol));
346 }
347 
348 void SymbolTable::AddParameter(ParameterNode* parameterNodeconst std::u32string& parameterName)
349 {
350     ParameterSymbol* parameterSymbol = new ParameterSymbol(parameterNode->GetSpan()parameterName);
351     parameterSymbol->SetAccess(Specifier::public_);
352     MapNode(parameterNodeparameterSymbol);
353     container->AddMember(std::unique_ptr<Symbol>(parameterSymbol));
354 }
355 
356 void SymbolTable::BeginDeclarationBlock(Node* blockNode)
357 {
358     DeclarationBlockSymbol* declarationBlock = new DeclarationBlockSymbol(blockNode->GetSpan()U"block" + ToUtf32(std::to_string(blockNumber++)));
359     declarationBlock->SetAccess(Specifier::public_);
360     MapNode(blockNodedeclarationBlock);
361     BeginContainer(declarationBlock);
362 }
363 
364 void SymbolTable::EndDeclarationBlock()
365 {
366     DeclarationBlockSymbol* declarationBlock = static_cast<DeclarationBlockSymbol*>(container);
367     EndContainer();
368     container->AddMember(std::unique_ptr<Symbol>(declarationBlock));
369 }
370 
371 void SymbolTable::AddTypedef(TypedefNode* nodeconst std::u32string& typedefNameconst std::u32string& projectName)
372 {
373     TypedefSymbol* typedefSymbol = new TypedefSymbol(node->GetSpan()typedefName);
374     typedefSymbol->SetProjectName(projectName);
375     MapNode(nodetypedefSymbol);
376     container->AddMember(std::unique_ptr<Symbol>(typedefSymbol));
377     if (container->IsNamespaceSymbol() && container->Name() == U"")
378     {
379         NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
380         ns->AddProject(projectName);
381     }
382 }
383 
384 void SymbolTable::AddVariable(Node* nodeconst std::u32string& variableNameconst std::u32string& projectName)
385 {
386     Symbol* symbol = container->GetContainerScope()->Lookup(variableName);
387     if (symbol)
388     {
389         MapNode(nodesymbol);
390     }
391     else
392     {
393         VariableSymbol* variableSymbol = new VariableSymbol(node->GetSpan()variableName);
394         variableSymbol->SetProjectName(projectName);
395         MapNode(nodevariableSymbol);
396         container->AddMember(std::unique_ptr<Symbol>(variableSymbol));
397         if (container->IsNamespaceSymbol() && container->Name() == U"")
398         {
399             NamespaceSymbol* ns = static_cast<NamespaceSymbol*>(container);
400             ns->AddProject(projectName);
401         }
402     }
403 }
404 
405 void SymbolTable::MapNode(Node* nodeSymbol* symbol)
406 {
407     nodeSymbolMap[node] = symbol;
408 }
409 
410 void SymbolTable::MapIdNodeSequence(Node* nodeconst std::std::vector<IdentifierNode*>&idNodeSequence)
411 {
412     idNodeSequenceMap[node] = idNodeSequence;
413 }
414 
415 void SymbolTable::MapTemplateIdToTemplateArgumentNodes(TemplateIdNode* templateIdNodeconst std::std::vector<Node*>&templateArgumentNodes)
416 {
417     templateIdTemplateArgumentNodeMap[templateIdNode] = templateArgumentNodes;
418 }
419 
420 Symbol* SymbolTable::GetSymbolNothrow(Node* node)
421 {
422     auto it = nodeSymbolMap.find(node);
423     if (it != nodeSymbolMap.cend())
424     {
425         return it->second;
426     }
427     else
428     {
429         return nullptr;
430     }
431 }
432 
433 Symbol* SymbolTable::GetSymbol(Node* node)
434 {
435     Symbol* symbol = GetSymbolNothrow(node);
436     if (symbol)
437     {
438         return symbol;
439     }
440     else
441     {
442         throw std::runtime_error("symbol for node not found");
443     }
444 }
445 
446 const std::std::vector<IdentifierNode*>&SymbolTable::GetIdNodeSequence(Node*node)
447 {
448     auto it = idNodeSequenceMap.find(node);
449     if (it != idNodeSequenceMap.cend())
450     {
451         return it->second;
452     }
453     else
454     {
455         throw std::runtime_error("id node sequence for node not found");
456     }
457 }
458 
459 const std::std::vector<Node*>&SymbolTable::GetTemplateArgumentNodes(TemplateIdNode*templateIdNode)
460 {
461     auto it = templateIdTemplateArgumentNodeMap.find(templateIdNode);
462     if (it != templateIdTemplateArgumentNodeMap.cend())
463     {
464         return it->second;
465     }
466     else
467     {
468         throw std::runtime_error("template argument nodes for template id node not found");
469     }
470 }
471 
472 ContainerScope* SymbolTable::GetContainerScope()
473 {
474     return container->GetContainerScope();
475 }
476 
477 TypeSymbol* SymbolTable::GetBoolType()
478 {
479     SimpleTypeNode boolNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::bool_));
480     return MakeSimpleTypeSymbol(boolNode);
481 }
482 
483 TypeSymbol* SymbolTable::GetLongType()
484 {
485     SimpleTypeNode longNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::long_));
486     return MakeSimpleTypeSymbol(longNode);
487 }
488 
489 TypeSymbol* SymbolTable::GetDoubleType()
490 {
491     SimpleTypeNode doubleNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::double_));
492     return MakeSimpleTypeSymbol(doubleNode);
493 }
494 
495 TypeSymbol* SymbolTable::GetIntType()
496 {
497     SimpleTypeNode intNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::int_));
498     return MakeSimpleTypeSymbol(intNode);
499 }
500 
501 TypeSymbol* SymbolTable::GetUIntType()
502 {
503     std::vector<SimpleTypeSpecifier> specifiers;
504     specifiers.push_back(SimpleTypeSpecifier::unsigned_);
505     specifiers.push_back(SimpleTypeSpecifier::int_);
506     SimpleTypeNode uintNode(soulng::lexer::Span()specifiers);
507     return MakeSimpleTypeSymbol(uintNode);
508 }
509 
510 TypeSymbol* SymbolTable::GetCharType()
511 {
512     SimpleTypeNode charNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::char_));
513     return MakeSimpleTypeSymbol(charNode);
514 }
515 
516 TypeSymbol* SymbolTable::GetChar16Type()
517 {
518     SimpleTypeNode char16Node(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::char16));
519     return MakeSimpleTypeSymbol(char16Node);
520 }
521 
522 TypeSymbol* SymbolTable::GetChar32Type()
523 {
524     SimpleTypeNode char32Node(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::char32));
525     return MakeSimpleTypeSymbol(char32Node);
526 }
527 
528 TypeSymbol* SymbolTable::GetVoidType()
529 {
530     SimpleTypeNode voidNode(soulng::lexer::Span()std::vector<SimpleTypeSpecifier>(1SimpleTypeSpecifier::void_));
531     return MakeSimpleTypeSymbol(voidNode);
532 }
533 
534 TypeSymbol* SymbolTable::MakeSimpleTypeSymbol(SimpleTypeNode& simpleTypeNode)
535 {
536     std::u32string id = simpleTypeNode.Id();
537     auto it = idTypeMap.find(id);
538     if (it != idTypeMap.cend())
539     {
540         return it->second;
541     }
542     else
543     {
544         SimpleTypeSymbol* simpleTypeSymbol = new SimpleTypeSymbol(simpleTypeNode.GetSpan()simpleTypeNode.Str()idsimpleTypeNode.Flags());
545         simpleTypeSymbol->SetAccess(Specifier::public_);
546         idTypeMap[id] = simpleTypeSymbol;
547         types.push_back(std::unique_ptr<TypeSymbol>(simpleTypeSymbol));
548         return simpleTypeSymbol;
549     }
550 }
551 
552 TypeSymbol* SymbolTable::MakeElaborateClassTypeSymbol(ClassKey classKeyTypeSymbol* classType)
553 {
554     std::u32string idMaterial = ToString(classKey) + classType->IdStr();
555     std::u32string id = U"type_" + ToUtf32(GetSha1MessageDigest(ToUtf8(idMaterial)));
556     auto it = idTypeMap.find(id);
557     if (it != idTypeMap.cend())
558     {
559         return it->second;
560     }
561     else
562     {
563         ElaborateClassTypeSymbol* elaborateClassTypeSymbol = new ElaborateClassTypeSymbol(classType->GetSpan()classKeyclassTypeid);
564         idTypeMap[id] = elaborateClassTypeSymbol;
565         types.push_back(std::unique_ptr<TypeSymbol>(elaborateClassTypeSymbol));
566         return elaborateClassTypeSymbol;
567     }
568 }
569 
570 TypeSymbol* SymbolTable::MakeDerivedTypeSymbol(std::std::vector<Derivation>&derivationsTypeSymbol*baseType)
571 {
572     if (baseType->IsDerivedTypeSymbol())
573     {
574         DerivedTypeSymbol* derivedType = static_cast<DerivedTypeSymbol*>(baseType);
575         derivations = UnifyDerivations(derivationsderivedType->Derivations());
576         baseType = derivedType->BaseType();
577     }
578     std::u32string id = MakeDerivedTypeId(derivationsbaseType);
579     auto it = idTypeMap.find(id);
580     if (it != idTypeMap.cend())
581     {
582         return it->second;
583     }
584     else
585     {
586         DerivedTypeSymbol* derivedTypeSymbol = new DerivedTypeSymbol(baseType->GetSpan()MakeDerivedTypeName(derivationsbaseType)baseTypederivationsid);
587         derivedTypeSymbol->SetAccess(Specifier::public_);
588         idTypeMap[id] = derivedTypeSymbol;
589         types.push_back(std::unique_ptr<TypeSymbol>(derivedTypeSymbol));
590         return derivedTypeSymbol;
591     }
592 }
593 
594 TypeSymbol* SymbolTable::MakeExternalTypeSymbol(const Span& spanconst std::u32string& nameClassKey classKey)
595 {
596     std::u32string id = U"type_";
597     if (classKey != ClassKey::none)
598     {
599         id.append(ToString(classKey));
600         id.append(1'_');
601     }
602     id.append(ToUtf32(GetSha1MessageDigest(ToUtf8(name))));
603     auto it = idTypeMap.find(id);
604     if (it != idTypeMap.cend())
605     {
606         return it->second;
607     }
608     else
609     {
610         ExternalTypeSymbol* externalTypeSymbol = new ExternalTypeSymbol(spannameclassKeyid);
611         externalTypeSymbol->SetAccess(Specifier::public_);
612         idTypeMap[id] = externalTypeSymbol;
613         types.push_back(std::unique_ptr<TypeSymbol>(externalTypeSymbol));
614         return externalTypeSymbol;
615     }
616 }
617 
618 TypeSymbol* SymbolTable::MakeClassGroupTypeSymbol(ClassGroupSymbol* classGroup)
619 {
620     std::u32string id = classGroup->Id();
621     auto it = idTypeMap.find(id);
622     if (it != idTypeMap.cend())
623     {
624         return it->second;
625     }
626     else
627     {
628         ClassGroupTypeSymbol* classGroupTypeSymbol = new ClassGroupTypeSymbol(classGroup);
629         idTypeMap[id] = classGroupTypeSymbol;
630         types.push_back(std::unique_ptr<TypeSymbol>(classGroupTypeSymbol));
631         return classGroupTypeSymbol;
632     }
633 }
634 
635 TypeSymbol* SymbolTable::MakeClassTemplateSpecializationSymbol(const Span& spanTypeSymbol* primaryClassTemplateconst std::std::vector<TypeSymbol*>&templateArguments)
636 {
637     std::u32string id = MakeClassTemplateSpecializationId(primaryClassTemplatetemplateArguments);
638     auto it = idTypeMap.find(id);
639     if (it != idTypeMap.cend())
640     {
641         return it->second;
642     }
643     else
644     {
645         ClassTemplateSpecializationSymbol* classTemplateSpecializationSymbol = new ClassTemplateSpecializationSymbol(span
646             MakeClassTemplateSpecializationName(primaryClassTemplatetemplateArguments)primaryClassTemplatetemplateArgumentsid);
647         classTemplateSpecializationSymbol->SetAccess(Specifier::public_);
648         idTypeMap[id] = classTemplateSpecializationSymbol;
649         types.push_back(std::unique_ptr<TypeSymbol>(classTemplateSpecializationSymbol));
650         if (gendocMode)
651         {
652             if (primaryClassTemplate->IsExternalTypeSymbol() && primaryClassTemplate->Name() == U"std::unique_ptr")
653             {
654                 BeginContainer(classTemplateSpecializationSymbol);
655                 FunctionDeclaratorNode* functionDeclaratorNode = new FunctionDeclaratorNode(spannew IdDeclaratorNode(spannew IdentifierNode(spanU"get"))nullptrSpecifier());
656                 ownedNodes.push_back(std::unique_ptr<Node>(functionDeclaratorNode));
657                 std::vector<std::std::unique_ptr<TypeSymbol>>templateParameters;
658                 BeginFunction(functionDeclaratorNodeU"get"U"get()"templateParametersSpecifier()std::u32string());
659                 FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(container);
660                 std::vector<Derivation> derivations;
661                 derivations.push_back(Derivation::ptr);
662                 functionSymbol->SetReturnType(MakeDerivedTypeSymbol(derivationstemplateArguments.front()));
663                 EndFunction(std::u32string());
664                 EndContainer();
665             }
666         }
667         return classTemplateSpecializationSymbol;
668     }
669 }
670 
671 TypeSymbol* SymbolTable::MakeIntegerLiteralTypeSymbol(const Span& spanconst std::u32string& valueName)
672 {
673     std::u32string id = U"literal_" + valueName;
674     auto it = idTypeMap.find(id);
675     if (it != idTypeMap.cend())
676     {
677         return it->second;
678     }
679     else
680     {
681         IntegerLiteralTypeSymbol* integerLiteralTypeSymbol = new IntegerLiteralTypeSymbol(spanvalueNameid);
682         integerLiteralTypeSymbol->SetAccess(Specifier::public_);
683         idTypeMap[id] = integerLiteralTypeSymbol;
684         types.push_back(std::unique_ptr<TypeSymbol>(integerLiteralTypeSymbol));
685         return integerLiteralTypeSymbol;
686     }
687 }
688 
689 } } // namespace gendoc::cppsym