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