1
2
3
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* classTemplate, const 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::classTemplateSpecializationSymbol, span_, 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::classTemplateSpecializationSymbol, span_, 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(reader, this, classTemplateId, -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(reader, this, typeArgumentId, -2 - i);
91 }
92 flags = ClassTemplateSpecializationFlags(reader.GetBinaryReader().ReadByte());
93 }
94
95 void ClassTemplateSpecializationSymbol::EmplaceType(TypeSymbol* typeSymbol, int 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(typeSymbol, index);
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& symbolTable, const std::std::unordered_map<TemplateParameterSymbol*, TypeSymbol*>&templateParameterMap,
183 const Span& span, const 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(symbolTable, templateParameterMap, span, moduleId);
189 if (templateArgumentType)
190 {
191 targetTemplateArgumentTypes.push_back(templateArgumentType);
192 }
193 else
194 {
195 return nullptr;
196 }
197 }
198 return symbolTable.MakeClassTemplateSpecialization(classTemplate, targetTemplateArgumentTypes, span, GetRootModuleForCurrentThread()->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 } }