1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/binder/XmlAttributeProcessor.hpp>
  7 #include <cmajor/binder/BoundCompileUnit.hpp>
  8 #include <cmajor/binder/TypeResolver.hpp>
  9 #include <cmajor/binder/StatementBinder.hpp>
 10 #include <cmajor/binder/TypeBinder.hpp>
 11 #include <cmajor/binder/BoundClass.hpp>
 12 #include <cmajor/binder/BoundFunction.hpp>
 13 #include <cmajor/symbols/Exception.hpp>
 14 #include <cmajor/symbols/SymbolCreatorVisitor.hpp>
 15 #include <sngcm/ast/TypeExpr.hpp>
 16 #include <sngcm/ast/Expression.hpp>
 17 #include <sngcm/ast/Literal.hpp>
 18 #include <soulng/util/Unicode.hpp>
 19 
 20 namespace cmajor { namespace binder {
 21 
 22 using namespace soulng::unicode;
 23 using namespace cmajor::symbols;
 24 
 25 XmlAttributeProcessor::XmlAttributeProcessor() : AttributeProcessor(U"xml")
 26 {
 27 }
 28 
 29 void XmlAttributeProcessor::TypeCheck(AttributeNode* attributeSymbol* symbol)
 30 {
 31     switch (symbol->GetSymbolType())
 32     {
 33         case SymbolType::classTypeSymbol: case SymbolType::classTemplateSpecializationSymbol: case SymbolType::memberVariableSymbol:
 34         {
 35             if (attribute->Value() == U"true" || attribute->Value() == U"false")
 36             {
 37                 return;
 38             }
 39             else
 40             {
 41                 throw Exception("unknown attribute value '" + ToUtf8(attribute->Value()) + "' for attribute '" + ToUtf8(attribute->Name()) + "'"attribute->GetSpan()attribute->ModuleId());
 42             }
 43             break;
 44         }
 45     }
 46     AttributeProcessor::TypeCheck(attributesymbol);
 47 }
 48 
 49 void XmlAttributeProcessor::GenerateSymbols(AttributeNode* attributeSymbol* symbolBoundCompileUnit& boundCompileUnitContainerScope* containerScope)
 50 {
 51     if (symbol->IsClassTypeSymbol())
 52     {
 53         ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
 54         if (attribute->Value() == U"true")
 55         {
 56             GenerateToXmlSymbol(attributeclassTypeSymbolboundCompileUnitcontainerScope);
 57             GenerateSystemDomElementConstructorSymbol(attributeclassTypeSymbolboundCompileUnitcontainerScope);
 58         }
 59     }
 60 }
 61 
 62 void XmlAttributeProcessor::GenerateImplementation(AttributeNode* attributeSymbol* symbolStatementBinder* statementBinder)
 63 {
 64     if (symbol->IsClassTypeSymbol())
 65     {
 66         ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
 67         auto toXmlIt = toXmlMemberFunctionSymbolMap.find(symbol);
 68         if (toXmlIt != toXmlMemberFunctionSymbolMap.cend())
 69         {
 70             MemberFunctionSymbol* toXmlMemberFunctionSymbol = toXmlIt->second;
 71             GenerateToXmlMemberFunctionImplementation(attributeclassTypeSymboltoXmlMemberFunctionSymbolstatementBinder);
 72         }
 73         else
 74         {
 75             throw Exception("internal error in XML attribute implementation: member function 'ToXml' symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found"attribute->GetSpan()attribute->ModuleId());
 76         }
 77         auto contructorIt = constructorSymbolMap.find(symbol);
 78         if (contructorIt != constructorSymbolMap.cend())
 79         {
 80             ConstructorSymbol* constructorSymbol = contructorIt->second;
 81             GenerateSystemDomElementConstructorImplementation(attributeclassTypeSymbolconstructorSymbolstatementBinder);
 82         }
 83         else
 84         {
 85             throw Exception("internal error in XML attribute implementation: constructor symbol for symbol '" + ToUtf8(symbol->FullName()) + "' not found"attribute->GetSpan()attribute->ModuleId());
 86         }
 87     }
 88 }
 89 
 90 void XmlAttributeProcessor::GenerateToXmlSymbol(AttributeNode* attributeClassTypeSymbol* classTypeSymbolBoundCompileUnit& boundCompileUnitContainerScope* containerScope)
 91 {
 92     MemberFunctionSymbol* toXmlMemberFunctionSymbol = new MemberFunctionSymbol(attribute->GetSpan()attribute->ModuleId()U"ToXml");
 93     toXmlMemberFunctionSymbol->SetModule(&boundCompileUnit.GetModule());
 94     toXmlMemberFunctionSymbol->SetGroupName(U"ToXml");
 95     if (classTypeSymbol->BaseClass())
 96     {
 97         toXmlMemberFunctionSymbol->SetOverride();
 98     }
 99     else if (classTypeSymbol->Destructor() && classTypeSymbol->Destructor()->IsVirtual())
100     {
101         toXmlMemberFunctionSymbol->SetVirtual();
102     }
103     GetRootModuleForCurrentThread()->GetSymbolTable().SetFunctionIdFor(toXmlMemberFunctionSymbol);
104     ParameterSymbol* thisParam = new ParameterSymbol(attribute->GetSpan()attribute->ModuleId()U"this");
105     thisParam->SetType(classTypeSymbol->AddPointer(attribute->GetSpan()attribute->ModuleId()));
106     ParameterSymbol* fieldNameParam = new ParameterSymbol(attribute->GetSpan()attribute->ModuleId()U"fieldName");
107     IdentifierNode * stringIdNode(new IdentifierNode(attribute->GetSpan()attribute->ModuleId()U"System.string"));
108     Node * refNode(new LValueRefNode(attribute->GetSpan()attribute->ModuleId()stringIdNode));
109     std::unique_ptr<Node> constNode(new ConstNode(attribute->GetSpan()attribute->ModuleId()refNode));
110     TypeSymbol* stringType = ResolveType(constNode.get()boundCompileUnitcontainerScope);
111     fieldNameParam->SetType(stringType);
112     TemplateIdNode templateId(attribute->GetSpan()attribute->ModuleId()new IdentifierNode(attribute->GetSpan()attribute->ModuleId()U"System.UniquePtr"));
113     templateId.AddTemplateArgument(new IdentifierNode(attribute->GetSpan()attribute->ModuleId()U"System.Dom.Element"));
114     TypeSymbol* uniquePtrElementType = ResolveType(&templateIdboundCompileUnitcontainerScope);
115     toXmlMemberFunctionSymbol->SetReturnType(uniquePtrElementType);
116     ParameterSymbol* returnParam = new ParameterSymbol(attribute->GetSpan()attribute->ModuleId()U"@return");
117     returnParam->SetParent(toXmlMemberFunctionSymbol);
118     returnParam->SetType(uniquePtrElementType->AddPointer(attribute->GetSpan()attribute->ModuleId()));
119     toXmlMemberFunctionSymbol->SetReturnParam(returnParam);
120     toXmlMemberFunctionSymbol->SetAccess(SymbolAccess::public_);
121     toXmlMemberFunctionSymbol->AddMember(thisParam);
122     toXmlMemberFunctionSymbol->AddMember(fieldNameParam);
123     classTypeSymbol->AddMember(toXmlMemberFunctionSymbol);
124     toXmlMemberFunctionSymbol->ComputeName();
125     toXmlMemberFunctionSymbolMap[classTypeSymbol] = toXmlMemberFunctionSymbol;
126 }
127 
128 void XmlAttributeProcessor::GenerateSystemDomElementConstructorSymbol(AttributeNode* attributeClassTypeSymbol* classTypeSymbolBoundCompileUnit& boundCompileUnitContainerScope* containerScope)
129 {
130     ConstructorSymbol* constructorSymbol = new ConstructorSymbol(attribute->GetSpan()attribute->ModuleId()U"@constructor");
131     constructorSymbol->SetModule(&boundCompileUnit.GetModule());
132     constructorSymbol->SetGroupName(U"@constructor");
133     GetRootModuleForCurrentThread()->GetSymbolTable().SetFunctionIdFor(constructorSymbol);
134     ParameterSymbol* thisParam = new ParameterSymbol(attribute->GetSpan()attribute->ModuleId()U"this");
135     thisParam->SetType(classTypeSymbol->AddPointer(attribute->GetSpan()attribute->ModuleId()));
136     ParameterSymbol* elementParam = new ParameterSymbol(attribute->GetSpan()attribute->ModuleId()U"@element");
137     std::unique_ptr<PointerNode> pointertNode(new PointerNode(attribute->GetSpan()attribute->ModuleId()new IdentifierNode(attribute->GetSpan()attribute->ModuleId()U"System.Dom.Element")));
138     TypeSymbol* elementType = ResolveType(pointertNode.get()boundCompileUnitcontainerScope);
139     elementParam->SetType(elementType);
140     constructorSymbol->SetAccess(SymbolAccess::public_);
141     constructorSymbol->AddMember(thisParam);
142     constructorSymbol->AddMember(elementParam);
143     classTypeSymbol->AddMember(constructorSymbol);
144     constructorSymbol->ComputeName();
145     constructorSymbolMap[classTypeSymbol] = constructorSymbol;
146 }
147 
148 void XmlAttributeProcessor::GenerateToXmlMemberFunctionImplementation(AttributeNode* attributeClassTypeSymbol* classTypeSymbolMemberFunctionSymbol* toXmlMemberFunctionSymbol
149     StatementBinder* statementBinder)
150 {
151     try
152     {
153         FileScope* fileScope = new FileScope();
154         Symbol* systemDomElement = GetRootModuleForCurrentThread()->GetSymbolTable().GlobalNs().GetContainerScope()->Lookup(U"System.Dom.Element");
155         if (systemDomElement)
156         {
157             fileScope->AddContainerScope(systemDomElement->Ns()->GetContainerScope());
158         }
159         statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
160         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit()toXmlMemberFunctionSymbol));
161         Span span = attribute->GetSpan();
162         boost::uuids::uuid moduleId = attribute->ModuleId();
163         CompoundStatementNode compoundStatementNode(spanmoduleId);
164         compoundStatementNode.SetEndBraceSpan(span);
165 
166         TemplateIdNode* uniquePtrSystemDomElement = new TemplateIdNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.UniquePtr"));
167         uniquePtrSystemDomElement->AddTemplateArgument(new IdentifierNode(spanmoduleIdU"System.Dom.Element"));
168         ConstructionStatementNode* constructSystemDomElementStatement = new ConstructionStatementNode(spanmoduleIduniquePtrSystemDomElementnew IdentifierNode(spanmoduleIdU"@element"));
169         NewNode* newNode = new NewNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.Dom.Element"));
170         InvokeNode* toUtf32Node = new InvokeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.ToUtf32"));
171         toUtf32Node->AddArgument(new IdentifierNode(spanmoduleIdU"fieldName"));
172         newNode->AddArgument(toUtf32Node);
173         constructSystemDomElementStatement->AddArgument(newNode);
174         compoundStatementNode.AddStatement(constructSystemDomElementStatement);
175 
176         if (classTypeSymbol->BaseClass())
177         {
178             ClassTypeSymbol* baseClassSymbol = classTypeSymbol->BaseClass();
179             AttributesNode* attributes = baseClassSymbol->GetAttributes();
180             if (attributes)
181             {
182                 AttributeNode* xmlAttribute = attributes->GetAttribute(U"xml");
183                 if (xmlAttribute)
184                 {
185                     if (xmlAttribute->Value() == U"true")
186                     {
187                         Span span = classTypeSymbol->BaseClass()->GetSpan();
188                         boost::uuids::uuid moduleId = classTypeSymbol->SourceModuleId();
189                         BaseNode* baseNode = new BaseNode(spanmoduleId);
190                         ArrowNode* arrowNode = new ArrowNode(spanmoduleIdbaseNodenew IdentifierNode(spanmoduleIdU"ToXml"));
191                         InvokeNode* toXmlInvokeNode = new InvokeNode(spanmoduleIdarrowNode);
192                         toXmlInvokeNode->AddArgument(new StringLiteralNode(spanmoduleId"base"));
193                         DotNode* dotNode = new DotNode(spanmoduleIdtoXmlInvokeNodenew IdentifierNode(spanmoduleIdU"Release"));
194                         InvokeNode* dotInvokeNode = new InvokeNode(spanmoduleIddotNode);
195                         TemplateIdNode* uniquePtrNode = new TemplateIdNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.UniquePtr"));
196                         uniquePtrNode->AddTemplateArgument(new IdentifierNode(spanmoduleIdU"System.Dom.Node"));
197                         InvokeNode* uniquePtrNodeInvokeNode = new InvokeNode(spanmoduleIduniquePtrNode);
198                         uniquePtrNodeInvokeNode->AddArgument(dotInvokeNode);
199                         ArrowNode* appendChildArrowNode = new ArrowNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@element")new IdentifierNode(spanmoduleIdU"AppendChild"));
200                         InvokeNode* appendChildInvokeNode = new InvokeNode(spanmoduleIdappendChildArrowNode);
201                         appendChildInvokeNode->AddArgument(uniquePtrNodeInvokeNode);
202                         ExpressionStatementNode* appendChildStatement = new ExpressionStatementNode(spanmoduleIdappendChildInvokeNode);
203                         compoundStatementNode.AddStatement(appendChildStatement);
204                     }
205                 }
206             }
207         }
208 
209         for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
210         {
211             AttributesNode* attributes = memberVariableSymbol->GetAttributes();
212             if (attributes)
213             {
214                 AttributeNode* xmlAttribute = attributes->GetAttribute(U"xml");
215                 if (xmlAttribute)
216                 {
217                     if (xmlAttribute->Value() == U"false")
218                     {
219                         continue;
220                     }
221                 }
222             }
223             InvokeNode* toXmlInvokeNode = new InvokeNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()new IdentifierNode(spanmoduleIdU"ToXml"));
224             toXmlInvokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()memberVariableSymbol->Name()));
225             toXmlInvokeNode->AddArgument(new StringLiteralNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()ToUtf8(memberVariableSymbol->Name())));
226             DotNode* dotNode = new DotNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()toXmlInvokeNodenew IdentifierNode(
227                 memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()U"Release"));
228             InvokeNode* dotInvokeNode = new InvokeNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()dotNode);
229             TemplateIdNode* uniquePtrNode = new TemplateIdNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()
230                 new IdentifierNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()U"System.UniquePtr"));
231             uniquePtrNode->AddTemplateArgument(new IdentifierNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()
232                 U"System.Dom.Node"));
233             InvokeNode* uniquePtrNodeInvokeNode = new InvokeNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()uniquePtrNode);
234             uniquePtrNodeInvokeNode->AddArgument(dotInvokeNode);
235             ArrowNode* appendChildArrowNode = new ArrowNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@element")new IdentifierNode(spanmoduleIdU"AppendChild"));
236             InvokeNode* appendChildInvokeNode = new InvokeNode(spanmoduleIdappendChildArrowNode);
237             appendChildInvokeNode->AddArgument(uniquePtrNodeInvokeNode);
238             ExpressionStatementNode* appendChildStatement = new ExpressionStatementNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()appendChildInvokeNode);
239             compoundStatementNode.AddStatement(appendChildStatement);
240         }
241 
242         TemplateIdNode* uniquePtrNode = new TemplateIdNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.UniquePtr"));
243         uniquePtrNode->AddTemplateArgument(new IdentifierNode(spanmoduleIdU"System.Dom.Element"));
244         InvokeNode* invokeReleaseUniquePtrNode = new InvokeNode(spanmoduleIduniquePtrNode);
245         invokeReleaseUniquePtrNode->AddArgument(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@element")
246             new IdentifierNode(spanmoduleIdU"Release"))));
247         ReturnStatementNode* returnStatementNode = new ReturnStatementNode(spanmoduleIdinvokeReleaseUniquePtrNode);
248         compoundStatementNode.AddStatement(returnStatementNode);
249 
250         SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
251         symbolTable.BeginContainer(toXmlMemberFunctionSymbol);
252         SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
253         compoundStatementNode.Accept(symbolCreatorVisitor);
254         symbolTable.EndContainer();
255         TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
256         ContainerScope* containerScope = statementBinder->GetContainerScope();
257         typeBinder.SetContainerScope(containerScope);
258         statementBinder->SetContainerScope(toXmlMemberFunctionSymbol->GetContainerScope());
259         typeBinder.SetCurrentFunctionSymbol(toXmlMemberFunctionSymbol);
260         compoundStatementNode.Accept(typeBinder);
261         BoundFunction* prevFunction = statementBinder->CurrentFunction();
262         statementBinder->SetCurrentFunction(boundFunction.get());
263         compoundStatementNode.Accept(*statementBinder);
264         statementBinder->SetContainerScope(containerScope);
265         BoundStatement* boundStatement = statementBinder->ReleaseStatement();
266         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
267         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
268         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
269         statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
270         statementBinder->SetCurrentFunction(prevFunction);
271         statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
272     }
273     catch (const Exception& ex;)
274     {
275         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
276         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
277         references.insert(references.end()ex.References().begin()ex.References().end());
278         throw Exception("error in XML attribute generation: could not create 'UniquePtr<System.Dom.Element> ToXml(const string& fieldName)' member function for class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message()
279             classTypeSymbol->GetSpan()classTypeSymbol->SourceModuleId()references);
280     }
281 }
282 
283 void XmlAttributeProcessor::GenerateSystemDomElementConstructorImplementation(AttributeNode* attributeClassTypeSymbol* classTypeSymbolConstructorSymbol* constructorSymbolStatementBinder* statementBinder)
284 {
285     try
286     {
287         FileScope* fileScope = new FileScope();
288         statementBinder->GetBoundCompileUnit().AddFileScope(fileScope);
289         std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&statementBinder->GetBoundCompileUnit()constructorSymbol));
290         Span span = attribute->GetSpan();
291         boost::uuids::uuid moduleId = attribute->ModuleId();
292         ConstructorNode constructorNode(spanmoduleId);
293         CompoundStatementNode compoundStatementNode(spanmoduleId);
294         compoundStatementNode.SetEndBraceSpan(span);
295 
296         ClassTypeSymbol* baseClass = classTypeSymbol->BaseClass();
297         if (baseClass)
298         {
299             AttributesNode* attributes = baseClass->GetAttributes();
300             if (attributes)
301             {
302                 AttributeNode* xmlAttribute = attributes->GetAttribute(U"xml");
303                 if (xmlAttribute)
304                 {
305                     if (xmlAttribute->Value() == U"true")
306                     {
307                         Span span = baseClass->GetSpan();
308                         boost::uuids::uuid moduleId = classTypeSymbol->SourceModuleId();
309                         InvokeNode* invokeNode = new InvokeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"GetXmlFieldElement"));
310                         invokeNode->AddArgument(new StringLiteralNode(spanmoduleId"base"));
311                         invokeNode->AddArgument(new IdentifierNode(spanmoduleIdU"@element"));
312                         BaseInitializerNode* baseInitializer = new BaseInitializerNode(spanmoduleId);
313                         baseInitializer->AddArgument(invokeNode);
314                         constructorNode.AddInitializer(baseInitializer);
315                     }
316                 }
317             }
318         }
319 
320         for (MemberVariableSymbol* memberVariableSymbol : classTypeSymbol->MemberVariables())
321         {
322             AttributesNode* attributes = memberVariableSymbol->GetAttributes();
323             if (attributes)
324             {
325                 AttributeNode* xmlAttribute = attributes->GetAttribute(U"xml");
326                 if (xmlAttribute)
327                 {
328                     if (xmlAttribute->Value() == U"false")
329                     {
330                         continue;
331                     }
332                 }
333             }
334             InvokeNode* invokeNode = new InvokeNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()new IdentifierNode(spanmoduleIdU"FromXml"));
335             invokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()U"@element"));
336             invokeNode->AddArgument(new StringLiteralNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()ToUtf8(memberVariableSymbol->Name())));
337             invokeNode->AddArgument(new IdentifierNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()memberVariableSymbol->Name()));
338             ExpressionStatementNode* fromXmlStatement = new ExpressionStatementNode(memberVariableSymbol->GetSpan()memberVariableSymbol->SourceModuleId()invokeNode);
339             compoundStatementNode.AddStatement(fromXmlStatement);
340         }
341 
342         SymbolTable& symbolTable = statementBinder->GetBoundCompileUnit().GetSymbolTable();
343         symbolTable.BeginContainer(constructorSymbol);
344         SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
345         compoundStatementNode.Accept(symbolCreatorVisitor);
346         symbolTable.EndContainer();
347         TypeBinder typeBinder(statementBinder->GetBoundCompileUnit());
348         ContainerScope* containerScope = statementBinder->GetContainerScope();
349         typeBinder.SetContainerScope(containerScope);
350         statementBinder->SetContainerScope(constructorSymbol->GetContainerScope());
351         typeBinder.SetCurrentFunctionSymbol(constructorSymbol);
352         compoundStatementNode.Accept(typeBinder);
353         BoundFunction* prevFunction = statementBinder->CurrentFunction();
354         statementBinder->SetCurrentFunction(boundFunction.get());
355         ConstructorSymbol* prevConstructorSymbol = statementBinder->CurrentConstructorSymbol();
356         ConstructorNode* prevConstructorNode = statementBinder->CurrentConstructorNode();
357         statementBinder->SetCurrentConstructor(constructorSymbol&constructorNode);
358         compoundStatementNode.Accept(*statementBinder);
359         statementBinder->SetContainerScope(containerScope);
360         BoundStatement* boundStatement = statementBinder->ReleaseStatement();
361         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
362         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
363         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
364         statementBinder->CurrentClass()->AddMember(std::move(boundFunction));
365         statementBinder->SetCurrentConstructor(prevConstructorSymbolprevConstructorNode);
366         statementBinder->SetCurrentFunction(prevFunction);
367         statementBinder->GetBoundCompileUnit().RemoveLastFileScope();
368     }
369     catch (const Exception& ex;)
370     {
371         std::vector<std::std::pair<Spanboost::uuids::uuid>>references;
372         references.push_back(std::make_pair(ex.Defined()ex.DefinedModuleId()));
373         references.insert(references.end()ex.References().begin()ex.References().end());
374         throw Exception("error in XML attribute generation: could not create constructor taking System.Dom.Element* for the class '" + ToUtf8(classTypeSymbol->FullName()) + "': " + ex.Message()
375             classTypeSymbol->GetSpan()classTypeSymbol->SourceModuleId()references);
376     }
377 }
378 } } // namespace cmajor::binder