1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/symbols/EnumSymbol.hpp>
  7 #include <cmajor/symbols/SymbolTable.hpp>
  8 #include <cmajor/symbols/SymbolWriter.hpp>
  9 #include <cmajor/symbols/SymbolReader.hpp>
 10 #include <cmajor/symbols/Exception.hpp>
 11 #include <cmajor/symbols/SymbolCollector.hpp>
 12 #include <cmajor/symbols/Module.hpp>
 13 #include <soulng/util/Unicode.hpp>
 14 #include <boost/uuid/uuid_io.hpp>
 15 
 16 namespace cmajor { namespace symbols {
 17 
 18 using namespace soulng::unicode;
 19 
 20 EnumTypeSymbol::EnumTypeSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 21     TypeSymbol(SymbolType::enumTypeSymbolspan_sourceModuleId_name_)underlyingType()
 22 {
 23 }
 24 
 25 void EnumTypeSymbol::Write(SymbolWriter& writer)
 26 {
 27     TypeSymbol::Write(writer);
 28     writer.GetBinaryWriter().Write(underlyingType->TypeId());
 29 }
 30 
 31 void EnumTypeSymbol::Read(SymbolReader& reader)
 32 {
 33     TypeSymbol::Read(reader);
 34     boost::uuids::uuid underlyingTypeId;
 35     reader.GetBinaryReader().ReadUuid(underlyingTypeId);
 36     reader.GetSymbolTable()->EmplaceTypeRequest(readerthisunderlyingTypeId0);
 37 }
 38 
 39 void EnumTypeSymbol::EmplaceType(TypeSymbol* typeSymbolint index)
 40 {
 41     Assert(index == 0"invalid emplace type index");
 42     underlyingType = typeSymbol;
 43 }
 44 
 45 std::string EnumTypeSymbol::Syntax() const
 46 {
 47     std::string syntax = GetSpecifierStr();
 48     if (!syntax.empty())
 49     {
 50         syntax.append(1' ');
 51     }
 52     syntax.append("enum ");
 53     syntax.append(ToUtf8(DocName()));
 54     syntax.append(1';');
 55     return syntax;
 56 }
 57 
 58 void EnumTypeSymbol::Accept(SymbolCollector* collector)
 59 {
 60     if (IsProject() && Access() == SymbolAccess::public_)
 61     {
 62         collector->AddEnumeratedType(this);
 63     }
 64 }
 65 
 66 void EnumTypeSymbol::CollectMembers(SymbolCollector* collector)
 67 {
 68     TypeSymbol::Accept(collector);
 69 }
 70 
 71 void EnumTypeSymbol::Dump(CodeFormatter& formatter)
 72 {
 73     formatter.WriteLine(ToUtf8(Name()));
 74     formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
 75     formatter.WriteLine("underlying type: " + ToUtf8(underlyingType->FullName()));
 76     formatter.WriteLine("typeid: " + boost::uuids::to_string(TypeId()));
 77     formatter.WriteLine("enumeration constants:");
 78     formatter.IncIndent();
 79     SymbolCollector collector;
 80     TypeSymbol::Accept(&collector);
 81     for (EnumConstantSymbol* enumConstant : collector.EnumerationConstants())
 82     {
 83         formatter.WriteLine();
 84         enumConstant->Dump(formatter);
 85     }
 86     formatter.DecIndent();
 87 }
 88 
 89 void EnumTypeSymbol::SetSpecifiers(Specifiers specifiers)
 90 {
 91     Specifiers accessSpecifiers = specifiers & Specifiers::access_;
 92     SetAccess(accessSpecifiers);
 93     if ((specifiers & Specifiers::static_) != Specifiers::none)
 94     {
 95         throw Exception("enumerated type cannot be static"GetSpan()SourceModuleId());
 96     }
 97     if ((specifiers & Specifiers::virtual_) != Specifiers::none)
 98     {
 99         throw Exception("enumerated type cannot be virtual"GetSpan()SourceModuleId());
100     }
101     if ((specifiers & Specifiers::override_) != Specifiers::none)
102     {
103         throw Exception("enumerated type cannot be override"GetSpan()SourceModuleId());
104     }
105     if ((specifiers & Specifiers::abstract_) != Specifiers::none)
106     {
107         throw Exception("enumerated type cannot be abstract"GetSpan()SourceModuleId());
108     }
109     if ((specifiers & Specifiers::inline_) != Specifiers::none)
110     {
111         throw Exception("enumerated type cannot be inline"GetSpan()SourceModuleId());
112     }
113     if ((specifiers & Specifiers::explicit_) != Specifiers::none)
114     {
115         throw Exception("enumerated type cannot be explicit"GetSpan()SourceModuleId());
116     }
117     if ((specifiers & Specifiers::external_) != Specifiers::none)
118     {
119         throw Exception("enumerated type cannot be external"GetSpan()SourceModuleId());
120     }
121     if ((specifiers & Specifiers::suppress_) != Specifiers::none)
122     {
123         throw Exception("enumerated type cannot be suppressed"GetSpan()SourceModuleId());
124     }
125     if ((specifiers & Specifiers::default_) != Specifiers::none)
126     {
127         throw Exception("enumerated type cannot be default"GetSpan()SourceModuleId());
128     }
129     if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
130     {
131         throw Exception("enumerated type cannot be constexpr"GetSpan()SourceModuleId());
132     }
133     if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
134     {
135         throw Exception("enumerated type cannot be cdecl"GetSpan()SourceModuleId());
136     }
137     if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
138     {
139         throw Exception("enumerated type cannot be nothrow"GetSpan()SourceModuleId());
140     }
141     if ((specifiers & Specifiers::throw_) != Specifiers::none)
142     {
143         throw Exception("enumerated type cannot be throw"GetSpan()SourceModuleId());
144     }
145     if ((specifiers & Specifiers::new_) != Specifiers::none)
146     {
147         throw Exception("enumerated type cannot be new"GetSpan()SourceModuleId());
148     }
149     if ((specifiers & Specifiers::const_) != Specifiers::none)
150     {
151         throw Exception("enumerated type cannot be const"GetSpan()SourceModuleId());
152     }
153     if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
154     {
155         throw Exception("enumerated type cannot be unit_test"GetSpan()SourceModuleId());
156     }
157 }
158 
159 std::std::vector<EnumConstantSymbol*>EnumTypeSymbol::GetEnumConstants()
160 {
161     SymbolCollector collector;
162     TypeSymbol::Accept(&collector);
163     return collector.EnumerationConstants();
164 }
165 
166 ValueType EnumTypeSymbol::GetValueType() const
167 {
168     return underlyingType->GetValueType();
169 }
170 
171 Value* EnumTypeSymbol::MakeValue() const
172 {
173     return underlyingType->MakeValue();
174 }
175 
176 std::u32string EnumTypeSymbol::Id() const
177 {
178     return MangledName();
179 }
180 
181 void* EnumTypeSymbol::CreateDIType(Emitter& emitter)
182 {
183     uint64_t sizeInBits = SizeInBits(emitter);
184     uint32_t alignInBits = AlignmentInBits(emitter);
185     std::vector<void*> elements;
186     std::vector<EnumConstantSymbol*> enumConstants = GetEnumConstants();
187     for (EnumConstantSymbol* enumConstant : enumConstants)
188     {
189         int64_t value = 0;
190         if (underlyingType->IsUnsignedType())
191         {
192             Value* val = enumConstant->GetValue()->As(GetRootModuleForCurrentThread()->GetSymbolTable().GetTypeByName(U"ulong")falseGetSpan()SourceModuleId()true);
193             if (val)
194             {
195                 ULongValue* ulongValue = static_cast<ULongValue*>(val);
196                 value = static_cast<int64_t>(ulongValue->GetValue());
197             }
198         }
199         else
200         {
201             Value* val = enumConstant->GetValue()->As(GetRootModuleForCurrentThread()->GetSymbolTable().GetTypeByName(U"long")falseGetSpan()SourceModuleId()true);
202             if (val)
203             {
204                 LongValue* longValue = static_cast<LongValue*>(val);
205                 value = longValue->GetValue();
206             }
207         }
208         elements.push_back(emitter.CreateDITypeForEnumConstant(ToUtf8(enumConstant->Name())value));
209     }
210     return emitter.CreateDITypeForEnumType(ToUtf8(Name())ToUtf8(MangledName())GetSpan()SourceModuleId()elementssizeInBitsalignInBitsunderlyingType->GetDIType(emitter));
211 }
212 
213 void EnumTypeSymbol::Check()
214 {
215     TypeSymbol::Check();
216     if (!underlyingType)
217     {
218         throw SymbolCheckException( "enumerated type symbol has no underlying type"GetSpan()SourceModuleId());
219     }
220 }
221 
222 EnumConstantSymbol::EnumConstantSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
223     Symbol(SymbolType::enumConstantSymbolspan_sourceModuleId_name_)evaluating(false)
224 {
225 }
226 
227 void EnumConstantSymbol::SetValue(Value* value_)
228 {
229     value.reset(value_);
230 }
231 
232 void EnumConstantSymbol::Accept(SymbolCollector* collector)
233 {
234     if (IsProject())
235     {
236         collector->AddEnumerationConstant(this);
237     }
238 }
239 
240 void EnumConstantSymbol::Dump(CodeFormatter& formatter)
241 {
242     formatter.WriteLine(ToUtf8(Name()));
243     formatter.WriteLine("value: " + value->ToString());
244 }
245 
246 void EnumConstantSymbol::Write(SymbolWriter& writer)
247 {
248     Symbol::Write(writer);
249     WriteValue(value.get()writer.GetBinaryWriter());
250     writer.GetBinaryWriter().Write(strValue);
251 }
252 
253 void EnumConstantSymbol::Read(SymbolReader& reader)
254 {
255     Symbol::Read(reader);
256     value = ReadValue(reader.GetBinaryReader()GetSpan()SourceModuleId());
257     strValue = reader.GetBinaryReader().ReadUtf32String();
258 }
259 
260 EnumTypeDefaultConstructor::EnumTypeDefaultConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
261     FunctionSymbol(SymbolType::enumTypeDefaultConstructorspan_sourceModuleId_name_)underlyingTypeDefaultConstructor(nullptr)
262 {
263 }
264 
265 EnumTypeDefaultConstructor::EnumTypeDefaultConstructor(EnumTypeSymbol* enumType_) :
266     FunctionSymbol(SymbolType::enumTypeDefaultConstructorenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeDefaultConstructor")underlyingTypeDefaultConstructor(nullptr)
267 {
268     SetGroupName(U"@constructor");
269     SetAccess(SymbolAccess::public_);
270     ParameterSymbol* thisParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"this");
271     thisParam->SetType(enumType_->AddPointer(Span()boost::uuids::nil_uuid()));
272     AddMember(thisParam);
273     ComputeName();
274     TypeSymbol* underlyingType = enumType_->UnderlyingType();
275     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
276     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
277     underlyingTypeDefaultConstructor = basicTypeSymbol->DefaultConstructor();
278 }
279 
280 void EnumTypeDefaultConstructor::Write(SymbolWriter& writer)
281 {
282     FunctionSymbol::Write(writer);
283     Assert(underlyingTypeDefaultConstructor"underlying default constructor not set");
284     const boost::uuids::uuid& defaultConstructorId = underlyingTypeDefaultConstructor->FunctionId();
285     writer.GetBinaryWriter().Write(defaultConstructorId);
286 }
287 
288 void EnumTypeDefaultConstructor::Read(SymbolReader& reader)
289 {
290     FunctionSymbol::Read(reader);
291     boost::uuids::uuid defaultConstructorId;
292     reader.GetBinaryReader().ReadUuid(defaultConstructorId);
293     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthisdefaultConstructorId0);
294 }
295 
296 void EnumTypeDefaultConstructor::EmplaceFunction(FunctionSymbol* functionSymbolint index)
297 {
298     if (index == 0)
299     {
300         underlyingTypeDefaultConstructor = functionSymbol;
301     }
302     else
303     {
304         Assert(false"invalid emplace function index");
305     }
306 }
307 
308 void EnumTypeDefaultConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
309 {
310     Assert(underlyingTypeDefaultConstructor"underlying default constructor not set");
311     underlyingTypeDefaultConstructor->GenerateCall(emittergenObjectsflagsspanmoduleId);
312 }
313 
314 void EnumTypeDefaultConstructor::Check()
315 {
316     FunctionSymbol::Check();
317     if (!underlyingTypeDefaultConstructor)
318     {
319         throw SymbolCheckException("enumerated type default constructor has no underlying type default constructor"GetSpan()SourceModuleId());
320     }
321 }
322 
323 EnumTypeCopyConstructor::EnumTypeCopyConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
324     FunctionSymbol(SymbolType::enumTypeCopyConstructorspan_sourceModuleId_name_)underlyingTypeCopyConstructor(nullptr)
325 {
326 }
327 
328 EnumTypeCopyConstructor::EnumTypeCopyConstructor(EnumTypeSymbol* enumType_) :
329     FunctionSymbol(SymbolType::enumTypeCopyConstructorenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeCopyConstructor")underlyingTypeCopyConstructor(nullptr)
330 {
331     SetGroupName(U"@constructor");
332     SetAccess(SymbolAccess::public_);
333     ParameterSymbol* thisParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"this");
334     thisParam->SetType(enumType_->AddPointer(Span()boost::uuids::nil_uuid()));
335     AddMember(thisParam);
336     ParameterSymbol* thatParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"that");
337     thatParam->SetType(enumType_);
338     AddMember(thatParam);
339     ComputeName();
340     TypeSymbol* underlyingType = enumType_->UnderlyingType();
341     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
342     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
343     underlyingTypeCopyConstructor = basicTypeSymbol->CopyConstructor();
344 }
345 
346 void EnumTypeCopyConstructor::Write(SymbolWriter& writer)
347 {
348     FunctionSymbol::Write(writer);
349     Assert(underlyingTypeCopyConstructor"underlying copy constructor not set");
350     const boost::uuids::uuid& copyConstructorId = underlyingTypeCopyConstructor->FunctionId();
351     writer.GetBinaryWriter().Write(copyConstructorId);
352 }
353 
354 void EnumTypeCopyConstructor::Read(SymbolReader& reader)
355 {
356     FunctionSymbol::Read(reader);
357     boost::uuids::uuid copyConstructorId;
358     reader.GetBinaryReader().ReadUuid(copyConstructorId);
359     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthiscopyConstructorId0);
360 }
361 
362 void EnumTypeCopyConstructor::EmplaceFunction(FunctionSymbol* functionSymbolint index)
363 {
364     if (index == 0)
365     {
366         underlyingTypeCopyConstructor = functionSymbol;
367     }
368     else
369     {
370         Assert(false"invalid emplace function index");
371     }
372 }
373 
374 void EnumTypeCopyConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
375 {
376     Assert(underlyingTypeCopyConstructor"underlying copy constructor not set");
377     underlyingTypeCopyConstructor->GenerateCall(emittergenObjectsflagsspanmoduleId);
378 }
379 
380 void EnumTypeCopyConstructor::Check()
381 {
382     FunctionSymbol::Check();
383     if (!underlyingTypeCopyConstructor)
384     {
385         throw SymbolCheckException("enumerated type copy constructor has no underlying type copy constructor"GetSpan()SourceModuleId());
386     }
387 }
388 
389 EnumTypeMoveConstructor::EnumTypeMoveConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
390     FunctionSymbol(SymbolType::enumTypeMoveConstructorspan_sourceModuleId_name_)underlyingTypeMoveConstructor(nullptr)
391 {
392 }
393 
394 EnumTypeMoveConstructor::EnumTypeMoveConstructor(EnumTypeSymbol* enumType_) :
395     FunctionSymbol(SymbolType::enumTypeMoveConstructorenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeMoveConstructor")underlyingTypeMoveConstructor(nullptr)
396 {
397     SetGroupName(U"@constructor");
398     SetAccess(SymbolAccess::public_);
399     ParameterSymbol* thisParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"this");
400     thisParam->SetType(enumType_->AddPointer(Span()boost::uuids::nil_uuid()));
401     AddMember(thisParam);
402     ParameterSymbol* thatParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"that");
403     thatParam->SetType(enumType_->AddRvalueReference(Span()boost::uuids::nil_uuid()));
404     AddMember(thatParam);
405     ComputeName();
406     TypeSymbol* underlyingType = enumType_->UnderlyingType();
407     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
408     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
409     underlyingTypeMoveConstructor = basicTypeSymbol->MoveConstructor();
410 }
411 
412 void EnumTypeMoveConstructor::Write(SymbolWriter& writer)
413 {
414     FunctionSymbol::Write(writer);
415     Assert(underlyingTypeMoveConstructor"underlying move constructor not set");
416     const boost::uuids::uuid& moveConstructorId = underlyingTypeMoveConstructor->FunctionId();
417     writer.GetBinaryWriter().Write(moveConstructorId);
418 }
419 
420 void EnumTypeMoveConstructor::Read(SymbolReader& reader)
421 {
422     FunctionSymbol::Read(reader);
423     boost::uuids::uuid moveConstructorId;
424     reader.GetBinaryReader().ReadUuid(moveConstructorId);
425     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthismoveConstructorId0);
426 }
427 
428 void EnumTypeMoveConstructor::EmplaceFunction(FunctionSymbol* functionSymbolint index)
429 {
430     if (index == 0)
431     {
432         underlyingTypeMoveConstructor = functionSymbol;
433     }
434     else
435     {
436         Assert(false"invalid emplace function index");
437     }
438 }
439 
440 void EnumTypeMoveConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
441 {
442     Assert(underlyingTypeMoveConstructor"underlying move constructor not set");
443     underlyingTypeMoveConstructor->GenerateCall(emittergenObjectsflagsspanmoduleId);
444 }
445 
446 void EnumTypeMoveConstructor::Check()
447 {
448     FunctionSymbol::Check();
449     if (!underlyingTypeMoveConstructor)
450     {
451         throw SymbolCheckException("enumerated type move constructor has no underlying type move constructor"GetSpan()SourceModuleId());
452     }
453 }
454 
455 EnumTypeCopyAssignment::EnumTypeCopyAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
456     FunctionSymbol(SymbolType::enumTypeCopyAssignmentspan_sourceModuleId_name_)underlyingTypeCopyAssignment(nullptr)
457 {
458 }
459 
460 EnumTypeCopyAssignment::EnumTypeCopyAssignment(EnumTypeSymbol* enumType_TypeSymbol* voidType_) :
461     FunctionSymbol(SymbolType::enumTypeCopyAssignmentenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeCopyAssignment")underlyingTypeCopyAssignment(nullptr)
462 {
463     SetGroupName(U"operator=");
464     SetAccess(SymbolAccess::public_);
465     ParameterSymbol* thisParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"this");
466     thisParam->SetType(enumType_->AddPointer(Span()boost::uuids::nil_uuid()));
467     AddMember(thisParam);
468     ParameterSymbol* thatParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"that");
469     thatParam->SetType(enumType_);
470     AddMember(thatParam);
471     SetReturnType(voidType_);
472     ComputeName();
473     TypeSymbol* underlyingType = enumType_->UnderlyingType();
474     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
475     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
476     underlyingTypeCopyAssignment = basicTypeSymbol->CopyAssignment();
477 }
478 
479 void EnumTypeCopyAssignment::Write(SymbolWriter& writer)
480 {
481     FunctionSymbol::Write(writer);
482     Assert(underlyingTypeCopyAssignment"underlying copy assignment not set");
483     const boost::uuids::uuid& copyAssignmentId = underlyingTypeCopyAssignment->FunctionId();
484     writer.GetBinaryWriter().Write(copyAssignmentId);
485 }
486 
487 void EnumTypeCopyAssignment::Read(SymbolReader& reader)
488 {
489     FunctionSymbol::Read(reader);
490     boost::uuids::uuid copyAssignmentId;
491     reader.GetBinaryReader().ReadUuid(copyAssignmentId);
492     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthiscopyAssignmentId0);
493 }
494 
495 void EnumTypeCopyAssignment::EmplaceFunction(FunctionSymbol* functionSymbolint index)
496 {
497     if (index == 0)
498     {
499         underlyingTypeCopyAssignment = functionSymbol;
500     }
501     else
502     {
503         Assert(false"invalid emplace function index");
504     }
505 }
506 
507 void EnumTypeCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
508 {
509     Assert(underlyingTypeCopyAssignment"underlying copy assignment not set");
510     underlyingTypeCopyAssignment->GenerateCall(emittergenObjectsflagsspanmoduleId);
511 }
512 
513 void EnumTypeCopyAssignment::Check()
514 {
515     FunctionSymbol::Check();
516     if (!underlyingTypeCopyAssignment)
517     {
518         throw SymbolCheckException("enumerated type copy assignment has no underlying type copy assignment"GetSpan()SourceModuleId());
519     }
520 }
521 
522 EnumTypeMoveAssignment::EnumTypeMoveAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
523     FunctionSymbol(SymbolType::enumTypeMoveAssignmentspan_sourceModuleId_name_)underlyingTypeMoveAssignment(nullptr)
524 {
525 }
526 
527 EnumTypeMoveAssignment::EnumTypeMoveAssignment(EnumTypeSymbol* enumType_TypeSymbol* voidType_) :
528     FunctionSymbol(SymbolType::enumTypeMoveAssignmentenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeMoveAssignment")underlyingTypeMoveAssignment(nullptr)
529 {
530     SetGroupName(U"operator=");
531     SetAccess(SymbolAccess::public_);
532     ParameterSymbol* thisParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"this");
533     thisParam->SetType(enumType_->AddPointer(Span()boost::uuids::nil_uuid()));
534     AddMember(thisParam);
535     ParameterSymbol* thatParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"that");
536     thatParam->SetType(enumType_->AddRvalueReference(Span()boost::uuids::nil_uuid()));
537     AddMember(thatParam);
538     SetReturnType(voidType_);
539     ComputeName();
540     TypeSymbol* underlyingType = enumType_->UnderlyingType();
541     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
542     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
543     underlyingTypeMoveAssignment = basicTypeSymbol->MoveAssignment();
544 }
545 
546 void EnumTypeMoveAssignment::Write(SymbolWriter& writer)
547 {
548     FunctionSymbol::Write(writer);
549     Assert(underlyingTypeMoveAssignment"underlying move assignment not set");
550     const boost::uuids::uuid& moveAssignmentId = underlyingTypeMoveAssignment->FunctionId();
551     writer.GetBinaryWriter().Write(moveAssignmentId);
552 }
553 
554 void EnumTypeMoveAssignment::Read(SymbolReader& reader)
555 {
556     FunctionSymbol::Read(reader);
557     boost::uuids::uuid moveAssignmentId;
558     reader.GetBinaryReader().ReadUuid(moveAssignmentId);
559     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthismoveAssignmentId0);
560 }
561 
562 void EnumTypeMoveAssignment::EmplaceFunction(FunctionSymbol* functionSymbolint index)
563 {
564     if (index == 0)
565     {
566         underlyingTypeMoveAssignment = functionSymbol;
567     }
568     else
569     {
570         Assert(false"invalid emplace function index");
571     }
572 }
573 
574 void EnumTypeMoveAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
575 {
576     Assert(underlyingTypeMoveAssignment"underlying move assignment not set");
577     underlyingTypeMoveAssignment->GenerateCall(emittergenObjectsflagsspanmoduleId);
578 }
579 
580 void EnumTypeMoveAssignment::Check()
581 {
582     FunctionSymbol::Check();
583     if (!underlyingTypeMoveAssignment)
584     {
585         throw SymbolCheckException( "enumerated type move assignment has no underlying type move assignment"GetSpan()SourceModuleId());
586     }
587 }
588 
589 EnumTypeReturn::EnumTypeReturn(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
590     FunctionSymbol(SymbolType::enumTypeReturnspan_sourceModuleId_name_)underlyingTypeReturn(nullptr)
591 {
592 }
593 
594 EnumTypeReturn::EnumTypeReturn(EnumTypeSymbol* enumType_) :
595     FunctionSymbol(SymbolType::enumTypeReturnenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeReturn")underlyingTypeReturn(nullptr)
596 {
597     SetGroupName(U"@return");
598     SetAccess(SymbolAccess::public_);
599     ParameterSymbol* valueParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"value");
600     valueParam->SetType(enumType_);
601     AddMember(valueParam);
602     SetReturnType(enumType_);
603     ComputeName();
604     TypeSymbol* underlyingType = enumType_->UnderlyingType();
605     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
606     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
607     underlyingTypeReturn = basicTypeSymbol->ReturnFun();
608 }
609 
610 void EnumTypeReturn::Write(SymbolWriter& writer)
611 {
612     FunctionSymbol::Write(writer);
613     Assert(underlyingTypeReturn"underlying return not set");
614     const boost::uuids::uuid& returnId = underlyingTypeReturn->FunctionId();
615     writer.GetBinaryWriter().Write(returnId);
616 }
617 
618 void EnumTypeReturn::Read(SymbolReader& reader)
619 {
620     FunctionSymbol::Read(reader);
621     boost::uuids::uuid returnId;
622     reader.GetBinaryReader().ReadUuid(returnId);
623     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthisreturnId0);
624 }
625 
626 void EnumTypeReturn::EmplaceFunction(FunctionSymbol* functionSymbolint index)
627 {
628     if (index == 0)
629     {
630         underlyingTypeReturn = functionSymbol;
631     }
632     else
633     {
634         Assert(false"invalid emplace function index");
635     }
636 }
637 
638 void EnumTypeReturn::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
639 {
640     Assert(underlyingTypeReturn"underlying return not set");
641     underlyingTypeReturn->GenerateCall(emittergenObjectsflagsspanmoduleId);
642 }
643 
644 void EnumTypeReturn::Check()
645 {
646     FunctionSymbol::Check();
647     if (!underlyingTypeReturn)
648     {
649         throw SymbolCheckException("enumerated type return has no underlying type return"GetSpan()SourceModuleId());
650     }
651 }
652 
653 EnumTypeEqualityOp::EnumTypeEqualityOp(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
654     FunctionSymbol(SymbolType::enumTypeEqualityspan_sourceModuleId_name_)underlyingTypeEquality(nullptr)
655 {
656 }
657 
658 EnumTypeEqualityOp::EnumTypeEqualityOp(EnumTypeSymbol* enumType_TypeSymbol* boolType_) :
659     FunctionSymbol(SymbolType::enumTypeEqualityenumType_->GetSpan()enumType_->SourceModuleId()U"enumTypeEquality")underlyingTypeEquality(nullptr)
660 {
661     SetGroupName(U"operator==");
662     SetAccess(SymbolAccess::public_);
663     ParameterSymbol* leftParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"left");
664     leftParam->SetType(enumType_);
665     AddMember(leftParam);
666     ParameterSymbol* rightParam = new ParameterSymbol(enumType_->GetSpan()enumType_->SourceModuleId()U"right");
667     rightParam->SetType(enumType_);
668     AddMember(rightParam);
669     SetReturnType(boolType_);
670     ComputeName();
671     TypeSymbol* underlyingType = enumType_->UnderlyingType();
672     Assert(underlyingType->IsBasicTypeSymbol()"basic type expected");
673     BasicTypeSymbol* basicTypeSymbol = static_cast<BasicTypeSymbol*>(underlyingType);
674     underlyingTypeEquality = basicTypeSymbol->EqualityOp();
675 }
676 
677 void EnumTypeEqualityOp::Write(SymbolWriter& writer)
678 {
679     FunctionSymbol::Write(writer);
680     Assert(underlyingTypeEquality"underlying equality not set");
681     const boost::uuids::uuid& equalityId = underlyingTypeEquality->FunctionId();
682     writer.GetBinaryWriter().Write(equalityId);
683 }
684 
685 void EnumTypeEqualityOp::Read(SymbolReader& reader)
686 {
687     FunctionSymbol::Read(reader);
688     boost::uuids::uuid equalityId;
689     reader.GetBinaryReader().ReadUuid(equalityId);
690     reader.GetSymbolTable()->EmplaceFunctionRequest(readerthisequalityId0);
691 }
692 
693 void EnumTypeEqualityOp::EmplaceFunction(FunctionSymbol* functionSymbolint index)
694 {
695     if (index == 0)
696     {
697         underlyingTypeEquality = functionSymbol;
698     }
699     else
700     {
701         Assert(false"invalid emplace function index");
702     }
703 }
704 
705 void EnumTypeEqualityOp::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
706 {
707     Assert(underlyingTypeEquality"underlying equality not set");
708     underlyingTypeEquality->GenerateCall(emittergenObjectsflagsspanmoduleId);
709 }
710 
711 void EnumTypeEqualityOp::Check()
712 {
713     FunctionSymbol::Check();
714     if (!underlyingTypeEquality)
715     {
716         throw SymbolCheckException("enumerated type equality operation has no underlying type equality operation"GetSpan()SourceModuleId());
717     }
718 }
719 
720 EnumTypeToUnderlyingTypeConversion::EnumTypeToUnderlyingTypeConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
721     FunctionSymbol(SymbolType::enumTypeToUnderlyingTypespan_sourceModuleId_name_)sourceType()targetType()
722 {
723     SetGroupName(U"@conversion");
724 }
725 
726 EnumTypeToUnderlyingTypeConversion::EnumTypeToUnderlyingTypeConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_TypeSymbol* sourceType_TypeSymbol* targetType_) :
727     FunctionSymbol(SymbolType::enumTypeToUnderlyingTypespan_sourceModuleId_name_)sourceType(sourceType_)targetType(targetType_)
728 {
729     SetConversion();
730     SetGroupName(U"@conversion");
731     SetConversionSourceType(sourceType->PlainType(GetSpan()SourceModuleId()));
732     SetConversionTargetType(targetType->PlainType(GetSpan()SourceModuleId()));
733 }
734 
735 void EnumTypeToUnderlyingTypeConversion::Write(SymbolWriter& writer)
736 {
737     FunctionSymbol::Write(writer);
738     writer.GetBinaryWriter().Write(sourceType->TypeId());
739     writer.GetBinaryWriter().Write(targetType->TypeId());
740 }
741 
742 void EnumTypeToUnderlyingTypeConversion::Read(SymbolReader& reader)
743 {
744     FunctionSymbol::Read(reader);
745     boost::uuids::uuid sourceTypeId;
746     reader.GetBinaryReader().ReadUuid(sourceTypeId);
747     reader.GetSymbolTable()->EmplaceTypeRequest(readerthissourceTypeId1);
748     boost::uuids::uuid targetTypeId;
749     reader.GetBinaryReader().ReadUuid(targetTypeId);
750     reader.GetSymbolTable()->EmplaceTypeRequest(readerthistargetTypeId2);
751 }
752 
753 void EnumTypeToUnderlyingTypeConversion::EmplaceType(TypeSymbol* typeSymbolint index)
754 {
755     if (index == 1)
756     {
757         sourceType = typeSymbol;
758     }
759     else if (index == 2)
760     {
761         targetType = typeSymbol;
762     }
763     else
764     {
765         FunctionSymbol::EmplaceType(typeSymbolindex);
766     }
767 }
768 
769 void EnumTypeToUnderlyingTypeConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
770 {
771 }
772 
773 void EnumTypeToUnderlyingTypeConversion::Check()
774 {
775     FunctionSymbol::Check();
776     if (!sourceType)
777     {
778         throw SymbolCheckException("enum type to underlying type conversion has no source type"GetSpan()SourceModuleId());
779     }
780     if (!targetType)
781     {
782         throw SymbolCheckException("enum type to underlying type conversion has no target type"GetSpan()SourceModuleId());
783     }
784 }
785 
786 UnderlyingTypeToEnumTypeConversion::UnderlyingTypeToEnumTypeConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_)
787     : FunctionSymbol(SymbolType::underlyingToEnumTypespan_sourceModuleId_name_)sourceType()targetType()
788 {
789     SetGroupName(U"@conversion");
790 }
791 
792 UnderlyingTypeToEnumTypeConversion::UnderlyingTypeToEnumTypeConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_TypeSymbol* sourceType_TypeSymbol* targetType_)
793     : FunctionSymbol(SymbolType::underlyingToEnumTypespan_sourceModuleId_name_)sourceType(sourceType_)targetType(targetType_)
794 {
795     SetConversion();
796     SetGroupName(U"@conversion");
797     SetConversionSourceType(sourceType->PlainType(GetSpan()SourceModuleId()));
798     SetConversionTargetType(targetType->PlainType(GetSpan()SourceModuleId()));
799 }
800 
801 void UnderlyingTypeToEnumTypeConversion::Write(SymbolWriter& writer)
802 {
803     FunctionSymbol::Write(writer);
804     writer.GetBinaryWriter().Write(sourceType->TypeId());
805     writer.GetBinaryWriter().Write(targetType->TypeId());
806 }
807 
808 void UnderlyingTypeToEnumTypeConversion::Read(SymbolReader& reader)
809 {
810     FunctionSymbol::Read(reader);
811     boost::uuids::uuid sourceTypeId;
812     reader.GetBinaryReader().ReadUuid(sourceTypeId);
813     reader.GetSymbolTable()->EmplaceTypeRequest(readerthissourceTypeId1);
814     boost::uuids::uuid targetTypeId;
815     reader.GetBinaryReader().ReadUuid(targetTypeId);
816     reader.GetSymbolTable()->EmplaceTypeRequest(readerthistargetTypeId2);
817 }
818 
819 void UnderlyingTypeToEnumTypeConversion::EmplaceType(TypeSymbol* typeSymbolint index)
820 {
821     if (index == 1)
822     {
823         sourceType = typeSymbol;
824     }
825     else if (index == 2)
826     {
827         targetType = typeSymbol;
828     }
829     else
830     {
831         FunctionSymbol::EmplaceType(typeSymbolindex);
832     }
833 }
834 
835 void UnderlyingTypeToEnumTypeConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
836 {
837 }
838 
839 void UnderlyingTypeToEnumTypeConversion::Check()
840 {
841     FunctionSymbol::Check();
842     if (!sourceType)
843     {
844         throw SymbolCheckException("underlying type to enum type conversion has no source type"GetSpan()SourceModuleId());
845     }
846     if (!targetType)
847     {
848         throw SymbolCheckException("underlying type to enum type conversion has no target type"GetSpan()SourceModuleId());
849     }
850 }
851 
852 } } // namespace cmajor::symbols