1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcm/ast/Class.hpp>
  7 #include <sngcm/ast/Visitor.hpp>
  8 #include <sngcm/ast/Identifier.hpp>
  9 
 10 namespace sngcm { namespace ast {
 11 
 12 ClassNode::ClassNode(const Span& span_const boost::uuids::uuid& moduleId_) :
 13     Node(NodeType::classNodespan_moduleId_)specifiers(Specifiers::none)id()templateParameters()baseClassOrInterfaces()members()
 14 {
 15 }
 16 
 17 ClassNode::ClassNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_IdentifierNode* id_AttributesNode* attributes_) :
 18     Node(NodeType::classNodespan_moduleId_)specifiers(specifiers_)id(id_)templateParameters()baseClassOrInterfaces()members()attributes(attributes_)
 19 {
 20 }
 21 
 22 Node* ClassNode::Clone(CloneContext& cloneContext) const
 23 {
 24     AttributesNode* clonedAttributes = nullptr;
 25     if (attributes)
 26     {
 27         clonedAttributes = static_cast<AttributesNode*>(attributes->Clone(cloneContext));
 28     }
 29     ClassNode* clone = new ClassNode(GetSpan()ModuleId()specifiersstatic_cast<IdentifierNode*>(id->Clone(cloneContext))clonedAttributes);
 30     if (!cloneContext.InstantiateClassNode())
 31     {
 32         int tn = templateParameters.Count();
 33         for (int i = 0; i < tn; ++i)
 34         {
 35             clone->AddTemplateParameter(static_cast<TemplateParameterNode*>(templateParameters[i]->Clone(cloneContext)));
 36         }
 37     }
 38     int bn = baseClassOrInterfaces.Count();
 39     for (int i = 0; i < bn; ++i)
 40     {
 41         clone->AddBaseClassOrInterface(baseClassOrInterfaces[i]->Clone(cloneContext));
 42     }
 43     if (constraint)
 44     {
 45         clone->SetConstraint(static_cast<WhereConstraintNode*>(constraint->Clone(cloneContext)));
 46     }
 47     int mn = members.Count();
 48     for (int i = 0; i < mn; ++i)
 49     {
 50         clone->AddMember(members[i]->Clone(cloneContext));
 51     }
 52     clone->SetSpecifierSpan(specifierSpan);
 53     clone->SetClassSpan(classSpan);
 54     clone->SetBeginBraceSpan(beginBraceSpan);
 55     clone->SetEndBraceSpan(endBraceSpan);
 56     return clone;
 57 }
 58 
 59 void ClassNode::Accept(Visitor& visitor)
 60 {
 61     visitor.Visit(*this);
 62 }
 63 
 64 void ClassNode::Write(AstWriter& writer)
 65 {
 66     Node::Write(writer);
 67     bool hasAttributes = attributes != nullptr;
 68     writer.GetBinaryWriter().Write(hasAttributes);
 69     if (hasAttributes)
 70     {
 71         writer.Write(attributes.get());
 72     }
 73     writer.Write(specifiers);
 74     writer.Write(id.get());
 75     templateParameters.Write(writer);
 76     baseClassOrInterfaces.Write(writer);
 77     members.Write(writer);
 78     bool convertExternal = ModuleId() == writer.SpanConversionModuleId();
 79     writer.Write(specifierSpanconvertExternal);
 80     writer.Write(classSpanconvertExternal);
 81     writer.Write(beginBraceSpanconvertExternal);
 82     writer.Write(endBraceSpanconvertExternal);
 83 }
 84 
 85 void ClassNode::Read(AstReader& reader)
 86 {
 87     Node::Read(reader);
 88     bool hasAttributes = reader.GetBinaryReader().ReadBool();
 89     if (hasAttributes)
 90     {
 91         attributes.reset(reader.ReadAttributesNode());
 92     }
 93     specifiers = reader.ReadSpecifiers();
 94     id.reset(reader.ReadIdentifierNode());
 95     id->SetParent(this);
 96     templateParameters.Read(reader);
 97     templateParameters.SetParent(this);
 98     baseClassOrInterfaces.Read(reader);
 99     baseClassOrInterfaces.SetParent(this);
100     members.Read(reader);
101     members.SetParent(this);
102     specifierSpan = reader.ReadSpan();
103     classSpan = reader.ReadSpan();
104     beginBraceSpan = reader.ReadSpan();
105     endBraceSpan = reader.ReadSpan();
106 }
107 
108 void ClassNode::AddTemplateParameter(TemplateParameterNode* templateParameter)
109 {
110     templateParameter->SetParent(this);
111     templateParameters.Add(templateParameter);
112 }
113 
114 void ClassNode::AddBaseClassOrInterface(Node* baseClassOrInterface)
115 {
116     baseClassOrInterface->SetParent(this);
117     baseClassOrInterfaces.Add(baseClassOrInterface);
118 }
119 
120 void ClassNode::SetConstraint(WhereConstraintNode* whereConstraint)
121 {
122     constraint.reset(whereConstraint);
123     constraint->SetParent(this);
124 }
125 
126 void ClassNode::AddMember(Node* member)
127 {
128     member->SetParent(this);
129     members.Add(member);
130 }
131 
132 void ClassNode::ArrangeMembers()
133 {
134     std::unique_ptr<Node> staticConstructor;
135     NodeList<Node> constructors;
136     std::unique_ptr<Node> destructor;
137     NodeList<Node> virtualMembers;
138     NodeList<Node> protectedMembers;
139     NodeList<Node> privateMembers;
140     int n = members.Count();
141     for (int i = 0; i < n; ++i)
142     {
143         Node* member = members[i];
144         if (member->GetNodeType() == NodeType::staticConstructorNode)
145         {
146             staticConstructor.reset(members.Release(i));
147         }
148         else if (member->GetNodeType() == NodeType::constructorNode)
149         {
150             constructors.Add(members.Release(i));
151         }
152         else if (member->GetNodeType() == NodeType::destructorNode)
153         {
154             destructor.reset(members.Release(i));
155         }
156         else
157         {
158             Specifiers specifiers = member->GetSpecifiers();
159             if ((specifiers&(  Specifiers::abstract_ | Specifiers::override_ | Specifiers::virtual_)) != Specifiers::none)
160             {
161                 virtualMembers.Add(members.Release(i));
162             }
163             else if ((specifiers & Specifiers::protected_) != Specifiers::none)
164             {
165                 protectedMembers.Add(members.Release(i));
166             }
167             else if ((specifiers & Specifiers::private_) != Specifiers::none)
168             {
169                 privateMembers.Add(members.Release(i));
170             }
171         }
172     }
173     members.RemoveEmpty();
174     int index = 0;
175     if (staticConstructor)
176     {
177         members.Insert(indexstaticConstructor.release());
178         ++index;
179     }
180     int nc = constructors.Count();
181     if (nc > 0)
182     {
183         for (int i = 0; i < nc; ++i)
184         {
185             members.Insert(indexconstructors.Release(i));
186             ++index;
187         }
188     }
189     if (destructor)
190     {
191         members.Insert(indexdestructor.release());
192         ++index;
193     }
194     if (virtualMembers.Count() > 0 || protectedMembers.Count() > 0 || privateMembers.Count() > 0)
195     {
196         for (int i = 0; i < virtualMembers.Count(); ++i)
197         {
198             members.Add(virtualMembers.Release(i));
199         }
200         for (int i = 0; i < protectedMembers.Count(); ++i)
201         {
202             members.Add(protectedMembers.Release(i));
203         }
204         for (int i = 0; i < privateMembers.Count(); ++i)
205         {
206             members.Add(privateMembers.Release(i));
207         }
208     }
209 }
210 
211 InitializerNode::InitializerNode(NodeType nodeType_const Span& span_const boost::uuids::uuid& moduleId_) : Node(nodeType_span_moduleId_)
212 {
213 }
214 
215 void InitializerNode::Write(AstWriter& writer)
216 {
217     Node::Write(writer);
218     arguments.Write(writer);
219 }
220 
221 void InitializerNode::Read(AstReader& reader)
222 {
223     Node::Read(reader);
224     arguments.Read(reader);
225     arguments.SetParent(this);
226 }
227 
228 void InitializerNode::AddArgument(Node* argument)
229 {
230     argument->SetParent(this);
231     arguments.Add(argument);
232 }
233 
234 ThisInitializerNode::ThisInitializerNode(const Span& span_const boost::uuids::uuid& moduleId_) : InitializerNode(NodeType::thisInitializerNodespan_moduleId_)
235 {
236 }
237 
238 Node* ThisInitializerNode::Clone(CloneContext& cloneContext) const
239 {
240     ThisInitializerNode* clone = new ThisInitializerNode(GetSpan()ModuleId());
241     int n = Arguments().Count();
242     for (int i = 0; i < n; ++i)
243     {
244         clone->AddArgument(Arguments()[i]->Clone(cloneContext));
245     }
246     return clone;
247 }
248 
249 void ThisInitializerNode::Accept(Visitor& visitor)
250 {
251     visitor.Visit(*this);
252 }
253 
254 BaseInitializerNode::BaseInitializerNode(const Span& span_const boost::uuids::uuid& moduleId_) : InitializerNode(NodeType::baseInitializerNodespan_moduleId_)
255 {
256 }
257 
258 Node* BaseInitializerNode::Clone(CloneContext& cloneContext) const
259 {
260     BaseInitializerNode* clone = new BaseInitializerNode(GetSpan()ModuleId());
261     int n = Arguments().Count();
262     for (int i = 0; i < n; ++i)
263     {
264         clone->AddArgument(Arguments()[i]->Clone(cloneContext));
265     }
266     return clone;
267 }
268 
269 void BaseInitializerNode::Accept(Visitor& visitor)
270 {
271     visitor.Visit(*this);
272 }
273 
274 MemberInitializerNode::MemberInitializerNode(const Span& span_const boost::uuids::uuid& moduleId_) : InitializerNode(NodeType::memberInitializerNodespan_moduleId_)memberId()
275 {
276 }
277 
278 MemberInitializerNode::MemberInitializerNode(const Span& span_const boost::uuids::uuid& moduleId_IdentifierNode* memberId_) :
279     InitializerNode(NodeType::memberInitializerNodespan_moduleId_)memberId(memberId_)
280 {
281     memberId->SetParent(this);
282 }
283 
284 Node* MemberInitializerNode::Clone(CloneContext& cloneContext) const
285 {
286     MemberInitializerNode* clone = new MemberInitializerNode(GetSpan()ModuleId()static_cast<IdentifierNode*>(memberId->Clone(cloneContext)));
287     int n = Arguments().Count();
288     for (int i = 0; i < n; ++i)
289     {
290         clone->AddArgument(Arguments()[i]->Clone(cloneContext));
291     }
292     return clone;
293 }
294 
295 void MemberInitializerNode::Accept(Visitor& visitor)
296 {
297     visitor.Visit(*this);
298 }
299 
300 void MemberInitializerNode::Write(AstWriter& writer)
301 {
302     InitializerNode::Write(writer);
303     writer.Write(memberId.get());
304 }
305 
306 void MemberInitializerNode::Read(AstReader& reader)
307 {
308     InitializerNode::Read(reader);
309     memberId.reset(reader.ReadIdentifierNode());
310     memberId->SetParent(this);
311 }
312 
313 StaticConstructorNode::StaticConstructorNode(const Span& span_const boost::uuids::uuid& moduleId_) :
314     FunctionNode(NodeType::staticConstructorNodespan_moduleId_Specifiers::nonenullptrU"@static_constructor"nullptr)initializers()
315 {
316 }
317 
318 StaticConstructorNode::StaticConstructorNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_AttributesNode* attributes_) :
319     FunctionNode(NodeType::staticConstructorNodespan_moduleId_specifiers_nullptrU"@static_constructor"attributes_)initializers()
320 {
321 }
322 
323 Node* StaticConstructorNode::Clone(CloneContext& cloneContext) const
324 {
325     StaticConstructorNode* clone = new StaticConstructorNode(GetSpan()ModuleId()GetSpecifiers()nullptr);
326     int n = initializers.Count();
327     for (int i = 0; i < n; ++i)
328     {
329         clone->AddInitializer(static_cast<InitializerNode*>(initializers[i]->Clone(cloneContext)));
330     }
331     clone->classId.reset(static_cast<IdentifierNode*>(classId->Clone(cloneContext)));
332     CloneContent(clonecloneContext);
333     return clone;
334 }
335 
336 void StaticConstructorNode::Accept(Visitor& visitor)
337 {
338     visitor.Visit(*this);
339 }
340 
341 void StaticConstructorNode::Write(AstWriter& writer)
342 {
343     FunctionNode::Write(writer);
344     initializers.Write(writer);
345     writer.Write(classId.get());
346 }
347 
348 void StaticConstructorNode::Read(AstReader& reader)
349 {
350     FunctionNode::Read(reader);
351     initializers.Read(reader);
352     initializers.SetParent(this);
353     classId.reset(reader.ReadIdentifierNode());
354 }
355 
356 void StaticConstructorNode::AddInitializer(InitializerNode* initializer)
357 {
358     initializer->SetParent(this);
359     initializers.Add(initializer);
360 }
361 
362 ConstructorNode::ConstructorNode(const Span& span_const boost::uuids::uuid& moduleId_) : FunctionNode(NodeType::constructorNodespan_moduleId_Specifiers::nonenullptrU"@constructor"nullptr)initializers()
363 {
364 }
365 
366 ConstructorNode::ConstructorNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_AttributesNode* attributes_) : FunctionNode(NodeType::constructorNodespan_moduleId_specifiers_nullptrU"@constructor"attributes_)initializers()
367 {
368 }
369 
370 Node* ConstructorNode::Clone(CloneContext& cloneContext) const
371 {
372     ConstructorNode* clone = new ConstructorNode(GetSpan()ModuleId()GetSpecifiers()nullptr);
373     int n = initializers.Count();
374     for (int i = 0; i < n; ++i)
375     {
376         clone->AddInitializer(static_cast<InitializerNode*>(initializers[i]->Clone(cloneContext)));
377     }
378     clone->classId.reset(static_cast<IdentifierNode*>(classId->Clone(cloneContext)));
379     CloneContent(clonecloneContext);
380     return clone;
381 }
382 
383 void ConstructorNode::Accept(Visitor& visitor)
384 {
385     visitor.Visit(*this);
386 }
387 
388 void ConstructorNode::Write(AstWriter& writer)
389 {
390     FunctionNode::Write(writer);
391     initializers.Write(writer);
392     writer.Write(classId.get());
393 }
394 
395 void ConstructorNode::Read(AstReader& reader)
396 {
397     FunctionNode::Read(reader);
398     initializers.Read(reader);
399     initializers.SetParent(this);
400     classId.reset(reader.ReadIdentifierNode());
401 }
402 
403 void ConstructorNode::AddInitializer(InitializerNode* initializer)
404 {
405     initializer->SetParent(this);
406     initializers.Add(initializer);
407 }
408 
409 DestructorNode::DestructorNode(const Span& span_const boost::uuids::uuid& moduleId_) : FunctionNode(NodeType::destructorNodespan_moduleId_)
410 {
411 }
412 
413 DestructorNode::DestructorNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_AttributesNode* attributes_) :
414     FunctionNode(NodeType::destructorNodespan_moduleId_specifiers_nullptrU"@destructor"attributes_)
415 {
416 }
417 
418 Node* DestructorNode::Clone(CloneContext& cloneContext) const
419 {
420     DestructorNode* clone = new DestructorNode(GetSpan()ModuleId()GetSpecifiers()nullptr);
421     clone->classId.reset(static_cast<IdentifierNode*>(classId->Clone(cloneContext)));
422     CloneContent(clonecloneContext);
423     return clone;
424 }
425 
426 void DestructorNode::Accept(Visitor& visitor)
427 {
428     visitor.Visit(*this);
429 }
430 
431 void DestructorNode::Write(AstWriter& writer)
432 {
433     FunctionNode::Write(writer);
434     writer.Write(classId.get());
435 }
436 
437 void DestructorNode::Read(AstReader& reader)
438 {
439     FunctionNode::Read(reader);
440     classId.reset(reader.ReadIdentifierNode());
441 }
442 
443 MemberFunctionNode::MemberFunctionNode(const Span& span_const boost::uuids::uuid& moduleId_) : FunctionNode(NodeType::memberFunctionNodespan_moduleId_)
444 {
445 }
446 
447 MemberFunctionNode::MemberFunctionNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_Node* returnTypeExpr_const std::u32string& groupId_AttributesNode* attributes_) :
448     FunctionNode(NodeType::memberFunctionNodespan_moduleId_specifiers_returnTypeExpr_groupId_attributes_)
449 {
450 }
451 
452 Node* MemberFunctionNode::Clone(CloneContext& cloneContext) const
453 {
454     MemberFunctionNode* clone = new MemberFunctionNode(GetSpan()ModuleId());
455     CloneContent(clonecloneContext);
456     if (IsConst())
457     {
458         clone->SetConst();
459     }
460     return clone;
461 }
462 
463 void MemberFunctionNode::Accept(Visitor& visitor)
464 {
465     visitor.Visit(*this);
466 }
467 
468 ConversionFunctionNode::ConversionFunctionNode(const Span& span_const boost::uuids::uuid& moduleId_) : FunctionNode(NodeType::conversionFunctionNodespan_moduleId_)
469 {
470 }
471 
472 ConversionFunctionNode::ConversionFunctionNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_Node* returnTypeExpr_AttributesNode* attributes_) :
473     FunctionNode(NodeType::conversionFunctionNodespan_moduleId_specifiers_returnTypeExpr_U"@operator_conv"attributes_)
474 {
475 }
476 
477 Node* ConversionFunctionNode::Clone(CloneContext& cloneContext) const
478 {
479     ConversionFunctionNode* clone = new ConversionFunctionNode(GetSpan()ModuleId());
480     CloneContent(clonecloneContext);
481     if (IsConst())
482     {
483         clone->SetConst();
484     }
485     return clone;
486 }
487 
488 void ConversionFunctionNode::Accept(Visitor& visitor)
489 {
490     visitor.Visit(*this);
491 }
492 
493 MemberVariableNode::MemberVariableNode(const Span& span_const boost::uuids::uuid& moduleId_) : Node(NodeType::memberVariableNodespan_moduleId_)specifiers()
494 {
495 }
496 
497 MemberVariableNode::MemberVariableNode(const Span& span_const boost::uuids::uuid& moduleId_Specifiers specifiers_Node* typeExpr_IdentifierNode* id_AttributesNode* attributes_) :
498     Node(NodeType::memberVariableNodespan_moduleId_)specifiers(specifiers_)typeExpr(typeExpr_)id(id_)attributes(attributes_)
499 {
500     typeExpr->SetParent(this);
501     id->SetParent(this);
502 }
503 
504 Node* MemberVariableNode::Clone(CloneContext& cloneContext) const
505 {
506     AttributesNode* clonedAttributes = nullptr;
507     if (attributes)
508     {
509         clonedAttributes = static_cast<AttributesNode*>(attributes->Clone(cloneContext));
510     }
511     MemberVariableNode* clone =  new MemberVariableNode(GetSpan()ModuleId()specifierstypeExpr->Clone(cloneContext)static_cast<IdentifierNode*>(id->Clone(cloneContext))clonedAttributes);
512     clone->SetSpecifierSpan(specifierSpan);
513     return clone;
514 }
515 
516 void MemberVariableNode::Accept(Visitor& visitor)
517 {
518     visitor.Visit(*this);
519 }
520 
521 void MemberVariableNode::Write(AstWriter& writer)
522 {
523     Node::Write(writer);
524     bool hasAttributes = attributes != nullptr;
525     writer.GetBinaryWriter().Write(hasAttributes);
526     if (hasAttributes)
527     {
528         writer.Write(attributes.get());
529     }
530     writer.Write(specifiers);
531     writer.Write(typeExpr.get());
532     writer.Write(id.get());
533     bool convertExternal = ModuleId() == writer.SpanConversionModuleId();
534     writer.Write(specifierSpanconvertExternal);
535 }
536 
537 void MemberVariableNode::Read(AstReader& reader)
538 {
539     Node::Read(reader);
540     bool hasAttributes = reader.GetBinaryReader().ReadBool();
541     if (hasAttributes)
542     {
543         attributes.reset(reader.ReadAttributesNode());
544     }
545     specifiers = reader.ReadSpecifiers();
546     typeExpr.reset(reader.ReadNode());
547     typeExpr->SetParent(this);
548     id.reset(reader.ReadIdentifierNode());
549     id->SetParent(this);
550     specifierSpan = reader.ReadSpan();
551 }
552 
553 } } // namespace sngcm::ast