1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/symbols/ClassTemplateSpecializationSymbol.hpp>
  7 #include <cmajor/symbols/Exception.hpp>
  8 #include <cmajor/symbols/Module.hpp>
  9 #include <cmajor/symbols/SymbolWriter.hpp>
 10 #include <cmajor/symbols/SymbolReader.hpp>
 11 #include <cmajor/symbols/SymbolTable.hpp>
 12 #include <soulng/util/Unicode.hpp>
 13 #include <soulng/util/Sha1.hpp>
 14 #include <boost/uuid/uuid_io.hpp>
 15 
 16 namespace cmajor { namespace symbols {
 17 
 18 using namespace soulng::unicode;
 19 
 20 std::u32string MakeClassTemplateSpecializationName(ClassTypeSymbol* classTemplateconst std::std::vector<TypeSymbol*>&templateArgumentTypes)
 21 {
 22     std::u32string name = classTemplate->GroupName();
 23     name.append(1'<');
 24     int n = templateArgumentTypes.size();
 25     for (int i = 0; i < n; ++i)
 26     {
 27         if (i > 0)
 28         {
 29             name.append(U", ");
 30         }
 31         name.append(templateArgumentTypes[i]->FullName());
 32     }
 33     name.append(1'>');
 34     return name;
 35 }
 36 
 37 ClassTemplateSpecializationSymbol::ClassTemplateSpecializationSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 38     ClassTypeSymbol(SymbolType::classTemplateSpecializationSymbolspan_sourceModuleId_name_)classTemplate(nullptr)templateArgumentTypes()flags(ClassTemplateSpecializationFlags::none)
 39 {
 40 }
 41 
 42 ClassTemplateSpecializationSymbol::ClassTemplateSpecializationSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_std::u32string& name_ClassTypeSymbol* classTemplate_const std::std::vector<TypeSymbol*>&templateArgumentTypes_):
 43     ClassTypeSymbol(SymbolType::classTemplateSpecializationSymbolspan_sourceModuleId_name_)classTemplate(classTemplate_)templateArgumentTypes(templateArgumentTypes_)flags(ClassTemplateSpecializationFlags::none)
 44 {
 45 }
 46 
 47 ClassTemplateSpecializationSymbol::~ClassTemplateSpecializationSymbol()
 48 {
 49 }
 50 
 51 std::u32string ClassTemplateSpecializationSymbol::SimpleName() const
 52 {
 53     std::u32string simpleName = classTemplate->GroupName();
 54     int n = templateArgumentTypes.size();
 55     for (int i = 0; i < n; ++i)
 56     {
 57         simpleName.append(U"_").append(templateArgumentTypes[i]->SimpleName());
 58     }
 59     return simpleName;
 60 }
 61 
 62 void ClassTemplateSpecializationSymbol::Write(SymbolWriter& writer)
 63 {
 64     ClassTypeSymbol::Write(writer);
 65     const boost::uuids::uuid& classTemplateId = classTemplate->TypeId();
 66     writer.GetBinaryWriter().Write(classTemplateId);
 67     uint32_t n = templateArgumentTypes.size();
 68     writer.GetBinaryWriter().WriteULEB128UInt(n);
 69     for (uint32_t i = 0; i < n; ++i)
 70     {
 71         TypeSymbol* templateArgumentType = templateArgumentTypes[i];
 72         const boost::uuids::uuid& templateArgumentTypeId = templateArgumentType->TypeId();
 73         writer.GetBinaryWriter().Write(templateArgumentTypeId);
 74     }
 75     writer.GetBinaryWriter().Write(uint8_t(flags));
 76 }
 77 
 78 void ClassTemplateSpecializationSymbol::Read(SymbolReader& reader)
 79 {
 80     ClassTypeSymbol::Read(reader);
 81     boost::uuids::uuid classTemplateId;
 82     reader.GetBinaryReader().ReadUuid(classTemplateId);
 83     reader.GetSymbolTable()->EmplaceTypeRequest(readerthisclassTemplateId-1);
 84     uint32_t n = reader.GetBinaryReader().ReadULEB128UInt();
 85     templateArgumentTypes.resize(n);
 86     for (uint32_t i = 0; i < n; ++i)
 87     {
 88         boost::uuids::uuid typeArgumentId;
 89         reader.GetBinaryReader().ReadUuid(typeArgumentId);
 90         reader.GetSymbolTable()->EmplaceTypeRequest(readerthistypeArgumentId-2 - i);
 91     }
 92     flags = ClassTemplateSpecializationFlags(reader.GetBinaryReader().ReadByte());
 93 }
 94 
 95 void ClassTemplateSpecializationSymbol::EmplaceType(TypeSymbol* typeSymbolint index)
 96 {
 97     if (index < 0)
 98     {
 99         if (index == -1)
100         {
101             Assert(typeSymbol->GetSymbolType() == SymbolType::classTypeSymbol"class type symbol expected");
102             classTemplate = static_cast<ClassTypeSymbol*>(typeSymbol);
103         }
104         else
105         {
106             int typeArgumentIndex = -(index + 2);
107             if (typeArgumentIndex < 0 || typeArgumentIndex >= templateArgumentTypes.size())
108             {
109                 Assert(false"invalid emplace type index in class template specialization");
110             }
111             templateArgumentTypes[typeArgumentIndex] = typeSymbol;
112         }
113     }
114     else
115     {
116         ClassTypeSymbol::EmplaceType(typeSymbolindex);
117     }
118 }
119 
120 bool ClassTemplateSpecializationSymbol::IsPrototypeTemplateSpecialization() const
121 {
122     return IsPrototype();
123 }
124 
125 void* ClassTemplateSpecializationSymbol::IrType(Emitter& emitter)
126 {
127     if (IsRecursive())
128     {
129         void* localIrType = emitter.GetIrTypeByTypeId(TypeId());
130         if (!localIrType)
131         {
132             localIrType = ClassTypeSymbol::IrType(emitter);
133             emitter.SetIrTypeByTypeId(TypeId()localIrType);
134         }
135         return localIrType;
136     }
137     else
138     {
139         return ClassTypeSymbol::IrType(emitter);
140     }
141 }
142 
143 const ContainerScope* ClassTemplateSpecializationSymbol::GetArrowScope() const
144 {
145     if (classTemplate->GroupName() == U"UniquePtr" || classTemplate->GroupName() == U"SharedPtr")
146     {
147         if (templateArgumentTypes.size() == 1)
148         {
149             return templateArgumentTypes[0]->GetContainerScope();
150         }
151     }
152     return Symbol::GetArrowScope();
153 }
154 
155 ContainerScope* ClassTemplateSpecializationSymbol::GetArrowScope()
156 {
157     if (classTemplate->GroupName() == U"UniquePtr" || classTemplate->GroupName() == U"SharedPtr")
158     {
159         if (templateArgumentTypes.size() == 1)
160         {
161             return templateArgumentTypes[0]->GetContainerScope();
162         }
163     }
164     return Symbol::GetArrowScope();
165 }
166 
167 void ClassTemplateSpecializationSymbol::SetGlobalNs(std::std::unique_ptr<Node>&&globalNs_)
168 {
169     globalNs = std::move(globalNs_);
170 }
171 
172 void ClassTemplateSpecializationSymbol::SetFileScope(FileScope* fileScope_)
173 {
174     fileScope.reset(fileScope_);
175 }
176 
177 FileScope* ClassTemplateSpecializationSymbol::ReleaseFileScope()
178 {
179     return fileScope.release();
180 }
181 
182 TypeSymbol* ClassTemplateSpecializationSymbol::UnifyTemplateArgumentType(SymbolTable& symbolTableconst std::std::unordered_map<TemplateParameterSymbol*TypeSymbol*>&templateParameterMap
183     const Span& spanconst boost::uuids::uuid& moduleId)
184 {
185     std::vector<TypeSymbol*> targetTemplateArgumentTypes;
186     for (int i = 0; i < templateArgumentTypes.size(); ++i)
187     {
188         TypeSymbol* templateArgumentType = templateArgumentTypes[i]->UnifyTemplateArgumentType(symbolTabletemplateParameterMapspanmoduleId);
189         if (templateArgumentType)
190         {
191             targetTemplateArgumentTypes.push_back(templateArgumentType);
192         }
193         else
194         {
195             return nullptr;
196         }
197     }
198     return symbolTable.MakeClassTemplateSpecialization(classTemplatetargetTemplateArgumentTypesspanGetRootModuleForCurrentThread()->Id());
199 }
200 
201 std::u32string ClassTemplateSpecializationSymbol::Id() const
202 {
203     if (IsPrototype())
204     {
205         return MangledName();
206     }
207     else
208     {
209         return TypeSymbol::Id();
210     }
211 }
212 
213 void ClassTemplateSpecializationSymbol::Check()
214 {
215     ClassTypeSymbol::Check();
216     if (!classTemplate)
217     {
218         throw SymbolCheckException("class template specialization has no class template"GetSpan()SourceModuleId());
219     }
220     for (TypeSymbol* templateArguementType : templateArgumentTypes)
221     {
222         if (!templateArguementType)
223         {
224             throw SymbolCheckException("class template specialization has no template argument type"GetSpan()SourceModuleId());
225         }
226     }
227 }
228 
229 } } // namespace cmajor::symbols