1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcm/ast/Function.hpp>
  7 #include <sngcm/ast/Visitor.hpp>
  8 
  9 namespace sngcm { namespace ast {
 10 
 11 FunctionNode::FunctionNode(const Span& span_) : Node(NodeType::functionNodespan_)specifiers(Specifiers::none)returnTypeExpr()groupId()parameters()body()bodySource()programMain(false)
 12 {
 13 }
 14 
 15 FunctionNode::FunctionNode(NodeType nodeType_const Span& span_) : Node(nodeType_span_)specifiers(Specifiers::none)returnTypeExpr()groupId()parameters()body()bodySource()programMain(false)
 16 {
 17 }
 18 
 19 FunctionNode::FunctionNode(const Span& span_Specifiers specifiers_Node* returnTypeExpr_const std::u32string& groupId_Attributes* attributes_) :
 20     Node(NodeType::functionNodespan_)specifiers(specifiers_)returnTypeExpr(returnTypeExpr_)groupId(groupId_)templateParameters()parameters()body()bodySource()attributes(attributes_)programMain(false)
 21 {
 22     if (returnTypeExpr)
 23     {
 24         returnTypeExpr->SetParent(this);
 25     }
 26 }
 27 
 28 FunctionNode::FunctionNode(NodeType nodeType_const Span& span_Specifiers specifiers_Node* returnTypeExpr_const std::u32string& groupId_Attributes* attributes_) :
 29     Node(nodeType_span_)specifiers(specifiers_)returnTypeExpr(returnTypeExpr_)groupId(groupId_)templateParameters()parameters()body()bodySource()attributes(attributes_)programMain(false)
 30 {
 31     if (returnTypeExpr)
 32     {
 33         returnTypeExpr->SetParent(this);
 34     }
 35 }
 36 
 37 Node* FunctionNode::Clone(CloneContext& cloneContext) const
 38 {
 39     Attributes* clonedAttributes = nullptr;
 40     if (attributes)
 41     {
 42         clonedAttributes = attributes->Clone();
 43     }
 44     Node* clonedReturnTypeExpr = nullptr;
 45     if (returnTypeExpr)
 46     {
 47         clonedReturnTypeExpr = returnTypeExpr->Clone(cloneContext);
 48     }
 49     FunctionNode* clone = new FunctionNode(GetSpan()specifiersclonedReturnTypeExprgroupIdclonedAttributes);
 50     if (!cloneContext.InstantiateFunctionNode())
 51     {
 52         int nt = templateParameters.Count();
 53         for (int i = 0; i < nt; ++i)
 54         {
 55             clone->AddTemplateParameter(static_cast<TemplateParameterNode*>(templateParameters[i]->Clone(cloneContext)));
 56         }
 57     }
 58     int np = parameters.Count();
 59     for (int i = 0; i < np; ++i)
 60     {
 61         clone->AddParameter(static_cast<ParameterNode*>(parameters[i]->Clone(cloneContext)));
 62     }
 63     if (body)
 64     {
 65         if (cloneContext.InstantiateClassNode())
 66         {
 67             CloneContext bodyCloneContext;
 68             clone->SetBodySource(static_cast<CompoundStatementNode*>(body->Clone(bodyCloneContext)));
 69         }
 70         else
 71         {
 72             clone->SetBody(static_cast<CompoundStatementNode*>(body->Clone(cloneContext)));
 73         }
 74     }
 75     if (whereConstraint)
 76     {
 77         clone->SetConstraint(static_cast<WhereConstraintNode*>(whereConstraint->Clone(cloneContext)));
 78     }
 79     clone->SetGroupIdSpan(groupIdSpan);
 80     clone->SetSpecifierSpan(specifierSpan);
 81     return clone;
 82 }
 83 
 84 void FunctionNode::CloneContent(FunctionNode* cloneCloneContext& cloneContext) const
 85 {
 86     if (attributes)
 87     {
 88         clone->attributes.reset(attributes->Clone());
 89     }
 90     clone->specifiers = specifiers;
 91     Node* clonedReturnTypeExpr = nullptr;
 92     if (returnTypeExpr)
 93     {
 94         clone->SetReturnTypeExpr(returnTypeExpr->Clone(cloneContext));
 95     }
 96     clone->groupId = groupId;
 97     int nt = templateParameters.Count();
 98     for (int i = 0; i < nt; ++i)
 99     {
100         clone->AddTemplateParameter(static_cast<TemplateParameterNode*>(templateParameters[i]->Clone(cloneContext)));
101     }
102     int np = parameters.Count();
103     for (int i = 0; i < np; ++i)
104     {
105         clone->AddParameter(static_cast<ParameterNode*>(parameters[i]->Clone(cloneContext)));
106     }
107     if (body)
108     {
109         if (cloneContext.InstantiateClassNode())
110         {
111             CloneContext bodyCloneContext;
112             clone->SetBodySource(static_cast<CompoundStatementNode*>(body->Clone(bodyCloneContext)));
113         }
114         else
115         {
116             clone->SetBody(static_cast<CompoundStatementNode*>(body->Clone(cloneContext)));
117         }
118     }
119     if (whereConstraint)
120     {
121         clone->SetConstraint(static_cast<WhereConstraintNode*>(whereConstraint->Clone(cloneContext)));
122     }
123     clone->SetGroupIdSpan(groupIdSpan);
124     clone->SetSpecifierSpan(specifierSpan);
125 }
126 
127 void FunctionNode::Accept(Visitor& visitor)
128 {
129     visitor.Visit(*this);
130 }
131 
132 void FunctionNode::Write(AstWriter& writer)
133 {
134     Node::Write(writer);
135     bool hasAttributes = attributes != nullptr;
136     writer.GetBinaryWriter().Write(hasAttributes);
137     if (hasAttributes)
138     {
139         attributes->Write(writer);
140     }
141     writer.Write(specifiers);
142     bool hasReturnTypeExpr = returnTypeExpr != nullptr;
143     writer.GetBinaryWriter().Write(hasReturnTypeExpr);
144     if (hasReturnTypeExpr)
145     {
146         writer.Write(returnTypeExpr.get());
147     }
148     writer.GetBinaryWriter().Write(groupId);
149     templateParameters.Write(writer);
150     parameters.Write(writer);
151     bool hasConstraint = whereConstraint != nullptr;
152     writer.GetBinaryWriter().Write(hasConstraint);
153     if (hasConstraint)
154     {
155         writer.Write(whereConstraint.get());
156     }
157     bool hasBody = body != nullptr;
158     writer.GetBinaryWriter().Write(hasBody);
159     if (hasBody)
160     {
161         writer.Write(body.get());
162     }
163     bool hasBodySource = bodySource != nullptr;
164     writer.GetBinaryWriter().Write(hasBodySource);
165     if (hasBodySource)
166     {
167         writer.Write(bodySource.get());
168     }
169     writer.Write(groupIdSpan);
170     writer.Write(specifierSpan);
171 }
172 
173 void FunctionNode::Read(AstReader& reader)
174 {
175     Node::Read(reader);
176     bool hasAttributes = reader.GetBinaryReader().ReadBool();
177     if (hasAttributes)
178     {
179         attributes.reset(new Attributes());
180         attributes->Read(reader);
181     }
182     specifiers = reader.ReadSpecifiers();
183     bool hasReturnTypeExpr = reader.GetBinaryReader().ReadBool();
184     if (hasReturnTypeExpr)
185     {
186         returnTypeExpr.reset(reader.ReadNode());
187         returnTypeExpr->SetParent(this);
188     }
189     groupId = reader.GetBinaryReader().ReadUtf32String();
190     templateParameters.Read(reader);
191     templateParameters.SetParent(this);
192     parameters.Read(reader);
193     parameters.SetParent(this);
194     bool hasConstraint = reader.GetBinaryReader().ReadBool();
195     if (hasConstraint)
196     {
197         whereConstraint.reset(reader.ReadWhereConstraintNode());
198     }
199     bool hasBody = reader.GetBinaryReader().ReadBool();
200     if (hasBody)
201     {
202         body.reset(reader.ReadCompoundStatementNode());
203         body->SetParent(this);
204     }
205     bool hasBodySource = reader.GetBinaryReader().ReadBool();
206     if (hasBodySource)
207     {
208         bodySource.reset(reader.ReadCompoundStatementNode());
209         bodySource->SetParent(this);
210     }
211     groupIdSpan = reader.ReadSpan();
212     specifierSpan = reader.ReadSpan();
213 }
214 
215 void FunctionNode::AddTemplateParameter(TemplateParameterNode* templateParameter)
216 {
217     templateParameter->SetParent(this);
218     templateParameters.Add(templateParameter);
219 }
220 
221 void FunctionNode::AddParameter(ParameterNode* parameter)
222 {
223     parameter->SetParent(this);
224     parameters.Add(parameter);
225 }
226 
227 void FunctionNode::SwitchToBody()
228 {
229     if (bodySource && !body)
230     {
231         SetBody(bodySource.release());
232     }
233 }
234 
235 void FunctionNode::SetReturnTypeExpr(Node* returnTypeExpr_)
236 {
237     returnTypeExpr.reset(returnTypeExpr_);
238     returnTypeExpr->SetParent(returnTypeExpr_);
239 }
240 
241 void FunctionNode::SetSpecifiers(Specifiers specifiers_)
242 {
243     specifiers = specifiers_;
244 }
245 
246 void FunctionNode::SetConstraint(WhereConstraintNode* whereConstraint_)
247 {
248     whereConstraint.reset(whereConstraint_);
249     whereConstraint->SetParent(this);
250 }
251 
252 void FunctionNode::SetBody(CompoundStatementNode* body_)
253 {
254     body.reset(body_);
255     body->SetParent(this);
256 }
257 
258 void FunctionNode::SetBodySource(CompoundStatementNode* bodySource_)
259 {
260     bodySource.reset(bodySource_);
261     bodySource->SetParent(this);
262 }
263 
264 } } // namespace sngcm::ast