1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 #include <cmajor/binder/StatementBinder.hpp>
   7 #include <cmajor/binder/BoundNamespace.hpp>
   8 #include <cmajor/binder/BoundClass.hpp>
   9 #include <cmajor/binder/BoundFunction.hpp>
  10 #include <cmajor/binder/BoundStatement.hpp>
  11 #include <cmajor/binder/BoundExpression.hpp>
  12 #include <cmajor/binder/OverloadResolution.hpp>
  13 #include <cmajor/binder/ExpressionBinder.hpp>
  14 #include <cmajor/binder/Access.hpp>
  15 #include <cmajor/binder/OperationRepository.hpp>
  16 #include <cmajor/binder/Evaluator.hpp>
  17 #include <cmajor/binder/TypeBinder.hpp>
  18 #include <cmajor/binder/TypeResolver.hpp>
  19 #include <cmajor/binder/AttributeBinder.hpp>
  20 #include <cmajor/binder/BoundEnum.hpp>
  21 #include <cmajor/symbols/FunctionSymbol.hpp>
  22 #include <cmajor/symbols/Exception.hpp>
  23 #include <cmajor/symbols/GlobalFlags.hpp>
  24 #include <cmajor/symbols/SymbolCreatorVisitor.hpp>
  25 #include <sngcm/cmparser/TypeExpr.hpp>
  26 #include <sngcm/cmlexer/CmajorLexer.hpp>
  27 #include <sngcm/ast/Literal.hpp>
  28 #include <sngcm/ast/Identifier.hpp>
  29 #include <sngcm/ast/Expression.hpp>
  30 #include <sngcm/ast/BasicType.hpp>
  31 #include <sngcm/ast/Statement.hpp>
  32 #include <soulng/util/Unicode.hpp>
  33 
  34 namespace cmajor { namespace binder {
  35 
  36 using namespace soulng::unicode;
  37 
  38 bool IsAlwaysTrue(Node* nodeBoundCompileUnit& boundCompileUnitContainerScope* containerScope)
  39 {
  40     std::unique_ptr<Value> value = Evaluate(nodeboundCompileUnit.GetSymbolTable().GetTypeByName(U"bool")containerScopeboundCompileUnittruenullptrnode->GetSpan()node->ModuleId());
  41     if (value)
  42     {
  43         if (value->GetValueType() == ValueType::boolValue)
  44         {
  45             BoolValue* boolValue = static_cast<BoolValue*>(value.get());
  46             return boolValue->GetValue() == true;
  47         }
  48     }
  49     return false;
  50 }
  51 
  52 bool TerminatesFunction(StatementNode* statementbool inForEverLoopContainerScope* containerScopeBoundCompileUnit& boundCompileUnit)
  53 {
  54     switch (statement->GetNodeType())
  55     {
  56         case NodeType::compoundStatementNode:
  57         {
  58             CompoundStatementNode* compoundStatement = static_cast<CompoundStatementNode*>(statement);
  59             int n = compoundStatement->Statements().Count();
  60             for (int i = 0; i < n; ++i)
  61             {
  62                 StatementNode* statement = compoundStatement->Statements()[i];
  63                 if (TerminatesFunction(statementinForEverLoopcontainerScopeboundCompileUnit)) return true;
  64             }
  65             break;
  66         }
  67         case NodeType::ifStatementNode:
  68         {
  69             IfStatementNode* ifStatement = static_cast<IfStatementNode*>(statement);
  70             if (inForEverLoop || ifStatement->ElseS())
  71             {
  72                 if (TerminatesFunction(ifStatement->ThenS()inForEverLoopcontainerScopeboundCompileUnit) && 
  73                     inForEverLoop || (ifStatement->ElseS() && TerminatesFunction(ifStatement->ElseS()inForEverLoopcontainerScopeboundCompileUnit)))
  74                 {
  75                     return true;
  76                 }
  77             }
  78             break;
  79         }
  80         case NodeType::whileStatementNode:
  81         {
  82             WhileStatementNode* whileStatement = static_cast<WhileStatementNode*>(statement);
  83             if (IsAlwaysTrue(whileStatement->Condition()boundCompileUnitcontainerScope))
  84             {
  85                 if (TerminatesFunction(whileStatement->Statement()truecontainerScopeboundCompileUnit)) return true;
  86             }
  87             break;
  88         }
  89         case NodeType::doStatementNode:
  90         {
  91             DoStatementNode* doStatement = static_cast<DoStatementNode*>(statement);
  92             if (IsAlwaysTrue(doStatement->Condition()boundCompileUnitcontainerScope))
  93             {
  94                 if (TerminatesFunction(doStatement->Statement()truecontainerScopeboundCompileUnit)) return true;
  95             }
  96             break;
  97         }
  98         case NodeType::forStatementNode:
  99         {
 100             ForStatementNode* forStatement = static_cast<ForStatementNode*>(statement);
 101             if (!forStatement->Condition() || IsAlwaysTrue(forStatement->Condition()boundCompileUnitcontainerScope))
 102             {
 103                 if (TerminatesFunction(forStatement->ActionS()truecontainerScopeboundCompileUnit)) return true;
 104             }
 105             break;
 106         }
 107         default:
 108         {
 109             if (statement->IsFunctionTerminatingNode())
 110             {
 111                 return true;
 112             }
 113             break;
 114         }
 115     }
 116     return false;
 117 }
 118 
 119 bool TerminatesCase(StatementNode* statementNode)
 120 {
 121     if (statementNode->GetNodeType() == NodeType::ifStatementNode)
 122     {
 123         IfStatementNode* ifStatementNode = static_cast<IfStatementNode*>(statementNode);
 124         if (ifStatementNode->ElseS())
 125         {
 126             if (TerminatesCase(ifStatementNode->ThenS()) && TerminatesCase(ifStatementNode->ElseS()))
 127             {
 128                 return true;
 129             }
 130         }
 131     }
 132     else if (statementNode->GetNodeType() == NodeType::compoundStatementNode)
 133     {
 134         CompoundStatementNode* compoundStatement = static_cast<CompoundStatementNode*>(statementNode);
 135         int n = compoundStatement->Statements().Count();
 136         for (int i = 0; i < n; ++i)
 137         {
 138             StatementNode* statementNode = compoundStatement->Statements()[i];
 139             if (TerminatesCase(statementNode))
 140             {
 141                 return true;
 142             }
 143         }
 144     }
 145     else
 146     {
 147         return statementNode->IsCaseTerminatingNode();
 148     }
 149     return false;
 150 }
 151 
 152 bool TerminatesDefault(StatementNode* statementNode)
 153 {
 154     if (statementNode->GetNodeType() == NodeType::ifStatementNode)
 155     {
 156         IfStatementNode* ifStatementNode = static_cast<IfStatementNode*>(statementNode);
 157         if (ifStatementNode->ElseS())
 158         {
 159             if (TerminatesDefault(ifStatementNode->ThenS()) && TerminatesDefault(ifStatementNode->ElseS()))
 160             {
 161                 return true;
 162             }
 163         }
 164     }
 165     else if (statementNode->GetNodeType() == NodeType::compoundStatementNode)
 166     {
 167         CompoundStatementNode* compoundStatement = static_cast<CompoundStatementNode*>(statementNode);
 168         int n = compoundStatement->Statements().Count();
 169         for (int i = 0; i < n; ++i)
 170         {
 171             StatementNode* statementNode = compoundStatement->Statements()[i];
 172             if (TerminatesDefault(statementNode))
 173             {
 174                 return true;
 175             }
 176         }
 177     }
 178     else
 179     {
 180         return statementNode->IsDefaultTerminatingNode();
 181     }
 182     return false;
 183 }
 184 
 185 void CheckFunctionReturnPaths(FunctionSymbol* functionSymbolCompoundStatementNode* bodyNodeconst Span& spanconst boost::uuids::uuid& moduleId
 186     ContainerScope* containerScopeBoundCompileUnit& boundCompileUnit);
 187 
 188 void CheckFunctionReturnPaths(FunctionSymbol* functionSymbolFunctionNode& functionNodeContainerScope* containerScopeBoundCompileUnit& boundCompileUnit)
 189 {
 190     CheckFunctionReturnPaths(functionSymbolfunctionNode.Body()functionNode.GetSpan()functionNode.ModuleId()containerScopeboundCompileUnit);
 191 }
 192 
 193 void CheckFunctionReturnPaths(FunctionSymbol* functionSymbolCompoundStatementNode* bodyNodeconst Span& spanconst boost::uuids::uuid& moduleId
 194     ContainerScope* containerScopeBoundCompileUnit& boundCompileUnit)
 195 {
 196     TypeSymbol* returnType = functionSymbol->ReturnType();
 197     if (!returnType || returnType->GetSymbolType() == SymbolType::voidTypeSymbol) return;
 198     if (functionSymbol->IsExternal()) return;
 199     if (functionSymbol->IsAbstract()) return;
 200     CompoundStatementNode* body = bodyNode;
 201     if (body)
 202     {
 203         int n = body->Statements().Count();
 204         for (int i = 0; i < n; ++i)
 205         {
 206             StatementNode* statement = body->Statements()[i];
 207             if (TerminatesFunction(statementfalsecontainerScopeboundCompileUnit)) return;
 208         }
 209         throw Exception("not all control paths terminate in return or throw statement"spanmoduleId);
 210     }
 211 }
 212 
 213 StatementBinder::StatementBinder(BoundCompileUnit& boundCompileUnit_) :
 214     boundCompileUnit(boundCompileUnit_)symbolTable(boundCompileUnit.GetSymbolTable())module(&boundCompileUnit.GetModule())containerScope(nullptr)statement()compoundLevel(0)insideCatch(false)
 215     currentClass(nullptr)currentFunction(nullptr)currentStaticConstructorSymbol(nullptr)currentStaticConstructorNode(nullptr)currentConstructorSymbol(nullptr)
 216     currentConstructorNode(nullptr)currentDestructorSymbol(nullptr)currentDestructorNode(nullptr)currentMemberFunctionSymbol(nullptr)currentMemberFunctionNode(nullptr)
 217     switchConditionType(nullptr)currentCaseValueMap(nullptr)currentGotoCaseStatements(nullptr)currentGotoDefaultStatements(nullptr)postfix(false)compilingThrow(false)
 218     compilingReleaseExceptionStatement(false)dontCheckDuplicateFunctionSymbols(false)
 219 {
 220 }
 221 
 222 void StatementBinder::Visit(CompileUnitNode& compileUnitNode)
 223 {
 224     if (compileUnitNode.IsSynthesizedUnit())
 225     {
 226         dontCheckDuplicateFunctionSymbols = true;
 227     }
 228     compileUnitNode.GlobalNs()->Accept(*this);
 229     dontCheckDuplicateFunctionSymbols = false;
 230     Symbol* symbol = symbolTable.GlobalNs().GetContainerScope()->Lookup(U"System.Runtime.AddCompileUnitFunction");
 231     if (symbol)
 232     {
 233         if (symbol->GetSymbolType() == SymbolType::functionGroupSymbol)
 234         {
 235             FunctionGroupSymbol* functionGroup = static_cast<FunctionGroupSymbol*>(symbol);
 236             FunctionSymbol* systemRuntimeAddCompileUnitFunctionSymbol = functionGroup->GetFunction();
 237             boundCompileUnit.SetSystemRuntimeAddCompileUnitFunctionSymbol(systemRuntimeAddCompileUnitFunctionSymbol);
 238         }
 239     }
 240     FunctionSymbol* initCompileUnitSymbol = boundCompileUnit.GetInitCompileUnitFunctionSymbol();
 241     if (initCompileUnitSymbol == nullptr)
 242     {
 243         boundCompileUnit.GenerateCompileUnitInitialization();
 244     }
 245 }
 246 
 247 struct NamespaceVisitor 
 248 {
 249     NamespaceVisitor(BoundCompileUnit* cu_BoundNamespace* ns_) : cu(cu_)ns(ns_)
 250     {
 251         cu->PushNamespace(ns);
 252     }
 253     ~NamespaceVisitor()
 254     {
 255         cu->PopNamespace();
 256     }
 257     BoundCompileUnit* cu;
 258     BoundNamespace* ns;
 259 };
 260 
 261 void StatementBinder::Visit(NamespaceNode& namespaceNode)
 262 {
 263     std::unique_ptr<BoundNamespace> ns(new BoundNamespace(namespaceNode));
 264     boundCompileUnit.PushNamespace(ns.get());
 265     ContainerScope* prevContainerScope = containerScope;
 266     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&namespaceNode);
 267     containerScope = symbol->GetContainerScope();
 268     int n = namespaceNode.Members().Count();
 269     for (int i = 0; i < n; ++i)
 270     {
 271         Node* member = namespaceNode.Members()[i];
 272         member->Accept(*this);
 273     }
 274     containerScope = prevContainerScope;
 275     boundCompileUnit.PopNamespace();
 276     boundCompileUnit.AddBoundNode(std::unique_ptr<BoundNode>(ns.release()));
 277 }
 278 
 279 void StatementBinder::Visit(EnumTypeNode& enumTypeNode)
 280 {
 281     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&enumTypeNode);
 282     Assert(symbol->GetSymbolType() == SymbolType::enumTypeSymbol"enum type symbols expected");
 283     EnumTypeSymbol* enumTypeSymbol = static_cast<EnumTypeSymbol*>(symbol);
 284     std::unique_ptr<BoundEnumTypeDefinition> boundEnum(new BoundEnumTypeDefinition(enumTypeSymbol));
 285     boundCompileUnit.AddBoundNode(std::move(boundEnum));
 286 }
 287 
 288 void StatementBinder::Visit(ClassNode& classNode)
 289 {
 290     ContainerScope* prevContainerScope = containerScope;
 291     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&classNode);
 292     Assert(symbol->GetSymbolType() == SymbolType::classTypeSymbol || symbol->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type symbol expected");
 293     ClassTypeSymbol* classTypeSymbol = static_cast<ClassTypeSymbol*>(symbol);
 294     if (classTypeSymbol->IsClassTemplate())
 295     {
 296         return;
 297     }
 298     containerScope = symbol->GetContainerScope();
 299     std::unique_ptr<BoundClass> boundClass(new BoundClass(classTypeSymbol));
 300     BoundClass* prevClass = currentClass;
 301     currentClass = boundClass.get();
 302     int n = classNode.Members().Count();
 303     for (int i = 0; i < n; ++i)
 304     {
 305         Node* classMember = classNode.Members()[i];
 306         classMember->Accept(*this);
 307     }
 308     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(classNode.GetAttributes()symbolthis);
 309     boundCompileUnit.AddBoundNode(std::move(boundClass));
 310     DestructorSymbol* destructorSymbol = classTypeSymbol->Destructor();
 311     if (destructorSymbol && destructorSymbol->IsGeneratedFunction() && !GetGlobalFlag(GlobalFlags::info))
 312     {
 313         if (!boundCompileUnit.IsGeneratedDestructorInstantiated(destructorSymbol))
 314         {
 315             boundCompileUnit.SetGeneratedDestructorInstantiated(destructorSymbol);
 316             GenerateDestructorImplementation(currentClassdestructorSymbolboundCompileUnitcontainerScopecurrentFunctionclassNode.GetSpan()classNode.ModuleId());
 317         }
 318     }
 319     currentClass = prevClass;
 320     containerScope = prevContainerScope;
 321 }
 322 
 323 void StatementBinder::Visit(MemberVariableNode& memberVariableNode)
 324 {
 325     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&memberVariableNode);
 326     Assert(symbol->GetSymbolType() == SymbolType::memberVariableSymbol"member variable symbol expected");
 327     MemberVariableSymbol* memberVariableSymbol = static_cast<MemberVariableSymbol*>(symbol);
 328     TypeSymbol* typeSymbol = memberVariableSymbol->GetType();
 329     if (typeSymbol->IsClassTypeSymbol())
 330     {
 331         ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(typeSymbol);
 332         DestructorSymbol* destructorSymbol = classType->Destructor();
 333         if (destructorSymbol && destructorSymbol->IsGeneratedFunction() && !GetGlobalFlag(GlobalFlags::info))
 334         {
 335             if (!boundCompileUnit.IsGeneratedDestructorInstantiated(destructorSymbol))
 336             {
 337                 boundCompileUnit.SetGeneratedDestructorInstantiated(destructorSymbol);
 338                 std::unique_ptr<BoundClass> boundClass(new BoundClass(classType));
 339                 GenerateDestructorImplementation(boundClass.get()destructorSymbolboundCompileUnitcontainerScopecurrentFunctionmemberVariableNode.GetSpan()memberVariableNode.ModuleId());
 340                 boundCompileUnit.AddBoundNode(std::move(boundClass));
 341             }
 342         }
 343     }
 344 }
 345 
 346 void StatementBinder::Visit(FunctionNode& functionNode)
 347 {
 348     ContainerScope* prevContainerScope = containerScope;
 349     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&functionNode);
 350     Assert(symbol->GetSymbolType() == SymbolType::functionSymbol"function symbol expected");
 351     FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(symbol);
 352     if (!dontCheckDuplicateFunctionSymbols)
 353     {
 354         functionSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 355     }
 356     if (functionSymbol->IsFunctionTemplate())
 357     {
 358         return;
 359     }
 360     containerScope = symbol->GetContainerScope();
 361     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitfunctionSymbol));
 362     BoundFunction* prevFunction = currentFunction;
 363     currentFunction = boundFunction.get();
 364     if (functionNode.Body())
 365     {
 366         GenerateEnterAndExitFunctionCode(currentFunction);
 367         compoundLevel = 0;
 368         functionNode.Body()->Accept(*this);
 369         BoundStatement* boundStatement = statement.release();
 370         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 371         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 372         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 373         CheckFunctionReturnPaths(functionSymbolfunctionNodecontainerScopeboundCompileUnit);
 374         boundCompileUnit.AddBoundNode(std::move(boundFunction));
 375     }
 376     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(functionNode.GetAttributes()symbolthis);
 377     currentFunction = prevFunction;
 378     containerScope = prevContainerScope;
 379 }
 380 
 381 void StatementBinder::Visit(FullInstantiationRequestNode& fullInstantiationRequestNode)
 382 {
 383     TypeSymbol* type = ResolveType(fullInstantiationRequestNode.TemplateId()boundCompileUnitcontainerScope);
 384     if (type->GetSymbolType() != SymbolType::classTemplateSpecializationSymbol)
 385     {
 386         throw Exception("full instantiation request expects subject template identifier to be a class template specialization"
 387             fullInstantiationRequestNode.GetSpan()
 388             fullInstantiationRequestNode.ModuleId());
 389     }
 390     ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(type);
 391     specialization->SetHasFullInstantiation();
 392 }
 393 
 394 void StatementBinder::Visit(StaticConstructorNode& staticConstructorNode)
 395 {
 396     ContainerScope* prevContainerScope = containerScope;
 397     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&staticConstructorNode);
 398     Assert(symbol->GetSymbolType() == SymbolType::staticConstructorSymbol "static constructor symbol expected");
 399     StaticConstructorSymbol* staticConstructorSymbol = static_cast<StaticConstructorSymbol*>(symbol);
 400     if (!dontCheckDuplicateFunctionSymbols)
 401     {
 402         staticConstructorSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 403     }
 404     StaticConstructorSymbol* prevStaticConstructorSymbol = currentStaticConstructorSymbol;
 405     currentStaticConstructorSymbol = staticConstructorSymbol;
 406     containerScope = symbol->GetContainerScope();
 407     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitstaticConstructorSymbol));
 408     BoundFunction* prevFunction = currentFunction;
 409     currentFunction = boundFunction.get();
 410     if (staticConstructorNode.Body())
 411     {
 412         GenerateEnterAndExitFunctionCode(currentFunction);
 413         StaticConstructorNode* prevStaticConstructorNode = currentStaticConstructorNode;
 414         currentStaticConstructorNode = &staticConstructorNode;
 415         compoundLevel = 0;
 416         staticConstructorNode.Body()->Accept(*this);
 417         currentStaticConstructorNode = prevStaticConstructorNode;
 418         BoundStatement* boundStatement = statement.release();
 419         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 420         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 421         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 422         CheckFunctionReturnPaths(staticConstructorSymbolstaticConstructorNodecontainerScopeboundCompileUnit);
 423         currentClass->AddMember(std::move(boundFunction));
 424     }
 425     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(staticConstructorNode.GetAttributes()symbolthis);
 426     currentFunction = prevFunction;
 427     containerScope = prevContainerScope;
 428     currentStaticConstructorSymbol = prevStaticConstructorSymbol;
 429 }
 430 
 431 void StatementBinder::GenerateEnterAndExitFunctionCode(BoundFunction* boundFunction)
 432 {
 433     if (cmajor::symbols::GetBackEnd() == cmajor::symbols::BackEnd::cmsx) return;
 434     Span span;
 435     boost::uuids::uuid moduleId = boost::uuids::nil_uuid();
 436     if (boundFunction->GetFunctionSymbol()->DontThrow()) return;
 437     TypeSymbol* systemRuntimeUnwindInfoSymbol = boundCompileUnit.GetSystemRuntimeUnwindInfoSymbol();
 438     if (systemRuntimeUnwindInfoSymbol == nullptr)
 439     {
 440         sngcm::ast::IdentifierNode systemRuntimeUnwindInfoNode(spanmoduleIdU"System.Runtime.UnwindInfo");
 441         systemRuntimeUnwindInfoSymbol = ResolveType(&systemRuntimeUnwindInfoNodeboundCompileUnitcontainerScope);
 442         boundCompileUnit.SetSystemRuntimeUnwindInfoSymbol(systemRuntimeUnwindInfoSymbol);
 443     }
 444     FunctionSymbol* initUnwindSymbol = boundCompileUnit.GetInitUnwindInfoFunctionSymbol();
 445     if (initUnwindSymbol == nullptr)
 446     {
 447         boundCompileUnit.GenerateInitUnwindInfoFunctionSymbol();
 448     }
 449     LocalVariableSymbol* prevUnwindInfoVariableSymbol = new LocalVariableSymbol(spanmoduleIdU"@prevUnwindInfo");
 450     containerScope->Install(prevUnwindInfoVariableSymbol);
 451     prevUnwindInfoVariableSymbol->SetType(systemRuntimeUnwindInfoSymbol->AddPointer(spanmoduleId));
 452     boundFunction->GetFunctionSymbol()->SetPrevUnwindInfoVar(prevUnwindInfoVariableSymbol);
 453     sngcm::ast::IdentifierNode* prevUnwindInfoNode1 = new IdentifierNode(spanmoduleIdU"@prevUnwindInfo");
 454     symbolTable.MapSymbol(prevUnwindInfoNode1prevUnwindInfoVariableSymbol);
 455     symbolTable.MapNode(prevUnwindInfoNode1prevUnwindInfoVariableSymbol);
 456     sngcm::ast::InvokeNode* pushUnwindInfo = new sngcm::ast::InvokeNode(spanmoduleIdnew sngcm::ast::IdentifierNode(spanmoduleIdU"RtPushUnwindInfo"));
 457     LocalVariableSymbol* unwindInfoVariableSymbol = new LocalVariableSymbol(spanmoduleIdU"@unwindInfo");
 458     containerScope->Install(unwindInfoVariableSymbol);
 459     unwindInfoVariableSymbol->SetType(systemRuntimeUnwindInfoSymbol);
 460     boundFunction->GetFunctionSymbol()->SetUnwindInfoVar(unwindInfoVariableSymbol);
 461     sngcm::ast::IdentifierNode* unwindInfoNode1 = new IdentifierNode(spanmoduleIdU"@unwindInfo");
 462     symbolTable.MapSymbol(unwindInfoNode1unwindInfoVariableSymbol);
 463     symbolTable.MapNode(unwindInfoNode1unwindInfoVariableSymbol);
 464     pushUnwindInfo->AddArgument(new sngcm::ast::CastNode(spanmoduleIdnew sngcm::ast::PointerNode(spanmoduleIdnew sngcm::ast::VoidNode(spanmoduleId))new AddrOfNode(spanmoduleIdunwindInfoNode1)));
 465     sngcm::ast::AssignmentStatementNode assignUnwindInfo(spanmoduleIdprevUnwindInfoNode1
 466         new sngcm::ast::CastNode(spanmoduleIdnew PointerNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System.Runtime.UnwindInfo"))pushUnwindInfo));
 467     assignUnwindInfo.Accept(*this);
 468     std::unique_ptr<BoundStatement> pushUnwindInfoStatement(statement.release());
 469 
 470     sngcm::ast::IdentifierNode* prevUnwindInfoNode2 = new IdentifierNode(spanmoduleIdU"@prevUnwindInfo");
 471     symbolTable.MapSymbol(prevUnwindInfoNode2prevUnwindInfoVariableSymbol);
 472     symbolTable.MapNode(prevUnwindInfoNode2prevUnwindInfoVariableSymbol);
 473     sngcm::ast::IdentifierNode* unwindInfoNode2 = new IdentifierNode(spanmoduleIdU"@unwindInfo");
 474     symbolTable.MapSymbol(unwindInfoNode2unwindInfoVariableSymbol);
 475     symbolTable.MapNode(unwindInfoNode2unwindInfoVariableSymbol);
 476     sngcm::ast::AssignmentStatementNode assignUnwindInfoNext(spanmoduleIdnew sngcm::ast::DotNode(spanmoduleIdunwindInfoNode2new IdentifierNode(spanmoduleIdU"next"))prevUnwindInfoNode2);
 477     assignUnwindInfoNext.Accept(*this);
 478     std::unique_ptr<BoundStatement> assignUnwindInfoNextStatement(statement.release());
 479 
 480     sngcm::ast::IdentifierNode* unwindInfoNode3 = new IdentifierNode(spanmoduleIdU"@unwindInfo");
 481     symbolTable.MapSymbol(unwindInfoNode3unwindInfoVariableSymbol);
 482     symbolTable.MapNode(unwindInfoNode3unwindInfoVariableSymbol);
 483     sngcm::ast::FunctionPtrNode* functionPtrNode = new sngcm::ast::FunctionPtrNode(spanmoduleId);
 484     BoundFunctionPtr* boundFunctionPtr = new BoundFunctionPtr(spanmoduleIdboundFunction->GetFunctionSymbol()boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId));
 485     BoundBitCast* boundBitCast = new BoundBitCast(std::unique_ptr<BoundExpression>(boundFunctionPtr)boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(spanmoduleId));
 486     std::unique_ptr<BoundExpression> boundFunctionPtrAsVoidPtr(boundBitCast);
 487     functionPtrNode->SetBoundExpression(boundFunctionPtrAsVoidPtr.get());
 488     sngcm::ast::AssignmentStatementNode assignFunctionPtr(spanmoduleIdnew sngcm::ast::DotNode(spanmoduleIdunwindInfoNode3new IdentifierNode(spanmoduleIdU"function"))
 489         new sngcm::ast::CastNode(spanmoduleIdnew sngcm::ast::PointerNode(spanmoduleIdnew sngcm::ast::VoidNode(spanmoduleId))functionPtrNode));
 490     assignFunctionPtr.Accept(*this);
 491     std::unique_ptr<BoundStatement> assignFunctionPtrStatement(statement.release());
 492 
 493     sngcm::ast::IdentifierNode* unwindInfoNode4 = new IdentifierNode(spanmoduleIdU"@unwindInfo");
 494     symbolTable.MapSymbol(unwindInfoNode4unwindInfoVariableSymbol);
 495     symbolTable.MapNode(unwindInfoNode4unwindInfoVariableSymbol);
 496     sngcm::ast::AssignmentStatementNode assignUnwindInfoLine(spanmoduleIdnew sngcm::ast::DotNode(spanmoduleIdunwindInfoNode4new IdentifierNode(spanmoduleIdU"line"))
 497         new IntLiteralNode(spanmoduleId0));
 498     assignUnwindInfoLine.Accept(*this);
 499     std::unique_ptr<BoundStatement> assignUnwindInfoLineStatement(statement.release());
 500 
 501     sngcm::ast::IdentifierNode* prevUnwindInfoNode3 = new IdentifierNode(spanmoduleIdU"@prevUnwindInfo");
 502     symbolTable.MapSymbol(prevUnwindInfoNode3prevUnwindInfoVariableSymbol);
 503     symbolTable.MapNode(prevUnwindInfoNode3prevUnwindInfoVariableSymbol);
 504     sngcm::ast::InvokeNode* setPrevUnwindInfoListPtr = new sngcm::ast::InvokeNode(spanmoduleIdnew sngcm::ast::IdentifierNode(spanmoduleIdU"RtPopUnwindInfo"));
 505     setPrevUnwindInfoListPtr->AddArgument(new CastNode(spanmoduleIdnew PointerNode(spanmoduleIdnew VoidNode(spanmoduleId))prevUnwindInfoNode3));
 506     sngcm::ast::ExpressionStatementNode setPrevUnwindInfoList(spanmoduleIdsetPrevUnwindInfoListPtr);
 507     setPrevUnwindInfoList.Accept(*this);
 508     std::unique_ptr<BoundStatement> setPrevUnwindInfoListStatement(statement.release());
 509 
 510     std::vector<std::std::unique_ptr<BoundStatement>>enterCode;
 511     enterCode.push_back(std::move(pushUnwindInfoStatement));
 512     enterCode.push_back(std::move(assignUnwindInfoNextStatement));
 513     enterCode.push_back(std::move(assignFunctionPtrStatement));
 514     enterCode.push_back(std::move(assignUnwindInfoLineStatement));
 515     boundFunction->SetEnterCode(std::move(enterCode));
 516 
 517     std::unique_ptr<BoundStatement> setLineCode;
 518     sngcm::ast::IdentifierNode* unwindInfoNode5 = new IdentifierNode(spanmoduleIdU"@unwindInfo");
 519     symbolTable.MapSymbol(unwindInfoNode5unwindInfoVariableSymbol);
 520     sngcm::ast::AssignmentStatementNode setUnwindInfoLine(spanmoduleIdnew sngcm::ast::DotNode(spanmoduleIdunwindInfoNode5new IdentifierNode(spanmoduleIdU"line"))
 521         new IntLiteralNode(spanmoduleId0));
 522     setUnwindInfoLine.Accept(*this);
 523     std::unique_ptr<BoundStatement> setLineStatement(statement.release());
 524     boundFunction->SetLineCode(std::move(setLineStatement));
 525 
 526     std::vector<std::std::unique_ptr<BoundStatement>>exitCode;
 527     exitCode.push_back(std::move(setPrevUnwindInfoListStatement));
 528     boundFunction->SetExitCode(std::move(exitCode));
 529 }
 530 
 531 void StatementBinder::Visit(ConstructorNode& constructorNode)
 532 {
 533     ContainerScope* prevContainerScope = containerScope;
 534     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&constructorNode);
 535     Assert(symbol->GetSymbolType() == SymbolType::constructorSymbol"constructor symbol expected");
 536     ConstructorSymbol* constructorSymbol = static_cast<ConstructorSymbol*>(symbol);
 537     if (!dontCheckDuplicateFunctionSymbols)
 538     {
 539         constructorSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 540     }
 541     ConstructorSymbol* prevConstructorSymbol = currentConstructorSymbol;
 542     currentConstructorSymbol = constructorSymbol;
 543     containerScope = symbol->GetContainerScope();
 544     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitconstructorSymbol));
 545     BoundFunction* prevFunction = currentFunction;
 546     currentFunction = boundFunction.get();
 547     if (constructorNode.Body())
 548     {
 549         GenerateEnterAndExitFunctionCode(currentFunction);
 550         ConstructorNode* prevConstructorNode = currentConstructorNode;
 551         currentConstructorNode = &constructorNode;
 552         compoundLevel = 0;
 553         constructorNode.Body()->Accept(*this);
 554         currentConstructorNode = prevConstructorNode;
 555         BoundStatement* boundStatement = statement.release();
 556         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 557         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 558         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 559     }
 560     else if (constructorSymbol->IsDefault())
 561     {
 562         ConstructorNode* prevConstructorNode = currentConstructorNode;
 563         currentConstructorNode = &constructorNode;
 564         std::unique_ptr<BoundCompoundStatement> boundCompoundStatement(new BoundCompoundStatement(constructorNode.GetSpan()constructorNode.ModuleId()));
 565         GenerateClassInitialization(currentConstructorSymbolcurrentConstructorNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethistrue
 566             constructorNode.GetSpan()constructorNode.ModuleId());
 567         currentConstructorNode = prevConstructorNode;
 568         boundFunction->SetBody(std::move(boundCompoundStatement));
 569     }
 570     if (boundFunction->Body())
 571     {
 572         CheckFunctionReturnPaths(constructorSymbolconstructorNodecontainerScopeboundCompileUnit);
 573         currentClass->AddMember(std::move(boundFunction));
 574     }
 575     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(constructorNode.GetAttributes()symbolthis);
 576     currentFunction = prevFunction;
 577     containerScope = prevContainerScope;
 578     currentConstructorSymbol = prevConstructorSymbol;
 579 }
 580 
 581 void StatementBinder::Visit(DestructorNode& destructorNode)
 582 {
 583     ContainerScope* prevContainerScope = containerScope;
 584     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&destructorNode);
 585     Assert(symbol->GetSymbolType() == SymbolType::destructorSymbol"destructor symbol expected");
 586     DestructorSymbol* destructorSymbol = static_cast<DestructorSymbol*>(symbol);
 587     if (!dontCheckDuplicateFunctionSymbols)
 588     {
 589         destructorSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 590     }
 591     DestructorSymbol* prevDestructorSymbol = currentDestructorSymbol;
 592     currentDestructorSymbol = destructorSymbol;
 593     containerScope = symbol->GetContainerScope();
 594     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitdestructorSymbol));
 595     BoundFunction* prevFunction = currentFunction;
 596     currentFunction = boundFunction.get();
 597     if (destructorNode.Body())
 598     {
 599         GenerateEnterAndExitFunctionCode(currentFunction);
 600         DestructorNode* prevDestructorNode = currentDestructorNode;
 601         currentDestructorNode = &destructorNode;
 602         compoundLevel = 0;
 603         destructorNode.Body()->Accept(*this);
 604         currentDestructorNode = prevDestructorNode;
 605         BoundStatement* boundStatement = statement.release();
 606         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 607         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 608         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 609     }
 610     else if (destructorSymbol->IsDefault())
 611     {
 612         DestructorNode* prevDestructorNode = currentDestructorNode;
 613         currentDestructorNode = &destructorNode;
 614         std::unique_ptr<BoundCompoundStatement> boundCompoundStatement(new BoundCompoundStatement(destructorNode.GetSpan()destructorNode.ModuleId()));
 615         GenerateClassTermination(currentDestructorSymbolcurrentDestructorNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethis
 616             currentDestructorNode->GetSpan()currentDestructorNode->ModuleId());
 617         currentDestructorNode = prevDestructorNode;
 618         boundFunction->SetBody(std::move(boundCompoundStatement));
 619     }
 620     if (boundFunction->Body())
 621     {
 622         CheckFunctionReturnPaths(destructorSymboldestructorNodecontainerScopeboundCompileUnit);
 623         currentClass->AddMember(std::move(boundFunction));
 624     }
 625     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(destructorNode.GetAttributes()symbolthis);
 626     currentFunction = prevFunction;
 627     containerScope = prevContainerScope;
 628     currentDestructorSymbol = prevDestructorSymbol;
 629 }
 630 
 631 void StatementBinder::Visit(MemberFunctionNode& memberFunctionNode)
 632 {
 633     ContainerScope* prevContainerScope = containerScope;
 634     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&memberFunctionNode);
 635     Assert(symbol->GetSymbolType() == SymbolType::memberFunctionSymbol"member function symbol expected");
 636     MemberFunctionSymbol* memberFunctionSymbol = static_cast<MemberFunctionSymbol*>(symbol);
 637     if (!dontCheckDuplicateFunctionSymbols)
 638     {
 639         memberFunctionSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 640     }
 641     MemberFunctionSymbol* prevMemberFunctionSymbol = currentMemberFunctionSymbol;
 642     currentMemberFunctionSymbol = memberFunctionSymbol;
 643     containerScope = symbol->GetContainerScope();
 644     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitmemberFunctionSymbol));
 645     BoundFunction* prevFunction = currentFunction;
 646     currentFunction = boundFunction.get();
 647     if (memberFunctionNode.Body())
 648     {
 649         GenerateEnterAndExitFunctionCode(currentFunction);
 650         MemberFunctionNode* prevMemberFunctionNode = currentMemberFunctionNode;
 651         currentMemberFunctionNode = &memberFunctionNode;
 652         compoundLevel = 0;
 653         memberFunctionNode.Body()->Accept(*this);
 654         currentMemberFunctionNode = prevMemberFunctionNode;
 655         BoundStatement* boundStatement = statement.release();
 656         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 657         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 658         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 659     }
 660     else if (memberFunctionSymbol->IsDefault())
 661     {
 662         Assert(memberFunctionSymbol->GroupName() == U"operator=""operator= expected");
 663         MemberFunctionNode* prevMemberFunctionNode = currentMemberFunctionNode;
 664         currentMemberFunctionNode = &memberFunctionNode;
 665         std::unique_ptr<BoundCompoundStatement> boundCompoundStatement(new BoundCompoundStatement(memberFunctionNode.GetSpan()memberFunctionNode.ModuleId()));
 666         GenerateClassAssignment(currentMemberFunctionSymbolcurrentMemberFunctionNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethistrue
 667             memberFunctionNode.GetSpan()memberFunctionNode.ModuleId());
 668         currentMemberFunctionNode = prevMemberFunctionNode;
 669         boundFunction->SetBody(std::move(boundCompoundStatement));
 670     }
 671     if (boundFunction->Body())
 672     {
 673         CheckFunctionReturnPaths(memberFunctionSymbolmemberFunctionNodecontainerScopeboundCompileUnit);
 674         currentClass->AddMember(std::move(boundFunction));
 675     }
 676     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(memberFunctionNode.GetAttributes()symbolthis);
 677     currentFunction = prevFunction;
 678     containerScope = prevContainerScope;
 679     currentMemberFunctionSymbol = prevMemberFunctionSymbol;
 680 }
 681 
 682 void StatementBinder::Visit(ConversionFunctionNode& conversionFunctionNode)
 683 {
 684     ContainerScope* prevContainerScope = containerScope;
 685     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&conversionFunctionNode);
 686     Assert(symbol->GetSymbolType() == SymbolType::conversionFunctionSymbol"conversion function symbol expected");
 687     ConversionFunctionSymbol* conversionFunctionSymbol = static_cast<ConversionFunctionSymbol*>(symbol);
 688     if (!dontCheckDuplicateFunctionSymbols)
 689     {
 690         conversionFunctionSymbol->FunctionGroup()->CheckDuplicateFunctionSymbols();
 691     }
 692     containerScope = symbol->GetContainerScope();
 693     std::unique_ptr<BoundFunction> boundFunction(new BoundFunction(&boundCompileUnitconversionFunctionSymbol));
 694     BoundFunction* prevFunction = currentFunction;
 695     currentFunction = boundFunction.get();
 696     if (conversionFunctionNode.Body())
 697     {
 698         GenerateEnterAndExitFunctionCode(currentFunction);
 699         compoundLevel = 0;
 700         conversionFunctionNode.Body()->Accept(*this);
 701         BoundStatement* boundStatement = statement.release();
 702         Assert(boundStatement->GetBoundNodeType() == BoundNodeType::boundCompoundStatement"bound compound statement expected");
 703         BoundCompoundStatement* compoundStatement = static_cast<BoundCompoundStatement*>(boundStatement);
 704         boundFunction->SetBody(std::unique_ptr<BoundCompoundStatement>(compoundStatement));
 705         CheckFunctionReturnPaths(conversionFunctionSymbolconversionFunctionNodecontainerScopeboundCompileUnit);
 706         currentClass->AddMember(std::move(boundFunction));
 707     }
 708     boundCompileUnit.GetAttributeBinder()->GenerateImplementation(conversionFunctionNode.GetAttributes()symbolthis);
 709     currentFunction = prevFunction;
 710     containerScope = prevContainerScope;
 711 }
 712 
 713 void StatementBinder::Visit(CompoundStatementNode& compoundStatementNode)
 714 {
 715     ContainerScope* prevContainerScope = containerScope;
 716     Symbol* symbol = symbolTable.GetSymbol(&compoundStatementNode);
 717     Assert(symbol->GetSymbolType() == SymbolType::declarationBlock"declaration block expected");
 718     DeclarationBlock* declarationBlock = static_cast<DeclarationBlock*>(symbol);
 719     containerScope = declarationBlock->GetContainerScope();
 720     std::unique_ptr<BoundCompoundStatement> boundCompoundStatement(new BoundCompoundStatement(compoundStatementNode.BeginBraceSpan()compoundStatementNode.EndBraceSpan()compoundStatementNode.ModuleId()));
 721     if (compoundLevel == 0)
 722     {
 723         if (GetGlobalFlag(GlobalFlags::profile))
 724         {
 725             bool profile = true;
 726             if (currentFunction->GetFunctionSymbol()->IsProgramMain())
 727             {
 728                 profile = false;
 729             }
 730             else if (currentClass && currentClass->GetClassTypeSymbol()->FullName() == U"System.Runtime.FunctionProfiler")
 731             {
 732                 profile = false;
 733             }
 734             if (profile)
 735             {
 736                 boost::uuids::uuid functionId = currentFunction->GetFunctionSymbol()->FunctionId();
 737                 symbolTable.MapProfiledFunction(functionIdcurrentFunction->GetFunctionSymbol()->FullName());
 738                 ConstructionStatementNode constructFunctionProfiler(compoundStatementNode.GetSpan()compoundStatementNode.ModuleId()
 739                     new IdentifierNode(compoundStatementNode.GetSpan()compoundStatementNode.ModuleId()U"System.Runtime.FunctionProfiler")
 740                     new IdentifierNode(compoundStatementNode.GetSpan()compoundStatementNode.ModuleId()U"@functionProfiler"));
 741                 constructFunctionProfiler.AddArgument(new UuidLiteralNode(compoundStatementNode.GetSpan()functionId));
 742                 symbolTable.SetCurrentFunctionSymbol(currentFunction->GetFunctionSymbol());
 743                 symbolTable.BeginContainer(containerScope->Container());
 744                 SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
 745                 constructFunctionProfiler.Accept(symbolCreatorVisitor);
 746                 symbolTable.EndContainer();
 747                 TypeBinder typeBinder(boundCompileUnit);
 748                 typeBinder.SetContainerScope(containerScope);
 749                 typeBinder.SetCurrentFunctionSymbol(currentFunction->GetFunctionSymbol());
 750                 constructFunctionProfiler.Accept(typeBinder);
 751                 constructFunctionProfiler.Accept(*this);
 752                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(ReleaseStatement()));
 753             }
 754         }
 755         if (currentStaticConstructorSymbol && currentStaticConstructorNode)
 756         {
 757             GenerateStaticClassInitialization(currentStaticConstructorSymbolcurrentStaticConstructorNodeboundCompileUnitboundCompoundStatement.get()currentFunctioncontainerScopethis
 758                 boundCompoundStatement->GetSpan()boundCompoundStatement->ModuleId());
 759         }
 760         else if (currentConstructorSymbol && currentConstructorNode)
 761         {
 762             GenerateClassInitialization(currentConstructorSymbolcurrentConstructorNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethisfalse
 763                 boundCompoundStatement->GetSpan()boundCompoundStatement->ModuleId());
 764         }
 765         else if (currentMemberFunctionSymbol && currentMemberFunctionSymbol->GroupName() == U"operator=" && currentMemberFunctionNode)
 766         {
 767             GenerateClassAssignment(currentMemberFunctionSymbolcurrentMemberFunctionNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethisfalse
 768                 boundCompoundStatement->GetSpan()boundCompoundStatement->ModuleId());
 769         }
 770         else if (currentMemberFunctionSymbol && currentMemberFunctionSymbol->IsStatic() && currentMemberFunctionNode)
 771         {
 772             if (currentClass->GetClassTypeSymbol()->StaticConstructor())
 773             {
 774                 boundCompoundStatement->AddStatement(std::unique_ptr<BoundStatement>(new BoundInitializationStatement(std::unique_ptr<BoundExpression>(
 775                     new BoundFunctionCall(boundCompoundStatement->GetSpan()boundCompoundStatement->ModuleId()currentClass->GetClassTypeSymbol()->StaticConstructor())))));
 776             }
 777         }
 778     }
 779     ++compoundLevel;
 780     int n = compoundStatementNode.Statements().Count();
 781     for (int i = 0; i < n; ++i)
 782     {
 783         StatementNode* statementNode = compoundStatementNode.Statements()[i];
 784         statementNode->Accept(*this);
 785         boundCompoundStatement->AddStatement(std::move(statement));
 786     }
 787     --compoundLevel;
 788     if (compoundLevel == 0 && currentDestructorSymbol && currentDestructorNode)
 789     {
 790         GenerateClassTermination(currentDestructorSymbolcurrentDestructorNodeboundCompoundStatement.get()currentFunctionboundCompileUnitcontainerScopethis
 791             boundCompoundStatement->EndSpan()boundCompoundStatement->ModuleId());
 792     }
 793     AddStatement(boundCompoundStatement.release());
 794     containerScope = prevContainerScope;
 795 }
 796 
 797 void StatementBinder::Visit(ReturnStatementNode& returnStatementNode)
 798 {
 799     if (returnStatementNode.Expression())
 800     {
 801         if (currentFunction->GetFunctionSymbol()->ReturnsClassInterfaceOrClassDelegateByValue())
 802         {
 803             std::vector<FunctionScopeLookup> classReturnLookups;
 804             classReturnLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
 805             classReturnLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcurrentFunction->GetFunctionSymbol()->ReturnType()->ClassInterfaceEnumDelegateOrNsScope()));
 806             classReturnLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
 807             std::vector<std::std::unique_ptr<BoundExpression>>classReturnArgs;
 808             classReturnArgs.push_back(std::unique_ptr<BoundExpression>(new BoundParameter(returnStatementNode.GetSpan()returnStatementNode.ModuleId()currentFunction->GetFunctionSymbol()->ReturnParam())));
 809             TypeSymbol* returnType = currentFunction->GetFunctionSymbol()->ReturnType();
 810             bool returnClassDelegateType = returnType->GetSymbolType() == SymbolType::classDelegateTypeSymbol;
 811             std::unique_ptr<BoundExpression> expression = BindExpression(returnStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethisfalsereturnClassDelegateType
 812                 returnClassDelegateType);
 813             bool exceptionCapture = false;
 814             if (insideCatch && expression->ContainsExceptionCapture())
 815             {
 816                 exceptionCapture = true;
 817             }
 818             if (expression->GetBoundNodeType() == BoundNodeType::boundLocalVariable)
 819             {
 820                 std::vector<FunctionScopeLookup> rvalueLookups;
 821                 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
 822                 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
 823                 std::vector<std::std::unique_ptr<BoundExpression>>rvalueArguments;
 824                 if (returnClassDelegateType && expression->GetType()->BaseType()->GetSymbolType() == SymbolType::functionGroupTypeSymbol)
 825                 {
 826                     TypeSymbol* exprType = expression->GetType();
 827                     ArgumentMatch argumentMatch;
 828                     expression.reset(new BoundConversion(std::move(expression)
 829                         boundCompileUnit.GetConversion(exprTypereturnTypecontainerScopecurrentFunctionreturnStatementNode.GetSpan()returnStatementNode.ModuleId()argumentMatch)));
 830                 }
 831                 rvalueArguments.push_back(std::move(expression));
 832                 std::unique_ptr<BoundExpression> rvalueExpr = ResolveOverload(U"System.Rvalue"containerScopervalueLookupsrvalueArgumentsboundCompileUnitcurrentFunction
 833                     returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 834                 expression = std::move(rvalueExpr);
 835             }
 836             classReturnArgs.push_back(std::move(expression));
 837             std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopeclassReturnLookupsclassReturnArgsboundCompileUnitcurrentFunction
 838                 returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 839             std::unique_ptr<BoundStatement> constructStatement(new BoundInitializationStatement(std::move(constructorCall)));
 840             AddStatement(constructStatement.release());
 841             std::unique_ptr<BoundFunctionCall> returnFunctionCall;
 842             std::unique_ptr<BoundStatement> returnStatement(new BoundReturnStatement(std::move(returnFunctionCall)returnStatementNode.GetSpan()returnStatementNode.ModuleId()));
 843             if (exceptionCapture)
 844             {
 845                 AddReleaseExceptionStatement(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 846             }
 847             AddStatement(returnStatement.release());
 848         }
 849         else
 850         {
 851             TypeSymbol* returnType = currentFunction->GetFunctionSymbol()->ReturnType();
 852             bool returnDelegateType = false;
 853             bool returnClassDelegateType = false;
 854             bool exceptionCapture = false;
 855             if (returnType)
 856             {
 857                 returnDelegateType = returnType->GetSymbolType() == SymbolType::delegateTypeSymbol;
 858                 returnClassDelegateType = returnType->GetSymbolType() == SymbolType::classDelegateTypeSymbol;
 859             }
 860             if (returnType && returnType->GetSymbolType() != SymbolType::voidTypeSymbol)
 861             {
 862                 std::vector<std::std::unique_ptr<BoundExpression>>returnTypeArgs;
 863                 BoundTypeExpression* boundTypeExpression = new BoundTypeExpression(returnStatementNode.GetSpan()returnStatementNode.ModuleId()returnType);
 864                 returnTypeArgs.push_back(std::unique_ptr<BoundTypeExpression>(boundTypeExpression));
 865                 std::vector<FunctionScopeLookup> functionScopeLookups;
 866                 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
 867                 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentreturnType->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
 868                 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
 869                 std::unique_ptr<BoundFunctionCall> returnFunctionCall = ResolveOverload(U"@return"containerScopefunctionScopeLookupsreturnTypeArgsboundCompileUnitcurrentFunction
 870                     returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 871                 std::unique_ptr<BoundExpression> expression = BindExpression(returnStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethisfalse
 872                     returnDelegateType || returnClassDelegateTypereturnClassDelegateType);
 873                 if (insideCatch && expression->ContainsExceptionCapture())
 874                 {
 875                     exceptionCapture = true;
 876                 }
 877                 std::vector<std::std::unique_ptr<BoundExpression>>returnValueArguments;
 878                 returnValueArguments.push_back(std::move(expression));
 879                 FunctionMatch functionMatch(returnFunctionCall->GetFunctionSymbol());
 880                 bool conversionFound = FindConversions(boundCompileUnitreturnFunctionCall->GetFunctionSymbol()returnValueArgumentsfunctionMatchConversionType::implicit_
 881                     containerScopecurrentFunctionreturnStatementNode.GetSpan()returnStatementNode.ModuleId());
 882                 if (conversionFound)
 883                 {
 884                     Assert(!functionMatch.argumentMatches.empty()"argument match expected");
 885                     ArgumentMatch argumentMatch = functionMatch.argumentMatches[0];
 886                     if (argumentMatch.preReferenceConversionFlags != OperationFlags::none)
 887                     {
 888                         if (argumentMatch.preReferenceConversionFlags == OperationFlags::addr)
 889                         {
 890                             TypeSymbol* type = returnValueArguments[0]->GetType()->AddLvalueReference(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 891                             BoundAddressOfExpression* addressOfExpression = new BoundAddressOfExpression(std::move(returnValueArguments[0])type);
 892                             returnValueArguments[0].reset(addressOfExpression);
 893                         }
 894                         else if (argumentMatch.preReferenceConversionFlags == OperationFlags::deref)
 895                         {
 896                             TypeSymbol* type = returnValueArguments[0]->GetType()->RemoveReference(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 897                             BoundDereferenceExpression* dereferenceExpression = new BoundDereferenceExpression(std::move(returnValueArguments[0])type);
 898                             returnValueArguments[0].reset(dereferenceExpression);
 899                         }
 900                     }
 901                     FunctionSymbol* conversionFun = argumentMatch.conversionFun;
 902                     if (conversionFun)
 903                     {
 904                         if (conversionFun->GetSymbolType() == SymbolType::constructorSymbol)
 905                         {
 906                             BoundFunctionCall* constructorCall = new BoundFunctionCall(returnStatementNode.GetSpan()returnStatementNode.ModuleId()conversionFun);
 907                             LocalVariableSymbol* temporary = currentFunction->GetFunctionSymbol()->CreateTemporary(conversionFun->ConversionTargetType()
 908                                 returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 909                             constructorCall->AddArgument(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(new BoundLocalVariable(returnStatementNode.GetSpan()returnStatementNode.ModuleId()temporary))
 910                                 conversionFun->ConversionTargetType()->AddPointer(returnStatementNode.GetSpan()returnStatementNode.ModuleId()))));
 911                             constructorCall->AddArgument(std::move(returnValueArguments[0]));
 912                             BoundConstructAndReturnTemporaryExpression* conversion = new BoundConstructAndReturnTemporaryExpression(std::unique_ptr<BoundExpression>(constructorCall)
 913                                 std::unique_ptr<BoundExpression>(new BoundLocalVariable(returnStatementNode.GetSpan()returnStatementNode.ModuleId()temporary)));
 914                             returnValueArguments[0].reset(conversion);
 915                         }
 916                         else
 917                         {
 918                             BoundConversion* boundConversion = new BoundConversion(std::unique_ptr<BoundExpression>(returnValueArguments[0].release())conversionFun);
 919                             returnValueArguments[0].reset(boundConversion);
 920                         }
 921                     }
 922                     if (argumentMatch.postReferenceConversionFlags != OperationFlags::none)
 923                     {
 924                         if (argumentMatch.postReferenceConversionFlags == OperationFlags::addr)
 925                         {
 926                             TypeSymbol* type = returnValueArguments[0]->GetType()->AddLvalueReference(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 927                             BoundAddressOfExpression* addressOfExpression = new BoundAddressOfExpression(std::move(returnValueArguments[0])type);
 928                             returnValueArguments[0].reset(addressOfExpression);
 929                         }
 930                         else if (argumentMatch.postReferenceConversionFlags == OperationFlags::deref)
 931                         {
 932                             TypeSymbol* type = returnValueArguments[0]->GetType()->RemoveReference(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 933                             BoundDereferenceExpression* dereferenceExpression = new BoundDereferenceExpression(std::move(returnValueArguments[0])type);
 934                             returnValueArguments[0].reset(dereferenceExpression);
 935                         }
 936                     }
 937                     returnFunctionCall->SetArguments(std::move(returnValueArguments));
 938                 }
 939                 else
 940                 {
 941                     throw Exception("no implicit conversion from '" + ToUtf8(returnValueArguments[0]->GetType()->FullName()) + "' to '" + ToUtf8(returnType->FullName()) + "' exists"
 942                         returnStatementNode.GetSpan()returnStatementNode.ModuleId()currentFunction->GetFunctionSymbol()->GetSpan()currentFunction->GetFunctionSymbol()->SourceModuleId());
 943                 }
 944                 CheckAccess(currentFunction->GetFunctionSymbol()returnFunctionCall->GetFunctionSymbol());
 945                 if (exceptionCapture)
 946                 {
 947                     AddReleaseExceptionStatement(returnStatementNode.GetSpan()returnStatementNode.ModuleId());
 948                 }
 949                 AddStatement(new BoundReturnStatement(std::move(returnFunctionCall)returnStatementNode.GetSpan()returnStatementNode.ModuleId()));
 950             }
 951             else
 952             {
 953                 if (returnType)
 954                 {
 955                     throw Exception("void function cannot return a value"returnStatementNode.Expression()->GetSpan()returnStatementNode.Expression()->ModuleId()
 956                         currentFunction->GetFunctionSymbol()->GetSpan()currentFunction->GetFunctionSymbol()->SourceModuleId());
 957                 }
 958                 else
 959                 {
 960                     throw Exception("constructor or assignment function cannot return a value"returnStatementNode.Expression()->GetSpan()returnStatementNode.Expression()->ModuleId()
 961                         currentFunction->GetFunctionSymbol()->GetSpan()currentFunction->GetFunctionSymbol()->SourceModuleId());
 962                 }
 963             }
 964         }
 965     }
 966     else
 967     {
 968         TypeSymbol* returnType = currentFunction->GetFunctionSymbol()->ReturnType();
 969         if (!returnType || returnType->GetSymbolType() == SymbolType::voidTypeSymbol)
 970         {
 971             std::unique_ptr<BoundFunctionCall> returnFunctionCall;
 972             AddStatement(new BoundReturnStatement(std::move(returnFunctionCall)returnStatementNode.GetSpan()returnStatementNode.ModuleId()));
 973         }
 974         else
 975         {
 976             throw Exception("nonvoid function must return a value"returnStatementNode.GetSpan()returnStatementNode.ModuleId()
 977                 currentFunction->GetFunctionSymbol()->GetSpan()currentFunction->GetFunctionSymbol()->SourceModuleId());
 978         }
 979     }
 980 }
 981 
 982 void StatementBinder::Visit(IfStatementNode& ifStatementNode)
 983 {
 984     bool exceptionCapture = false;
 985     std::unique_ptr<BoundExpression> condition = BindExpression(ifStatementNode.Condition()boundCompileUnitcurrentFunctioncontainerScopethis);
 986     if (insideCatch && condition->ContainsExceptionCapture())
 987     {
 988         exceptionCapture = true;
 989     }
 990     if (!TypesEqual(symbolTable.GetTypeByName(U"bool")condition->GetType()->PlainType(ifStatementNode.GetSpan()ifStatementNode.ModuleId())))
 991     {
 992         throw Exception("condition of an if statement must be a Boolean expression"ifStatementNode.Condition()->GetSpan()ifStatementNode.Condition()->ModuleId());
 993     }
 994     if (condition->GetType()->IsReferenceType())
 995     {
 996         TypeSymbol* baseType = condition->GetType()->BaseType();
 997         condition.reset(new BoundDereferenceExpression(std::move(condition)baseType));
 998     }
 999     std::unique_ptr<BoundStatement> s;
1000     if (statement)
1001     {
1002         s = std::move(statement);
1003     }
1004     ifStatementNode.ThenS()->Accept(*this);
1005     BoundStatement* thenS = statement.release();
1006     BoundStatement* elseS = nullptr;
1007     if (ifStatementNode.ElseS())
1008     {
1009         ifStatementNode.ElseS()->Accept(*this);
1010         elseS = statement.release();
1011     }
1012     if (s)
1013     {
1014         AddStatement(s.release());
1015     }
1016     if (exceptionCapture)
1017     {
1018         AddReleaseExceptionStatement(ifStatementNode.GetSpan()ifStatementNode.ModuleId());
1019     }
1020     AddStatement(new BoundIfStatement(ifStatementNode.GetSpan()ifStatementNode.ModuleId()std::move(condition)std::unique_ptr<BoundStatement>(thenS)std::unique_ptr<BoundStatement>(elseS)));
1021 }
1022 
1023 void StatementBinder::Visit(WhileStatementNode& whileStatementNode)
1024 {
1025     bool exceptionCapture = false;
1026     std::unique_ptr<BoundExpression> condition = BindExpression(whileStatementNode.Condition()boundCompileUnitcurrentFunctioncontainerScopethis);
1027     if (insideCatch && condition->ContainsExceptionCapture())
1028     {
1029         exceptionCapture = true;
1030     }
1031     if (!TypesEqual(symbolTable.GetTypeByName(U"bool")condition->GetType()->PlainType(whileStatementNode.GetSpan()whileStatementNode.ModuleId())))
1032     {
1033         throw Exception("condition of a while statement must be a Boolean expression"whileStatementNode.Condition()->GetSpan()whileStatementNode.Condition()->ModuleId());
1034     }
1035     if (condition->GetType()->IsReferenceType())
1036     {
1037         TypeSymbol* baseType = condition->GetType()->BaseType();
1038         condition.reset(new BoundDereferenceExpression(std::move(condition)baseType));
1039     }
1040     std::unique_ptr<BoundStatement> s;
1041     if (statement)
1042     {
1043         s = std::move(statement);
1044     }
1045     whileStatementNode.Statement()->Accept(*this);
1046     BoundStatement* stmt = statement.release();
1047     if (s)
1048     {
1049         AddStatement(s.release());
1050     }
1051     if (exceptionCapture)
1052     {
1053         AddReleaseExceptionStatement(whileStatementNode.GetSpan()whileStatementNode.ModuleId());
1054     }
1055     AddStatement(new BoundWhileStatement(whileStatementNode.GetSpan()whileStatementNode.ModuleId()std::move(condition)std::unique_ptr<BoundStatement>(stmt)));
1056 }
1057 
1058 void StatementBinder::Visit(DoStatementNode& doStatementNode)
1059 {
1060     bool exceptionCapture = false;
1061     std::unique_ptr<BoundExpression> condition = BindExpression(doStatementNode.Condition()boundCompileUnitcurrentFunctioncontainerScopethis);
1062     if (insideCatch && condition->ContainsExceptionCapture())
1063     {
1064         exceptionCapture = true;
1065     }
1066     if (!TypesEqual(symbolTable.GetTypeByName(U"bool")condition->GetType()->PlainType(doStatementNode.GetSpan()doStatementNode.ModuleId())))
1067     {
1068         throw Exception("condition of a do statement must be a Boolean expression"doStatementNode.Condition()->GetSpan()doStatementNode.Condition()->ModuleId());
1069     }
1070     if (condition->GetType()->IsReferenceType())
1071     {
1072         TypeSymbol* baseType = condition->GetType()->BaseType();
1073         condition.reset(new BoundDereferenceExpression(std::move(condition)baseType));
1074     }
1075     std::unique_ptr<BoundStatement> s;
1076     if (statement)
1077     {
1078         s = std::move(statement);
1079     }
1080     doStatementNode.Statement()->Accept(*this);
1081     BoundStatement* stmt = statement.release();
1082     if (s)
1083     {
1084         AddStatement(s.release());
1085     }
1086     if (exceptionCapture)
1087     {
1088         AddReleaseExceptionStatement(doStatementNode.GetSpan()doStatementNode.ModuleId());
1089     }
1090     AddStatement(new BoundDoStatement(doStatementNode.GetSpan()doStatementNode.ModuleId()std::unique_ptr<BoundStatement>(stmt)std::move(condition)));
1091 }
1092 
1093 void StatementBinder::Visit(ForStatementNode& forStatementNode)
1094 {
1095     ContainerScope* prevContainerScope = containerScope;
1096     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&forStatementNode);
1097     Assert(symbol->GetSymbolType() == SymbolType::declarationBlock"declaration block expected");
1098     DeclarationBlock* declarationBlock = static_cast<DeclarationBlock*>(symbol);
1099     containerScope = declarationBlock->GetContainerScope();
1100     std::unique_ptr<BoundExpression> condition;
1101     if (forStatementNode.Condition())
1102     {
1103         condition = BindExpression(forStatementNode.Condition()boundCompileUnitcurrentFunctioncontainerScopethis);
1104     }
1105     else
1106     {
1107         BooleanLiteralNode trueNode(forStatementNode.GetSpan()forStatementNode.ModuleId()true);
1108         condition = BindExpression(&trueNodeboundCompileUnitcurrentFunctioncontainerScopethis);
1109     }
1110     bool exceptionCapture = false;
1111     if (insideCatch && condition->ContainsExceptionCapture())
1112     {
1113         exceptionCapture = true;
1114     }
1115     if (!TypesEqual(symbolTable.GetTypeByName(U"bool")condition->GetType()->PlainType(forStatementNode.GetSpan()forStatementNode.ModuleId())))
1116     {
1117         throw Exception("condition of a for statement must be a Boolean expression"forStatementNode.Condition()->GetSpan()forStatementNode.Condition()->ModuleId());
1118     }
1119     if (condition->GetType()->IsReferenceType())
1120     {
1121         TypeSymbol* baseType = condition->GetType()->BaseType();
1122         condition.reset(new BoundDereferenceExpression(std::move(condition)baseType));
1123     }
1124     std::unique_ptr<BoundStatement> s;
1125     if (statement)
1126     {
1127         s = std::move(statement);
1128     }
1129     forStatementNode.InitS()->Accept(*this);
1130     BoundStatement* initS = statement.release();
1131     forStatementNode.LoopS()->Accept(*this);
1132     BoundStatement* loopS = statement.release();
1133     loopS->SetForLoopStatementNode();
1134     forStatementNode.ActionS()->Accept(*this);
1135     BoundStatement* actionS = statement.release();
1136     if (s)
1137     {
1138         AddStatement(s.release());
1139     }
1140     if (exceptionCapture)
1141     {
1142         AddReleaseExceptionStatement(forStatementNode.GetSpan()forStatementNode.ModuleId());
1143     }
1144     AddStatement(new BoundForStatement(forStatementNode.GetSpan()forStatementNode.ModuleId()std::unique_ptr<BoundStatement>(initS)std::move(condition)std::unique_ptr<BoundStatement>(loopS)
1145         std::unique_ptr<BoundStatement>(actionS)));
1146     containerScope = prevContainerScope;
1147 }
1148 
1149 void StatementBinder::Visit(BreakStatementNode& breakStatementNode)
1150 {
1151     const Node* parent = breakStatementNode.Parent();
1152     const StatementNode* parentStatement = nullptr;
1153     if (parent && parent->IsStatementNode())
1154     {
1155         parentStatement = static_cast<const StatementNode*>(parent);
1156     }
1157     while (parentStatement && !parentStatement->IsBreakEnclosingStatementNode())
1158     {
1159         parent = parentStatement->Parent();
1160         if (parent && parent->IsStatementNode())
1161         {
1162             parentStatement = static_cast<const StatementNode*>(parent);
1163         }
1164         else
1165         {
1166             parentStatement = nullptr;
1167         }
1168     }
1169     if (!parentStatement)
1170     {
1171         throw Exception("break statement must be enclosed in a while, do, for or switch statement"breakStatementNode.GetSpan()breakStatementNode.ModuleId());
1172     }
1173     AddStatement(new BoundBreakStatement(breakStatementNode.GetSpan()breakStatementNode.ModuleId()));
1174 }
1175 
1176 void StatementBinder::Visit(ContinueStatementNode& continueStatementNode)
1177 {
1178     const Node* parent = continueStatementNode.Parent();
1179     const StatementNode* parentStatement = nullptr;
1180     if (parent && parent->IsStatementNode())
1181     {
1182         parentStatement = static_cast<const StatementNode*>(parent);
1183     }
1184     while (parentStatement && !parentStatement->IsContinueEnclosingStatementNode())
1185     {
1186         parent = parentStatement->Parent();
1187         if (parent && parent->IsStatementNode())
1188         {
1189             parentStatement = static_cast<const StatementNode*>(parent);
1190         }
1191         else
1192         {
1193             parentStatement = nullptr;
1194         }
1195     }
1196     if (!parentStatement)
1197     {
1198         throw Exception("continue statement must be enclosed in a while, do or for statement"continueStatementNode.GetSpan()continueStatementNode.ModuleId());
1199     }
1200     AddStatement(new BoundContinueStatement(continueStatementNode.GetSpan()continueStatementNode.ModuleId()));
1201 }
1202 
1203 void StatementBinder::Visit(GotoStatementNode& gotoStatementNode)
1204 {
1205     currentFunction->SetHasGotos();
1206     boundCompileUnit.SetHasGotos();
1207     AddStatement(new BoundGotoStatement(gotoStatementNode.GetSpan()gotoStatementNode.ModuleId()gotoStatementNode.Target()));
1208 }
1209 
1210 void StatementBinder::Visit(ConstructionStatementNode& constructionStatementNode)
1211 {
1212     Symbol* symbol = boundCompileUnit.GetSymbolTable().GetSymbol(&constructionStatementNode);
1213     Assert(symbol->GetSymbolType() == SymbolType::localVariableSymbol"local variable symbol expected");
1214     LocalVariableSymbol* localVariableSymbol = static_cast<LocalVariableSymbol*>(symbol);
1215     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1216     BoundExpression* localVariable = new BoundLocalVariable(constructionStatementNode.GetSpan()constructionStatementNode.ModuleId()localVariableSymbol);
1217     arguments.push_back(std::unique_ptr<BoundExpression>(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(localVariable)
1218         localVariable->GetType()->AddPointer(constructionStatementNode.GetSpan()constructionStatementNode.ModuleId()))));
1219     bool constructDelegateOrClassDelegateType =
1220         localVariableSymbol->GetType()->GetSymbolType() == SymbolType::delegateTypeSymbol || 
1221         localVariableSymbol->GetType()->GetSymbolType() == SymbolType::classDelegateTypeSymbol;
1222     std::vector<FunctionScopeLookup> functionScopeLookups;
1223     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_localVariableSymbol->GetType()->ClassInterfaceEnumDelegateOrNsScope()));
1224     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1225     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1226     bool exceptionCapture = false;
1227     int n = constructionStatementNode.Arguments().Count();
1228     for (int i = 0; i < n; ++i)
1229     {
1230         Node* argumentNode = constructionStatementNode.Arguments()[i];
1231         std::unique_ptr<BoundExpression> argument = BindExpression(argumentNodeboundCompileUnitcurrentFunctioncontainerScopethisfalseconstructDelegateOrClassDelegateType);
1232         if (insideCatch && argument->ContainsExceptionCapture())
1233         {
1234             exceptionCapture = true;
1235         }
1236         arguments.push_back(std::move(argument));
1237     }
1238     std::unique_ptr<BoundFunctionCall> constructorCall = ResolveOverload(U"@constructor"containerScopefunctionScopeLookupsargumentsboundCompileUnitcurrentFunction
1239         constructionStatementNode.GetSpan()constructionStatementNode.ModuleId());
1240     FunctionSymbol* functionSymbol = constructorCall->GetFunctionSymbol();
1241     CheckAccess(currentFunction->GetFunctionSymbol()functionSymbol);
1242     if (exceptionCapture)
1243     {
1244         AddReleaseExceptionStatement(constructionStatementNode.GetSpan()constructionStatementNode.ModuleId());
1245     }
1246     if (functionSymbol->Parent()->IsClassTypeSymbol())
1247     {
1248         ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(functionSymbol->Parent());
1249         if (classType->Destructor() && classType->Destructor()->IsGeneratedFunction() && !GetGlobalFlag(GlobalFlags::info))
1250         {
1251             if (!boundCompileUnit.IsGeneratedDestructorInstantiated(classType->Destructor()))
1252             {
1253                 boundCompileUnit.SetGeneratedDestructorInstantiated(classType->Destructor());
1254                 std::unique_ptr<BoundClass> boundClass(new BoundClass(classType));
1255                 GenerateDestructorImplementation(boundClass.get()classType->Destructor()boundCompileUnitcontainerScopecurrentFunction
1256                     constructionStatementNode.GetSpan()constructionStatementNode.ModuleId());
1257                 boundCompileUnit.AddBoundNode(std::move(boundClass));
1258             }
1259         }
1260     }
1261     BoundConstructionStatement* boundConstructionStatement = new BoundConstructionStatement(std::move(constructorCall)constructionStatementNode.GetSpan()constructionStatementNode.ModuleId());
1262     boundConstructionStatement->SetLocalVariable(localVariableSymbol);
1263     AddStatement(boundConstructionStatement);
1264 }
1265 
1266 void StatementBinder::Visit(DeleteStatementNode& deleteStatementNode)
1267 {
1268     Span span;
1269     boost::uuids::uuid moduleId = boost::uuids::nil_uuid();
1270     if (GetBackEnd() == BackEnd::llvm)
1271     {
1272         span = deleteStatementNode.GetSpan();
1273         moduleId = deleteStatementNode.ModuleId();
1274     }
1275     bool exceptionCapture = false;
1276     std::unique_ptr<BoundExpression> ptr = BindExpression(deleteStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethis);
1277     if (insideCatch && ptr->ContainsExceptionCapture())
1278     {
1279         exceptionCapture = true;
1280     }
1281     if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1282     {
1283         if (GetConfig() == "debug")
1284         {
1285             std::vector<FunctionScopeLookup> lookups;
1286             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1287             lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1288             std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1289             arguments.push_back(std::move(std::unique_ptr<BoundExpression>(ptr->Clone())));
1290             std::unique_ptr<BoundFunctionCall> disposeCall = ResolveOverload(U"RtDispose"containerScopelookupsargumentsboundCompileUnitcurrentFunctionspanmoduleId);
1291             CheckAccess(currentFunction->GetFunctionSymbol()disposeCall->GetFunctionSymbol());
1292             AddStatement(new BoundExpressionStatement(std::move(disposeCall)spanmoduleId));
1293         }
1294     }
1295     std::unique_ptr<BoundExpression> memFreePtr;
1296     TypeSymbol* baseType = ptr->GetType()->BaseType();
1297     if (baseType->HasNontrivialDestructor())
1298     {
1299         Assert(baseType->GetSymbolType() == SymbolType::classTypeSymbol || baseType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type expected");
1300         ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(baseType);
1301         std::vector<FunctionScopeLookup> lookups;
1302         lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1303         lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->ClassInterfaceOrNsScope()));
1304         lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1305         std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1306         arguments.push_back(std::move(ptr));
1307         std::unique_ptr<BoundFunctionCall> destructorCall = ResolveOverload(U"@destructor"containerScopelookupsargumentsboundCompileUnitcurrentFunctionspanmoduleId);
1308         CheckAccess(currentFunction->GetFunctionSymbol()destructorCall->GetFunctionSymbol());
1309         if (destructorCall->GetFunctionSymbol()->IsVirtualAbstractOrOverride())
1310         {
1311             destructorCall->SetFlag(BoundExpressionFlags::virtualCall);
1312         }
1313         AddStatement(new BoundExpressionStatement(std::move(destructorCall)spanmoduleId));
1314         memFreePtr = BindExpression(deleteStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethis);
1315         if (insideCatch && memFreePtr->ContainsExceptionCapture())
1316         {
1317             exceptionCapture = true;
1318         }
1319     }
1320     else
1321     {
1322         memFreePtr = std::move(ptr);
1323     }
1324     std::vector<FunctionScopeLookup> lookups;
1325     lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1326     lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1327     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1328     arguments.push_back(std::move(memFreePtr));
1329     const char32_t* memFreeFunctionName = U"";
1330     if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1331     {
1332         memFreeFunctionName = U"RtMemFree";
1333     }
1334     else if (GetBackEnd() == BackEnd::cmsx)
1335     {
1336         memFreeFunctionName = U"MemFree";
1337     }
1338     std::unique_ptr<BoundFunctionCall> memFreeCall = ResolveOverload(memFreeFunctionNamecontainerScopelookupsargumentsboundCompileUnitcurrentFunctionspanmoduleId);
1339     CheckAccess(currentFunction->GetFunctionSymbol()memFreeCall->GetFunctionSymbol());
1340     if (exceptionCapture)
1341     {
1342         AddReleaseExceptionStatement(deleteStatementNode.GetSpan()deleteStatementNode.ModuleId());
1343     }
1344     AddStatement(new BoundExpressionStatement(std::move(memFreeCall)deleteStatementNode.GetSpan()deleteStatementNode.ModuleId()));
1345 }
1346 
1347 void StatementBinder::Visit(DestroyStatementNode& destroyStatementNode)
1348 {
1349     bool exceptionCapture = false;
1350     std::unique_ptr<BoundExpression> ptr = BindExpression(destroyStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethis);
1351     if (insideCatch && ptr->ContainsExceptionCapture())
1352     {
1353         exceptionCapture = true;
1354     }
1355     if (!ptr->GetType()->IsPointerType())
1356     {
1357         throw Exception("destroy statement needs pointer type operand"destroyStatementNode.GetSpan()destroyStatementNode.ModuleId());
1358     }
1359     TypeSymbol* pointeeType = ptr->GetType()->RemovePointer(destroyStatementNode.GetSpan()destroyStatementNode.ModuleId());
1360     if (pointeeType->HasNontrivialDestructor())
1361     {
1362         Assert(pointeeType->GetSymbolType() == SymbolType::classTypeSymbol || pointeeType->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol"class type expected");
1363         ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(pointeeType);
1364         std::vector<FunctionScopeLookup> lookups;
1365         lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1366         lookups.push_back(FunctionScopeLookup(ScopeLookup::this_classType->ClassInterfaceOrNsScope()));
1367         lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1368         std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1369         arguments.push_back(std::move(ptr));
1370         std::unique_ptr<BoundFunctionCall> destructorCall = ResolveOverload(U"@destructor"containerScopelookupsargumentsboundCompileUnitcurrentFunction
1371             destroyStatementNode.GetSpan()destroyStatementNode.ModuleId());
1372         CheckAccess(currentFunction->GetFunctionSymbol()destructorCall->GetFunctionSymbol());
1373         if (destructorCall->GetFunctionSymbol()->IsVirtualAbstractOrOverride())
1374         {
1375             destructorCall->SetFlag(BoundExpressionFlags::virtualCall);
1376         }
1377         if (exceptionCapture)
1378         {
1379             AddReleaseExceptionStatement(destroyStatementNode.GetSpan()destroyStatementNode.ModuleId());
1380         }
1381         AddStatement(new BoundExpressionStatement(std::move(destructorCall)destroyStatementNode.GetSpan()destroyStatementNode.ModuleId()));
1382     }
1383     else
1384     {
1385         AddStatement(new BoundEmptyStatement(destroyStatementNode.GetSpan()destroyStatementNode.ModuleId()));
1386     }
1387 }
1388 
1389 void StatementBinder::Visit(AssignmentStatementNode& assignmentStatementNode)
1390 {
1391     bool exceptionCapture = false;
1392     std::unique_ptr<BoundExpression> target = BindExpression(assignmentStatementNode.TargetExpr()boundCompileUnitcurrentFunctioncontainerScopethistrue);
1393     if (insideCatch && target->ContainsExceptionCapture())
1394     {
1395         exceptionCapture = true;
1396     }
1397     TypeSymbol* targetPlainType = target->GetType()->PlainType(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1398     if ((targetPlainType->IsClassTypeSymbol() || targetPlainType->IsArrayType()) && target->GetType()->IsReferenceType())
1399     {
1400         TypeSymbol* type = target->GetType()->RemoveReference(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId())->AddPointer(
1401             assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1402         target.reset(new BoundReferenceToPointerExpression(std::unique_ptr<BoundExpression>(target.release())type));
1403     }
1404     else if (targetPlainType->IsPointerType() && target->GetType()->IsReferenceType())
1405     {
1406         TypeSymbol* derefType = target->GetType()->RemoveReference(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1407         TypeSymbol* addrOfType = derefType->AddPointer(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1408         target.reset(new BoundAddressOfExpression(std::unique_ptr<BoundExpression>(
1409             new BoundDereferenceExpression(std::unique_ptr<BoundExpression>(target.release())derefType))addrOfType));
1410     }
1411     else
1412     {
1413         target.reset(new BoundAddressOfExpression(std::move(target)target->GetType()->AddPointer(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId())));
1414     }
1415     TypeSymbol* targetType = target->GetType()->BaseType();
1416     bool assignDelegateOrClassDelegateType = targetType->GetSymbolType() == SymbolType::delegateTypeSymbol || targetType->GetSymbolType() == SymbolType::classDelegateTypeSymbol;
1417     std::unique_ptr<BoundExpression> source = BindExpression(assignmentStatementNode.SourceExpr()boundCompileUnitcurrentFunctioncontainerScopethisfalseassignDelegateOrClassDelegateType);
1418     if (insideCatch && source->ContainsExceptionCapture())
1419     {
1420         exceptionCapture = true;
1421     }
1422     std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1423     arguments.push_back(std::move(target));
1424     arguments.push_back(std::move(source));
1425     std::vector<FunctionScopeLookup> functionScopeLookups;
1426     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_targetType->ClassInterfaceEnumDelegateOrNsScope()));
1427     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentcontainerScope));
1428     functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopesnullptr));
1429     std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator="containerScopefunctionScopeLookupsargumentsboundCompileUnitcurrentFunction
1430         assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1431     CheckAccess(currentFunction->GetFunctionSymbol()assignmentCall->GetFunctionSymbol());
1432     currentFunction->MoveTemporaryDestructorCallsTo(*assignmentCall);
1433     if (exceptionCapture)
1434     {
1435         AddReleaseExceptionStatement(assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId());
1436     }
1437     AddStatement(new BoundAssignmentStatement(std::move(assignmentCall)assignmentStatementNode.GetSpan()assignmentStatementNode.ModuleId()));
1438 }
1439 
1440 void StatementBinder::Visit(ExpressionStatementNode& expressionStatementNode)
1441 {
1442     bool exceptionCapture = false;
1443     std::unique_ptr<BoundExpression> expression = BindExpression(expressionStatementNode.Expression()boundCompileUnitcurrentFunctioncontainerScopethis);
1444     if (insideCatch && expression->ContainsExceptionCapture())
1445     {
1446         exceptionCapture = true;
1447     }
1448     if (exceptionCapture)
1449     {
1450         AddReleaseExceptionStatement(expressionStatementNode.GetSpan()expressionStatementNode.ModuleId());
1451     }
1452     AddStatement(new BoundExpressionStatement(std::move(expression)expressionStatementNode.GetSpan()expressionStatementNode.ModuleId()));
1453 }
1454 
1455 void StatementBinder::Visit(EmptyStatementNode& emptyStatementNode)
1456 {
1457     AddStatement(new BoundEmptyStatement(emptyStatementNode.GetSpan()emptyStatementNode.ModuleId()));
1458 }
1459 
1460 void StatementBinder::Visit(RangeForStatementNode& rangeForStatementNode)
1461 {
1462     Span span;
1463     boost::uuids::uuid moduleId = boost::uuids::nil_uuid();
1464     if (GetBackEnd() == BackEnd::llvm)
1465     {
1466         span = rangeForStatementNode.GetSpan();
1467         moduleId = rangeForStatementNode.ModuleId();
1468     }
1469     Span actionBeginBraceSpan;
1470     Span actionEndBraceSpan;
1471     if (rangeForStatementNode.Action()->GetNodeType() == NodeType::compoundStatementNode)
1472     {
1473         CompoundStatementNode* action = static_cast<CompoundStatementNode*>(rangeForStatementNode.Action());
1474         actionBeginBraceSpan = action->BeginBraceSpan();
1475         actionEndBraceSpan = action->EndBraceSpan();
1476     }
1477     else
1478     {
1479         actionBeginBraceSpan = rangeForStatementNode.Action()->GetSpan();
1480         actionEndBraceSpan = rangeForStatementNode.Action()->GetSpan();
1481     }
1482     Span initSpan = rangeForStatementNode.TypeExpr()->GetSpan();
1483     initSpan.end = rangeForStatementNode.Id()->GetSpan().end;
1484     Span containerSpan = rangeForStatementNode.Container()->GetSpan();
1485     Span colonSpan = rangeForStatementNode.ColonSpan();
1486     std::unique_ptr<BoundExpression> container = BindExpression(rangeForStatementNode.Container()boundCompileUnitcurrentFunctioncontainerScopethis);
1487     TypeSymbol* plainContainerType = container->GetType()->PlainType(spanmoduleId);
1488     std::u32string plainContainerTypeFullName = plainContainerType->FullName();
1489     ParsingContext parsingContext;
1490     CmajorLexer cmajorLexer(plainContainerTypeFullName + U"\n"""0);
1491     cmajorLexer.SetSeparatorChar('\n');
1492     std::unique_ptr<Node> containerTypeNode(TypeExprParser::Parse(cmajorLexer&moduleId&parsingContext));
1493     std::unique_ptr<IdentifierNode> iteratorTypeNode = nullptr;
1494     if (container->GetType()->IsConstType())
1495     {
1496         iteratorTypeNode.reset(new IdentifierNode(spanmoduleIdU"ConstIterator"));
1497     }
1498     else
1499     {
1500         iteratorTypeNode.reset(new IdentifierNode(spanmoduleIdU"Iterator"));
1501     }
1502     CloneContext cloneContext;
1503     std::unique_ptr<CompoundStatementNode> compoundStatementNode(new CompoundStatementNode(spanmoduleId));
1504     if (rangeForStatementNode.Action()->GetNodeType() == NodeType::compoundStatementNode)
1505     {
1506         CompoundStatementNode* action = static_cast<CompoundStatementNode*>(rangeForStatementNode.Action());
1507         compoundStatementNode->SetBeginBraceSpan(span);
1508         compoundStatementNode->SetEndBraceSpan(span);
1509     }
1510     else
1511     {
1512         compoundStatementNode->SetBeginBraceSpan(span);
1513         compoundStatementNode->SetEndBraceSpan(span);
1514     }
1515     compoundStatementNode->SetParent(rangeForStatementNode.Parent());
1516     ConstructionStatementNode* constructEndIteratorStatement = new ConstructionStatementNode(spanmoduleId
1517         new DotNode(spanmoduleIdcontainerTypeNode->Clone(cloneContext)static_cast<IdentifierNode*>(iteratorTypeNode->Clone(cloneContext)))new IdentifierNode(spanmoduleIdU"@end"));
1518     if (container->GetType()->IsConstType())
1519     {
1520         constructEndIteratorStatement->AddArgument(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdrangeForStatementNode.Container()->Clone(cloneContext)
1521             new IdentifierNode(spanmoduleIdU"CEnd"))));
1522     }
1523     else
1524     {
1525         constructEndIteratorStatement->AddArgument(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdrangeForStatementNode.Container()->Clone(cloneContext)
1526             new IdentifierNode(spanmoduleIdU"End"))));
1527     }
1528     compoundStatementNode->AddStatement(constructEndIteratorStatement);
1529     ConstructionStatementNode* constructIteratorStatement = new ConstructionStatementNode(initSpanmoduleId
1530         new DotNode(spanmoduleIdcontainerTypeNode->Clone(cloneContext)static_cast<IdentifierNode*>(iteratorTypeNode->Clone(cloneContext)))new IdentifierNode(spanmoduleIdU"@it"));
1531     if (container->GetType()->IsConstType())
1532     {
1533         constructIteratorStatement->AddArgument(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdrangeForStatementNode.Container()->Clone(cloneContext)
1534             new IdentifierNode(spanmoduleIdU"CBegin"))));
1535     }
1536     else
1537     {
1538         constructIteratorStatement->AddArgument(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdrangeForStatementNode.Container()->Clone(cloneContext)
1539             new IdentifierNode(spanmoduleIdU"Begin"))));
1540     }
1541     Node* itNotEndCond = new NotEqualNode(colonSpanmoduleIdnew IdentifierNode(colonSpanmoduleIdU"@it")new IdentifierNode(colonSpanmoduleIdU"@end"));
1542     StatementNode* incrementItStatement = new ExpressionStatementNode(containerSpanmoduleIdnew PrefixIncrementNode(containerSpanmoduleIdnew IdentifierNode(containerSpanmoduleIdU"@it")));
1543     CompoundStatementNode* actionStatement = new CompoundStatementNode(actionBeginBraceSpanmoduleId);
1544     actionStatement->SetBeginBraceSpan(actionBeginBraceSpan);
1545     actionStatement->SetEndBraceSpan(actionEndBraceSpan);
1546     ConstructionStatementNode* constructLoopVarStatement = new ConstructionStatementNode(spanmoduleId
1547         rangeForStatementNode.TypeExpr()->Clone(cloneContext)static_cast<IdentifierNode*>(rangeForStatementNode.Id()->Clone(cloneContext)));
1548     constructLoopVarStatement->AddArgument(new DerefNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@it")));
1549     actionStatement->AddStatement(constructLoopVarStatement);
1550     actionStatement->AddStatement(static_cast<StatementNode*>(rangeForStatementNode.Action()->Clone(cloneContext)));
1551     ForStatementNode* forStatement = new ForStatementNode(spanmoduleIdconstructIteratorStatementitNotEndCondincrementItStatementactionStatement);
1552     compoundStatementNode->AddStatement(forStatement);
1553 
1554     symbolTable.BeginContainer(containerScope->Container());
1555     SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
1556     compoundStatementNode->Accept(symbolCreatorVisitor);
1557     symbolTable.EndContainer();
1558     TypeBinder typeBinder(boundCompileUnit);
1559     typeBinder.SetContainerScope(containerScope);
1560     typeBinder.SetCurrentFunctionSymbol(currentFunction->GetFunctionSymbol());
1561     compoundStatementNode->Accept(typeBinder);
1562     compoundStatementNode->Accept(*this);
1563 }
1564 
1565 void StatementBinder::Visit(SwitchStatementNode& switchStatementNode)
1566 {
1567     bool exceptionCapture = false;
1568     std::unique_ptr<BoundExpression> condition = BindExpression(switchStatementNode.Condition()boundCompileUnitcurrentFunctioncontainerScopethis);
1569     if (insideCatch && condition->ContainsExceptionCapture())
1570     {
1571         exceptionCapture = true;
1572     }
1573     TypeSymbol* conditionType = condition->GetType();
1574     if (conditionType->IsSwitchConditionType())
1575     {
1576         if (conditionType->GetSymbolType() == SymbolType::enumTypeSymbol)
1577         {
1578             EnumTypeSymbol* enumType = static_cast<EnumTypeSymbol*>(conditionType);
1579             conditionType = enumType->UnderlyingType();
1580         }
1581         TypeSymbol* prevSwitchConditionType = switchConditionType;
1582         switchConditionType = conditionType;
1583         std::std::unordered_map<IntegralValueCaseStatementNode*IntegralValueHash>*prevCaseValueMap=currentCaseValueMap;
1584         std::unordered_map<IntegralValueCaseStatementNode*IntegralValueHash> caseValueMap;
1585         currentCaseValueMap = &caseValueMap;
1586         std::std::vector<std::std::pair<BoundGotoCaseStatement*IntegralValue>>*prevGotoCaseStatements=currentGotoCaseStatements;
1587         std::vector<std::std::pair<BoundGotoCaseStatement*IntegralValue>>gotoCaseStatements;
1588         currentGotoCaseStatements = &gotoCaseStatements;
1589         std::std::vector<BoundGotoDefaultStatement*>*prevGotoDefaultStatements=currentGotoDefaultStatements;
1590         std::vector<BoundGotoDefaultStatement*> gotoDefaultStatements;
1591         currentGotoDefaultStatements = &gotoDefaultStatements;
1592         std::unique_ptr<BoundSwitchStatement> boundSwitchStatement(new BoundSwitchStatement(switchStatementNode.GetSpan()switchStatementNode.ModuleId()std::move(condition)));
1593         int n = switchStatementNode.Cases().Count();
1594         for (int i = 0; i < n; ++i)
1595         {
1596             CaseStatementNode* caseS = switchStatementNode.Cases()[i];
1597             caseS->Accept(*this);
1598             Assert(statement->GetBoundNodeType() == BoundNodeType::boundCaseStatement"case statement expected");
1599             boundSwitchStatement->AddCaseStatement(std::unique_ptr<BoundCaseStatement>(static_cast<BoundCaseStatement*>(statement.release())));
1600         }
1601         if (switchStatementNode.Default())
1602         {
1603             switchStatementNode.Default()->Accept(*this);
1604             Assert(statement->GetBoundNodeType() == BoundNodeType::boundDefaultStatement"default statement expected");
1605             boundSwitchStatement->SetDefaultStatement(std::unique_ptr<BoundDefaultStatement>(static_cast<BoundDefaultStatement*>(statement.release())));
1606         }
1607         for (const std::std::pair<BoundGotoCaseStatement*IntegralValue>&p : gotoCaseStatements)
1608         {
1609             BoundGotoCaseStatement* gotoCaseStatement = p.first;
1610             IntegralValue integralCaseValue = p.second;
1611             auto it = caseValueMap.find(integralCaseValue);
1612             if (it == caseValueMap.cend())
1613             {
1614                 throw Exception("case not found"gotoCaseStatement->GetSpan()gotoCaseStatement->ModuleId());
1615             }
1616         }
1617         if (!gotoDefaultStatements.empty() && !switchStatementNode.Default())
1618         {
1619             throw Exception("switch does not have a default statement"gotoDefaultStatements.front()->GetSpan()gotoDefaultStatements.front()->ModuleId());
1620         }
1621         currentGotoCaseStatements = prevGotoCaseStatements;
1622         currentGotoDefaultStatements = prevGotoDefaultStatements;
1623         currentCaseValueMap = prevCaseValueMap;
1624         if (exceptionCapture)
1625         {
1626             AddReleaseExceptionStatement(switchStatementNode.GetSpan()switchStatementNode.ModuleId());
1627         }
1628         AddStatement(boundSwitchStatement.release());
1629         switchConditionType = prevSwitchConditionType;
1630     }
1631     else
1632     {
1633         throw Exception("switch statement condition must be of integer, character, enumerated or Boolean type"switchStatementNode.Condition()->GetSpan()switchStatementNode.Condition()->ModuleId());
1634     }
1635 }
1636 
1637 void StatementBinder::Visit(CaseStatementNode& caseStatementNode)
1638 {
1639     std::unique_ptr<BoundCaseStatement> boundCaseStatement(new BoundCaseStatement(caseStatementNode.GetSpan()caseStatementNode.ModuleId()));
1640     bool terminated = false;
1641     int n = caseStatementNode.Statements().Count();
1642     for (int i = 0; i < n; ++i)
1643     {
1644         StatementNode* statementNode = caseStatementNode.Statements()[i];
1645         if (TerminatesCase(statementNode))
1646         {
1647             terminated = true;
1648         }
1649         statementNode->Accept(*this);
1650         boundCaseStatement->AddStatement(std::move(statement));
1651     }
1652     if (!terminated)
1653     {
1654         throw Exception("case must end in break, continue, return, throw, goto, goto case or goto default statement"caseStatementNode.GetSpan()caseStatementNode.ModuleId());
1655     }
1656     int ne = caseStatementNode.CaseExprs().Count();
1657     for (int i = 0; i < ne; ++i)
1658     {
1659         Node* caseExprNode = caseStatementNode.CaseExprs()[i];
1660         std::unique_ptr<Value> caseValue = Evaluate(caseExprNodeswitchConditionTypecontainerScopeboundCompileUnitfalsecurrentFunctioncaseExprNode->GetSpan()caseExprNode->ModuleId());
1661         IntegralValue integralCaseValue(caseValue.get());
1662         Assert(currentCaseValueMap"current case value map not set");
1663         auto it = currentCaseValueMap->find(integralCaseValue);
1664         if (it != currentCaseValueMap->cend())
1665         {
1666             throw Exception("case value already used"caseExprNode->GetSpan()caseExprNode->ModuleId());
1667         }
1668         (*currentCaseValueMap)[integralCaseValue] = &caseStatementNode;
1669         boundCaseStatement->AddCaseValue(std::move(caseValue));
1670     }
1671     AddStatement(boundCaseStatement.release());
1672 }
1673 
1674 void StatementBinder::Visit(DefaultStatementNode& defaultStatementNode)
1675 {
1676     std::unique_ptr<BoundDefaultStatement> boundDefaultStatement(new BoundDefaultStatement(defaultStatementNode.GetSpan()defaultStatementNode.ModuleId()));
1677     bool terminated = false;
1678     int n = defaultStatementNode.Statements().Count();
1679     for (int i = 0; i < n; ++i)
1680     {
1681         StatementNode* statementNode = defaultStatementNode.Statements()[i];
1682         if (TerminatesDefault(statementNode))
1683         {
1684             terminated = true;
1685         }
1686         statementNode->Accept(*this);
1687         boundDefaultStatement->AddStatement(std::move(statement));
1688     }
1689     if (!terminated)
1690     {
1691         throw Exception("default must end in break, continue, return, throw, goto, or goto case statement"defaultStatementNode.GetSpan()defaultStatementNode.ModuleId());
1692     }
1693     AddStatement(boundDefaultStatement.release());
1694 }
1695 
1696 void StatementBinder::Visit(GotoCaseStatementNode& gotoCaseStatementNode)
1697 {
1698     const Node* parent = gotoCaseStatementNode.Parent();
1699     while (parent && parent->GetNodeType() != NodeType::caseStatementNode && parent->GetNodeType() != NodeType::defaultStatementNode)
1700     {
1701         parent = parent->Parent();
1702     }
1703     if (!parent)
1704     {
1705         throw Exception("goto case statement must be enclosed in a case or default statement"gotoCaseStatementNode.GetSpan()gotoCaseStatementNode.ModuleId());
1706     }
1707     Node* caseExprNode = gotoCaseStatementNode.CaseExpr();
1708     std::unique_ptr<Value> caseValue = Evaluate(caseExprNodeswitchConditionTypecontainerScopeboundCompileUnitfalsecurrentFunctiongotoCaseStatementNode.GetSpan()gotoCaseStatementNode.ModuleId());
1709     Value* caseValuePtr = caseValue.get();
1710     BoundGotoCaseStatement* boundGotoCaseStatement = new BoundGotoCaseStatement(gotoCaseStatementNode.GetSpan()gotoCaseStatementNode.ModuleId()std::move(caseValue));
1711     Assert(currentGotoCaseStatements"current goto case statement vector not set");
1712     currentGotoCaseStatements->push_back(std::make_pair(boundGotoCaseStatementIntegralValue(caseValuePtr)));
1713     AddStatement(boundGotoCaseStatement);
1714 }
1715 
1716 void StatementBinder::Visit(GotoDefaultStatementNode& gotoDefaultStatementNode)
1717 {
1718     const Node* parent = gotoDefaultStatementNode.Parent();
1719     while (parent && parent->GetNodeType() != NodeType::caseStatementNode)
1720     {
1721         parent = parent->Parent();
1722     }
1723     if (!parent)
1724     {
1725         throw Exception("goto default statement must be enclosed in a case statement"gotoDefaultStatementNode.GetSpan()gotoDefaultStatementNode.ModuleId());
1726     }
1727     BoundGotoDefaultStatement* boundGotoDefaultStatement = new BoundGotoDefaultStatement(gotoDefaultStatementNode.GetSpan()gotoDefaultStatementNode.ModuleId());
1728     Assert(currentGotoDefaultStatements"current goto default statement vector not set");
1729     currentGotoDefaultStatements->push_back(boundGotoDefaultStatement);
1730     AddStatement(boundGotoDefaultStatement);
1731 }
1732 
1733 void StatementBinder::Visit(ThrowStatementNode& throwStatementNode)
1734 {
1735     bool prevCompilingThrow = compilingThrow;
1736     compilingThrow = true;
1737     if (currentFunction->GetFunctionSymbol()->DontThrow() && !currentFunction->GetFunctionSymbol()->HasTry())
1738     {
1739         throw Exception("a nothrow function cannot contain a throw statement unless it handles exceptions"
1740             throwStatementNode.GetSpan()throwStatementNode.ModuleId()currentFunction->GetFunctionSymbol()->GetSpan()currentFunction->GetFunctionSymbol()->SourceModuleId());
1741     }
1742     Span span = throwStatementNode.GetSpan();
1743     boost::uuids::uuid moduleId = throwStatementNode.ModuleId();
1744     Node* exceptionExprNode = throwStatementNode.Expression();
1745     if (exceptionExprNode)
1746     {
1747         std::unique_ptr<BoundExpression> boundExceptionExpr = BindExpression(exceptionExprNodeboundCompileUnitcurrentFunctioncontainerScopethis);
1748         if (boundExceptionExpr->GetType()->PlainType(spanmoduleId)->IsClassTypeSymbol())
1749         {
1750             ClassTypeSymbol* exceptionClassType = static_cast<ClassTypeSymbol*>(boundExceptionExpr->GetType()->PlainType(spanmoduleId));
1751             IdentifierNode systemExceptionNode(spanmoduleIdU"System.Exception");
1752             TypeSymbol* systemExceptionType = ResolveType(&systemExceptionNodeboundCompileUnitcontainerScope);
1753             Assert(systemExceptionType->IsClassTypeSymbol()"System.Exception not of class type");
1754             ClassTypeSymbol* systemExceptionClassType = static_cast<ClassTypeSymbol*>(systemExceptionType);
1755             if (exceptionClassType == systemExceptionClassType || exceptionClassType->HasBaseClass(systemExceptionClassType))
1756             {
1757                 NewNode* newNode = new NewNode(spanmoduleIdnew IdentifierNode(spanmoduleIdexceptionClassType->FullName()));
1758                 CloneContext cloneContext;
1759                 newNode->AddArgument(throwStatementNode.Expression()->Clone(cloneContext));
1760                 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1761                 {
1762                     InvokeNode invokeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"RtThrowException"));
1763                     invokeNode.AddArgument(newNode);
1764                     invokeNode.AddArgument(new UuidLiteralNode(spanmoduleIdexceptionClassType->TypeId()));
1765                     std::unique_ptr<BoundExpression> throwCallExpr = BindExpression(&invokeNodeboundCompileUnitcurrentFunctioncontainerScopethis);
1766                     AddStatement(new BoundThrowStatement(spanmoduleIdstd::move(throwCallExpr)));
1767                 }
1768                 else if (GetBackEnd() == BackEnd::cmsx)
1769                 {
1770                     InvokeNode invokeNode(spanmoduleIdnew DotNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"System")new IdentifierNode(spanmoduleIdU"Throw")));
1771                     invokeNode.AddArgument(newNode);
1772                     std::unique_ptr<BoundExpression> throwCallExpr = BindExpression(&invokeNodeboundCompileUnitcurrentFunctioncontainerScopethis);
1773                     AddStatement(new BoundThrowStatement(spanmoduleIdstd::move(throwCallExpr)));
1774                 }
1775             }
1776             else
1777             {
1778                 throw Exception("exception class must be derived from System.Exception class"throwStatementNode.GetSpan()throwStatementNode.ModuleId());
1779             }
1780         }
1781         else
1782         {
1783             throw Exception("exception not of class type"throwStatementNode.GetSpan()throwStatementNode.ModuleId());
1784         }
1785     }
1786     else
1787     {
1788         if (insideCatch)
1789         {
1790             InvokeNode invokeNode(spanmoduleIdnew DotNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@exPtr")new IdentifierNode(spanmoduleIdU"Release")));
1791             std::unique_ptr<BoundExpression> releaseCall = BindExpression(&invokeNodeboundCompileUnitcurrentFunctioncontainerScopethis);
1792             AddStatement(new BoundRethrowStatement(spanmoduleIdstd::move(releaseCall)));
1793         }
1794         else
1795         {
1796             throw Exception("rethrow must occur inside a catch clause"throwStatementNode.GetSpan()throwStatementNode.ModuleId());
1797         }
1798     }
1799     compilingThrow = prevCompilingThrow;
1800 }
1801 
1802 void StatementBinder::Visit(TryStatementNode& tryStatementNode)
1803 {
1804     BoundTryStatement* boundTryStatement = new BoundTryStatement(tryStatementNode.GetSpan()tryStatementNode.ModuleId());
1805     tryStatementNode.TryBlock()->Accept(*this);
1806     boundTryStatement->SetTryBlock(std::move(statement));
1807     int n = tryStatementNode.Catches().Count();
1808     for (int i = 0; i < n; ++i)
1809     {
1810         CatchNode* catchNode = tryStatementNode.Catches()[i];
1811         catchNode->Accept(*this);
1812         BoundStatement* s = statement.release();
1813         Assert(s->GetBoundNodeType() == BoundNodeType::boundCatchStatement"catch statement expected");
1814         BoundCatchStatement* catchStatement = static_cast<BoundCatchStatement*>(s);
1815         boundTryStatement->AddCatch(std::unique_ptr<BoundCatchStatement>(catchStatement));
1816     }
1817     AddStatement(boundTryStatement);
1818 }
1819 
1820 void StatementBinder::Visit(CatchNode& catchNode)
1821 {
1822     bool prevInsideCatch = insideCatch;
1823     insideCatch = true;
1824     Span span;
1825     boost::uuids::uuid moduleId = boost::uuids::nil_uuid();
1826     if (GetBackEnd() == BackEnd::llvm)
1827     {
1828         span = catchNode.GetSpan();
1829         moduleId = catchNode.ModuleId();
1830     }
1831     std::unique_ptr<BoundCatchStatement> boundCatchStatement(new BoundCatchStatement(spanmoduleId));
1832     TypeSymbol* catchedType = ResolveType(catchNode.TypeExpr()boundCompileUnitcontainerScope);
1833     boundCatchStatement->SetCatchedType(catchedType);
1834     boundCatchStatement->SetCatchedTypeUuidId(boundCompileUnit.Install(catchedType->BaseType()->TypeId()));
1835     LocalVariableSymbol* catchVar = nullptr;
1836     if (catchNode.Id())
1837     {
1838         Symbol* symbol = symbolTable.GetSymbol(catchNode.Id());
1839         Assert(symbol->GetSymbolType() == SymbolType::localVariableSymbol"local variable symbol expected");
1840         catchVar = static_cast<LocalVariableSymbol*>(symbol);
1841         boundCatchStatement->SetCatchVar(catchVar);
1842         currentFunction->GetFunctionSymbol()->AddLocalVariable(catchVar);
1843     }
1844     CompoundStatementNode handlerBlock(catchNode.CatchBlock()->BeginBraceSpan()moduleId);
1845     handlerBlock.SetBeginBraceSpan(catchNode.CatchBlock()->BeginBraceSpan());
1846     handlerBlock.SetEndBraceSpan(catchNode.CatchBlock()->EndBraceSpan());
1847     handlerBlock.SetParent(catchNode.Parent());
1848     if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1849     {
1850         ConstructionStatementNode* getExceptionAddr = new ConstructionStatementNode(spanmoduleIdnew PointerNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"void"))
1851             new IdentifierNode(spanmoduleIdU"@exceptionAddr"));
1852         getExceptionAddr->AddArgument(new InvokeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"RtGetException")));
1853         handlerBlock.AddStatement(getExceptionAddr);
1854     }
1855     else if (GetBackEnd() == BackEnd::cmsx)
1856     {
1857         ConstructionStatementNode* getExceptionAddr = new ConstructionStatementNode(spanmoduleIdnew PointerNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"void"))
1858             new IdentifierNode(spanmoduleIdU"@exceptionAddr"));
1859         getExceptionAddr->AddArgument(new InvokeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"do_catch")));
1860         handlerBlock.AddStatement(getExceptionAddr);
1861     }
1862     PointerNode exceptionPtrTypeNode(spanmoduleIdnew IdentifierNode(spanmoduleIdcatchedType->BaseType()->FullName()));
1863     CloneContext cloneContext;
1864     ConstructionStatementNode* constructExceptionPtr = new ConstructionStatementNode(spanmoduleIdexceptionPtrTypeNode.Clone(cloneContext)
1865         new IdentifierNode(spanmoduleIdU"@exceptionPtr"));
1866     constructExceptionPtr->AddArgument(new CastNode(spanmoduleIdexceptionPtrTypeNode.Clone(cloneContext)new IdentifierNode(spanmoduleIdU"@exceptionAddr")));
1867     handlerBlock.AddStatement(constructExceptionPtr);
1868     TemplateIdNode* uniquePtrNode = new TemplateIdNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"UniquePtr"));
1869     uniquePtrNode->AddTemplateArgument(new IdentifierNode(spanmoduleIdcatchedType->BaseType()->FullName()));
1870     ConstructionStatementNode* constructUniquePtrException = new ConstructionStatementNode(spanmoduleIduniquePtrNodenew IdentifierNode(spanmoduleIdU"@exPtr"));
1871     constructUniquePtrException->AddArgument(new IdentifierNode(spanmoduleIdU"@exceptionPtr"));
1872     handlerBlock.AddStatement(constructUniquePtrException);
1873     if (catchVar)
1874     {
1875         ConstructionStatementNode* setExceptionVar = new ConstructionStatementNode(spanmoduleIdcatchNode.TypeExpr()->Clone(cloneContext)static_cast<IdentifierNode*>(catchNode.Id()->Clone(cloneContext)));
1876         setExceptionVar->AddArgument(new DerefNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@exPtr")));
1877         handlerBlock.AddStatement(setExceptionVar);
1878     }
1879     handlerBlock.AddStatement(static_cast<StatementNode*>(catchNode.CatchBlock()->Clone(cloneContext)));
1880     symbolTable.BeginContainer(containerScope->Container());
1881     SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
1882     handlerBlock.Accept(symbolCreatorVisitor);
1883     symbolTable.EndContainer();
1884     TypeBinder typeBinder(boundCompileUnit);
1885     typeBinder.SetContainerScope(containerScope);
1886     typeBinder.SetCurrentFunctionSymbol(currentFunction->GetFunctionSymbol());
1887     handlerBlock.Accept(typeBinder);
1888     handlerBlock.Accept(*this);
1889     boundCatchStatement->SetCatchBlock(std::move(statement));
1890     AddStatement(boundCatchStatement.release());
1891     insideCatch = prevInsideCatch;
1892 }
1893 
1894 void StatementBinder::Visit(AssertStatementNode& assertStatementNode)
1895 {
1896     if (!module)
1897     {
1898         throw std::runtime_error("module not set");
1899     }
1900     bool unitTesting = GetGlobalFlag(GlobalFlags::unitTest) && InUnitTest();
1901     bool unitTestAssertion = false;
1902     if (unitTesting)
1903     {
1904         FunctionSymbol* functionSymbol = currentFunction->GetFunctionSymbol();
1905         Node* node = symbolTable.GetNodeNoThrow(functionSymbol);
1906         if (node)
1907         {
1908             if (node->GetNodeType() == NodeType::functionNode)
1909             {
1910                 FunctionNode* functionNode = static_cast<FunctionNode*>(node);
1911                 if ((functionNode->GetSpecifiers() & Specifiers::unit_test_) != Specifiers::none)
1912                 {
1913                     unitTestAssertion = true;
1914                 }
1915             }
1916         }
1917     }
1918     if (unitTestAssertion)
1919     {
1920         int32_t assertionLineNumber = assertStatementNode.GetSpan().line;
1921         int32_t assertionIndex = GetNextUnitTestAssertionNumber();
1922         AddAssertionLineNumber(assertionLineNumber);
1923         InvokeNode* invokeSetUnitTestAssertionResult = new InvokeNode(assertStatementNode.GetSpan()assertStatementNode.ModuleId()
1924             new IdentifierNode(assertStatementNode.GetSpan()assertStatementNode.ModuleId()U"RtSetUnitTestAssertionResult"));
1925         invokeSetUnitTestAssertionResult->AddArgument(new IntLiteralNode(assertStatementNode.GetSpan()assertStatementNode.ModuleId()assertionIndex));
1926         CloneContext cloneContext;
1927         invokeSetUnitTestAssertionResult->AddArgument(assertStatementNode.AssertExpr()->Clone(cloneContext));
1928         invokeSetUnitTestAssertionResult->AddArgument(new IntLiteralNode(assertStatementNode.GetSpan()assertStatementNode.ModuleId()assertionLineNumber));
1929         ExpressionStatementNode setUnitTestAssertionResult(assertStatementNode.GetSpan()assertStatementNode.ModuleId()invokeSetUnitTestAssertionResult);
1930         symbolTable.BeginContainer(containerScope->Container());
1931         SymbolCreatorVisitor symbolCreatorVisitor(symbolTable);
1932         setUnitTestAssertionResult.Accept(symbolCreatorVisitor);
1933         symbolTable.EndContainer();
1934         TypeBinder typeBinder(boundCompileUnit);
1935         typeBinder.SetContainerScope(containerScope);
1936         typeBinder.SetCurrentFunctionSymbol(currentFunction->GetFunctionSymbol());
1937         setUnitTestAssertionResult.Accept(typeBinder);
1938         setUnitTestAssertionResult.Accept(*this);
1939     }
1940     else
1941     {
1942         if (GetGlobalFlag(GlobalFlags::release))
1943         {
1944             AddStatement(new BoundEmptyStatement(assertStatementNode.GetSpan()assertStatementNode.ModuleId()));
1945         }
1946         else
1947         {
1948             std::vector<FunctionScopeLookup> lookups;
1949             lookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parentsymbolTable.GlobalNs().GetContainerScope()));
1950             std::vector<std::std::unique_ptr<BoundExpression>>arguments;
1951             TypeSymbol* constCharPtrType = symbolTable.GetTypeByName(U"char")->AddConst(Span()boost::uuids::nil_uuid())->AddPointer(Span()boost::uuids::nil_uuid());
1952             arguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new StringValue(Span()boost::uuids::nil_uuid()
1953                 boundCompileUnit.Install(assertStatementNode.AssertExpr()->ToString())assertStatementNode.AssertExpr()->ToString()))constCharPtrType)));
1954             arguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new StringValue(Span()boost::uuids::nil_uuid()
1955                 boundCompileUnit.Install(ToUtf8(currentFunction->GetFunctionSymbol()->FullName()))ToUtf8(currentFunction->GetFunctionSymbol()->FullName())))constCharPtrType)));
1956             arguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new StringValue(Span()boost::uuids::nil_uuid()
1957                 boundCompileUnit.Install(GetSourceFilePath(assertStatementNode.GetSpan().fileIndexassertStatementNode.ModuleId()))
1958                 GetSourceFilePath(assertStatementNode.GetSpan().fileIndexassertStatementNode.ModuleId())))constCharPtrType)));
1959             arguments.push_back(std::unique_ptr<BoundExpression>(new BoundLiteral(std::unique_ptr<Value>(new IntValue(Span()boost::uuids::nil_uuid()
1960                 assertStatementNode.GetSpan().line))symbolTable.GetTypeByName(U"int"))));
1961             std::unique_ptr<BoundExpression> assertExpression = BindExpression(assertStatementNode.AssertExpr()boundCompileUnitcurrentFunctioncontainerScopethis);
1962             const char32_t* failAssertionFunctionName = U"";
1963             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1964             {
1965                 failAssertionFunctionName = U"RtFailAssertion";
1966             }
1967             else if (GetBackEnd() == BackEnd::cmsx)
1968             {
1969                 failAssertionFunctionName = U"System.FailAssertion";
1970             }
1971             std::unique_ptr<BoundStatement> emptyStatement(new BoundEmptyStatement(Span()boost::uuids::nil_uuid()));
1972             emptyStatement->SetIgnoreNode();
1973             std::unique_ptr<BoundStatement> failAssertionStatement(
1974                 new BoundExpressionStatement(ResolveOverload(failAssertionFunctionNamecontainerScopelookupsarguments
1975                     boundCompileUnitcurrentFunctionSpan()boost::uuids::nil_uuid())Span()boost::uuids::nil_uuid()));
1976             failAssertionStatement->SetIgnoreNode();
1977             std::unique_ptr<BoundStatement> ifStatement(new BoundIfStatement(assertStatementNode.GetSpan()assertStatementNode.ModuleId()std::move(assertExpression)
1978                 std::unique_ptr<BoundStatement>(emptyStatement.release())
1979                 std::unique_ptr<BoundStatement>(failAssertionStatement.release())));
1980             ifStatement->SetAssertNode();
1981             AddStatement(ifStatement.release());
1982         }
1983     }
1984 }
1985 
1986 void StatementBinder::Visit(ConditionalCompilationPartNode& conditionalCompilationPartNode)
1987 {
1988     conditionalCompilationPartNode.Expr()->Accept(*this);
1989 }
1990 
1991 void StatementBinder::Visit(ConditionalCompilationDisjunctionNode& conditionalCompilationDisjunctionNode)
1992 {
1993     conditionalCompilationDisjunctionNode.Left()->Accept(*this);
1994     bool left = conditionalCompilationStack.top();
1995     conditionalCompilationStack.pop();
1996     conditionalCompilationDisjunctionNode.Right()->Accept(*this);
1997     bool right = conditionalCompilationStack.top();
1998     conditionalCompilationStack.pop();
1999     conditionalCompilationStack.push(left || right);
2000 }
2001 
2002 void StatementBinder::Visit(ConditionalCompilationConjunctionNode& conditionalCompilationConjunctionNode)
2003 {
2004     conditionalCompilationConjunctionNode.Left()->Accept(*this);
2005     bool left = conditionalCompilationStack.top();
2006     conditionalCompilationStack.pop();
2007     conditionalCompilationConjunctionNode.Right()->Accept(*this);
2008     bool right = conditionalCompilationStack.top();
2009     conditionalCompilationStack.pop();
2010     conditionalCompilationStack.push(left && right);
2011 }
2012 
2013 void StatementBinder::Visit(ConditionalCompilationNotNode& conditionalCompilationNotNode)
2014 {
2015     conditionalCompilationNotNode.Expr()->Accept(*this);
2016     bool operand = conditionalCompilationStack.top();
2017     conditionalCompilationStack.pop();
2018     conditionalCompilationStack.push(!operand);
2019 }
2020 
2021 void StatementBinder::Visit(ConditionalCompilationPrimaryNode& conditionalCompilationPrimaryNode)
2022 {
2023     bool defined = module->IsSymbolDefined(conditionalCompilationPrimaryNode.Symbol());
2024     conditionalCompilationStack.push(defined);
2025 }
2026 
2027 void StatementBinder::Visit(ConditionalCompilationStatementNode& conditionalCompilationStatementNode)
2028 {
2029     conditionalCompilationStatementNode.IfPart()->Accept(*this);
2030     bool defined = conditionalCompilationStack.top();
2031     conditionalCompilationStack.pop();
2032     if (defined)
2033     {
2034         int n = conditionalCompilationStatementNode.IfPart()->Statements().Count();
2035         if (n > 0)
2036         {
2037             for (int i = 0; i < n; ++i)
2038             {
2039                 StatementNode* statement = conditionalCompilationStatementNode.IfPart()->Statements()[i];
2040                 statement->Accept(*this);
2041             }
2042         }
2043         else
2044         {
2045             AddStatement(new BoundEmptyStatement(conditionalCompilationStatementNode.GetSpan()conditionalCompilationStatementNode.ModuleId()));
2046         }
2047     }
2048     else
2049     {
2050         bool executed = false;
2051         int n = conditionalCompilationStatementNode.ElifParts().Count();
2052         for (int i = 0; i < n; ++i)
2053         {
2054             ConditionalCompilationPartNode* elifPart = conditionalCompilationStatementNode.ElifParts()[i];
2055             elifPart->Accept(*this);
2056             bool defined = conditionalCompilationStack.top();
2057             conditionalCompilationStack.pop();
2058             if (defined)
2059             {
2060                 int n = elifPart->Statements().Count();
2061                 if (n > 0)
2062                 {
2063                     for (int i = 0; i < n; ++i)
2064                     {
2065                         StatementNode* statement = elifPart->Statements()[i];
2066                         statement->Accept(*this);
2067                     }
2068                 }
2069                 else
2070                 {
2071                     AddStatement(new BoundEmptyStatement(conditionalCompilationStatementNode.GetSpan()conditionalCompilationStatementNode.ModuleId()));
2072                 }
2073                 executed = true;
2074                 break;
2075             }
2076         }
2077         if (!executed)
2078         {
2079             ConditionalCompilationPartNode* elsePart = conditionalCompilationStatementNode.ElsePart();
2080             if (elsePart)
2081             {
2082                 int n = elsePart->Statements().Count();
2083                 if (n > 0)
2084                 {
2085                     for (int i = 0; i < n; ++i)
2086                     {
2087                         StatementNode* statement = elsePart->Statements()[i];
2088                         statement->Accept(*this);
2089                     }
2090                 }
2091                 else
2092                 {
2093                     AddStatement(new BoundEmptyStatement(conditionalCompilationStatementNode.GetSpan()conditionalCompilationStatementNode.ModuleId()));
2094                 }
2095             }
2096             else
2097             {
2098                 AddStatement(new BoundEmptyStatement(conditionalCompilationStatementNode.GetSpan()conditionalCompilationStatementNode.ModuleId()));
2099             }
2100         }
2101     }
2102 }
2103 
2104 void StatementBinder::CompileStatement(Node* statementNodebool setPostfix)
2105 {
2106     bool prevPostfix = postfix;
2107     postfix = setPostfix;
2108     statementNode->Accept(*this);
2109     postfix = prevPostfix;
2110 }
2111 
2112 void StatementBinder::SetCurrentConstructor(ConstructorSymbol* currentConstructorSymbol_ConstructorNode* currentConstructorNode_)
2113 {
2114     currentConstructorSymbol = currentConstructorSymbol_;
2115     currentConstructorNode = currentConstructorNode_;
2116 }
2117 
2118 void StatementBinder::SetCurrentDestructor(DestructorSymbol* currentDestructorSymbol_DestructorNode* currentDestructorNode_)
2119 {
2120     currentDestructorSymbol = currentDestructorSymbol_;
2121     currentDestructorNode = currentDestructorNode_;
2122 }
2123 
2124 void StatementBinder::SetCurrentMemberFunction(MemberFunctionSymbol* currentMemberFunctionSymbol_MemberFunctionNode* currentMemberFunctionNode_)
2125 {
2126     currentMemberFunctionSymbol = currentMemberFunctionSymbol_;
2127     currentMemberFunctionNode = currentMemberFunctionNode_;
2128 }
2129 
2130 void StatementBinder::AddReleaseExceptionStatement(const Span& spanconst boost::uuids::uuid& moduleId)
2131 {
2132     if (insideCatch && !compilingReleaseExceptionStatement)
2133     {
2134         compilingReleaseExceptionStatement = true;
2135         InvokeNode * invokeNode(new InvokeNode(spanmoduleIdnew DotNode(spanmoduleIdnew IdentifierNode(spanmoduleIdU"@exPtr")new IdentifierNode(spanmoduleIdU"Release"))));
2136         ExpressionStatementNode releaseExceptionStatement(spanmoduleIdinvokeNode);
2137         CompileStatement(&releaseExceptionStatementtrue);
2138         compilingReleaseExceptionStatement = false;
2139     }
2140 }
2141 
2142 void StatementBinder::AddStatement(BoundStatement* boundStatement)
2143 {
2144     if (postfix)
2145     {
2146         boundStatement->SetPostfix();
2147     }
2148     if (statement)
2149     {
2150         if (statement->Postfix())
2151         {
2152             BoundSequenceStatement* sequenceStatement = new BoundSequenceStatement(boundStatement->GetSpan()boundStatement->ModuleId()std::unique_ptr<BoundStatement>(boundStatement)std::move(statement));
2153             boundStatement = sequenceStatement;
2154         }
2155         else
2156         {
2157             BoundSequenceStatement* sequenceStatement = new BoundSequenceStatement(boundStatement->GetSpan()boundStatement->ModuleId()std::move(statement)std::unique_ptr<BoundStatement>(boundStatement));
2158             boundStatement = sequenceStatement;
2159         }
2160         if (postfix)
2161         {
2162             boundStatement->SetPostfix();
2163         }
2164     }
2165     statement.reset(boundStatement);
2166 }
2167 
2168 } } // namespace cmajor::binder