1
2
3
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* node, BoundCompileUnit& boundCompileUnit, ContainerScope* containerScope)
39 {
40 std::unique_ptr<Value> value = Evaluate(node, boundCompileUnit.GetSymbolTable().GetTypeByName(U"bool"), containerScope, boundCompileUnit, true, nullptr, node->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* statement, bool inForEverLoop, ContainerScope* containerScope, BoundCompileUnit& 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(statement, inForEverLoop, containerScope, boundCompileUnit)) 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(), inForEverLoop, containerScope, boundCompileUnit) &&
73 inForEverLoop || (ifStatement->ElseS() && TerminatesFunction(ifStatement->ElseS(), inForEverLoop, containerScope, boundCompileUnit)))
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(), boundCompileUnit, containerScope))
84 {
85 if (TerminatesFunction(whileStatement->Statement(), true, containerScope, boundCompileUnit)) return true;
86 }
87 break;
88 }
89 case NodeType::doStatementNode:
90 {
91 DoStatementNode* doStatement = static_cast<DoStatementNode*>(statement);
92 if (IsAlwaysTrue(doStatement->Condition(), boundCompileUnit, containerScope))
93 {
94 if (TerminatesFunction(doStatement->Statement(), true, containerScope, boundCompileUnit)) 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(), boundCompileUnit, containerScope))
102 {
103 if (TerminatesFunction(forStatement->ActionS(), true, containerScope, boundCompileUnit)) 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* functionSymbol, CompoundStatementNode* bodyNode, const Span& span, const boost::uuids::uuid& moduleId,
186 ContainerScope* containerScope, BoundCompileUnit& boundCompileUnit);
187
188 void CheckFunctionReturnPaths(FunctionSymbol* functionSymbol, FunctionNode& functionNode, ContainerScope* containerScope, BoundCompileUnit& boundCompileUnit)
189 {
190 CheckFunctionReturnPaths(functionSymbol, functionNode.Body(), functionNode.GetSpan(), functionNode.ModuleId(), containerScope, boundCompileUnit);
191 }
192
193 void CheckFunctionReturnPaths(FunctionSymbol* functionSymbol, CompoundStatementNode* bodyNode, const Span& span, const boost::uuids::uuid& moduleId,
194 ContainerScope* containerScope, BoundCompileUnit& 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(statement, false, containerScope, boundCompileUnit)) return;
208 }
209 throw Exception("not all control paths terminate in return or throw statement", span, moduleId);
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(), symbol, this);
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(currentClass, destructorSymbol, boundCompileUnit, containerScope, currentFunction, classNode.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(), destructorSymbol, boundCompileUnit, containerScope, currentFunction, memberVariableNode.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(&boundCompileUnit, functionSymbol));
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(functionSymbol, functionNode, containerScope, boundCompileUnit);
374 boundCompileUnit.AddBoundNode(std::move(boundFunction));
375 }
376 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(functionNode.GetAttributes(), symbol, this);
377 currentFunction = prevFunction;
378 containerScope = prevContainerScope;
379 }
380
381 void StatementBinder::Visit(FullInstantiationRequestNode& fullInstantiationRequestNode)
382 {
383 TypeSymbol* type = ResolveType(fullInstantiationRequestNode.TemplateId(), boundCompileUnit, containerScope);
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(&boundCompileUnit, staticConstructorSymbol));
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(staticConstructorSymbol, staticConstructorNode, containerScope, boundCompileUnit);
423 currentClass->AddMember(std::move(boundFunction));
424 }
425 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(staticConstructorNode.GetAttributes(), symbol, this);
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(span, moduleId, U"System.Runtime.UnwindInfo");
441 systemRuntimeUnwindInfoSymbol = ResolveType(&systemRuntimeUnwindInfoNode, boundCompileUnit, containerScope);
442 boundCompileUnit.SetSystemRuntimeUnwindInfoSymbol(systemRuntimeUnwindInfoSymbol);
443 }
444 FunctionSymbol* initUnwindSymbol = boundCompileUnit.GetInitUnwindInfoFunctionSymbol();
445 if (initUnwindSymbol == nullptr)
446 {
447 boundCompileUnit.GenerateInitUnwindInfoFunctionSymbol();
448 }
449 LocalVariableSymbol* prevUnwindInfoVariableSymbol = new LocalVariableSymbol(span, moduleId, U"@prevUnwindInfo");
450 containerScope->Install(prevUnwindInfoVariableSymbol);
451 prevUnwindInfoVariableSymbol->SetType(systemRuntimeUnwindInfoSymbol->AddPointer(span, moduleId));
452 boundFunction->GetFunctionSymbol()->SetPrevUnwindInfoVar(prevUnwindInfoVariableSymbol);
453 sngcm::ast::IdentifierNode* prevUnwindInfoNode1 = new IdentifierNode(span, moduleId, U"@prevUnwindInfo");
454 symbolTable.MapSymbol(prevUnwindInfoNode1, prevUnwindInfoVariableSymbol);
455 symbolTable.MapNode(prevUnwindInfoNode1, prevUnwindInfoVariableSymbol);
456 sngcm::ast::InvokeNode* pushUnwindInfo = new sngcm::ast::InvokeNode(span, moduleId, new sngcm::ast::IdentifierNode(span, moduleId, U"RtPushUnwindInfo"));
457 LocalVariableSymbol* unwindInfoVariableSymbol = new LocalVariableSymbol(span, moduleId, U"@unwindInfo");
458 containerScope->Install(unwindInfoVariableSymbol);
459 unwindInfoVariableSymbol->SetType(systemRuntimeUnwindInfoSymbol);
460 boundFunction->GetFunctionSymbol()->SetUnwindInfoVar(unwindInfoVariableSymbol);
461 sngcm::ast::IdentifierNode* unwindInfoNode1 = new IdentifierNode(span, moduleId, U"@unwindInfo");
462 symbolTable.MapSymbol(unwindInfoNode1, unwindInfoVariableSymbol);
463 symbolTable.MapNode(unwindInfoNode1, unwindInfoVariableSymbol);
464 pushUnwindInfo->AddArgument(new sngcm::ast::CastNode(span, moduleId, new sngcm::ast::PointerNode(span, moduleId, new sngcm::ast::VoidNode(span, moduleId)), new AddrOfNode(span, moduleId, unwindInfoNode1)));
465 sngcm::ast::AssignmentStatementNode assignUnwindInfo(span, moduleId, prevUnwindInfoNode1,
466 new sngcm::ast::CastNode(span, moduleId, new PointerNode(span, moduleId, new IdentifierNode(span, moduleId, U"System.Runtime.UnwindInfo")), pushUnwindInfo));
467 assignUnwindInfo.Accept(*this);
468 std::unique_ptr<BoundStatement> pushUnwindInfoStatement(statement.release());
469
470 sngcm::ast::IdentifierNode* prevUnwindInfoNode2 = new IdentifierNode(span, moduleId, U"@prevUnwindInfo");
471 symbolTable.MapSymbol(prevUnwindInfoNode2, prevUnwindInfoVariableSymbol);
472 symbolTable.MapNode(prevUnwindInfoNode2, prevUnwindInfoVariableSymbol);
473 sngcm::ast::IdentifierNode* unwindInfoNode2 = new IdentifierNode(span, moduleId, U"@unwindInfo");
474 symbolTable.MapSymbol(unwindInfoNode2, unwindInfoVariableSymbol);
475 symbolTable.MapNode(unwindInfoNode2, unwindInfoVariableSymbol);
476 sngcm::ast::AssignmentStatementNode assignUnwindInfoNext(span, moduleId, new sngcm::ast::DotNode(span, moduleId, unwindInfoNode2, new IdentifierNode(span, moduleId, U"next")), prevUnwindInfoNode2);
477 assignUnwindInfoNext.Accept(*this);
478 std::unique_ptr<BoundStatement> assignUnwindInfoNextStatement(statement.release());
479
480 sngcm::ast::IdentifierNode* unwindInfoNode3 = new IdentifierNode(span, moduleId, U"@unwindInfo");
481 symbolTable.MapSymbol(unwindInfoNode3, unwindInfoVariableSymbol);
482 symbolTable.MapNode(unwindInfoNode3, unwindInfoVariableSymbol);
483 sngcm::ast::FunctionPtrNode* functionPtrNode = new sngcm::ast::FunctionPtrNode(span, moduleId);
484 BoundFunctionPtr* boundFunctionPtr = new BoundFunctionPtr(span, moduleId, boundFunction->GetFunctionSymbol(), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId));
485 BoundBitCast* boundBitCast = new BoundBitCast(std::unique_ptr<BoundExpression>(boundFunctionPtr), boundCompileUnit.GetSymbolTable().GetTypeByName(U"void")->AddPointer(span, moduleId));
486 std::unique_ptr<BoundExpression> boundFunctionPtrAsVoidPtr(boundBitCast);
487 functionPtrNode->SetBoundExpression(boundFunctionPtrAsVoidPtr.get());
488 sngcm::ast::AssignmentStatementNode assignFunctionPtr(span, moduleId, new sngcm::ast::DotNode(span, moduleId, unwindInfoNode3, new IdentifierNode(span, moduleId, U"function")),
489 new sngcm::ast::CastNode(span, moduleId, new sngcm::ast::PointerNode(span, moduleId, new sngcm::ast::VoidNode(span, moduleId)), functionPtrNode));
490 assignFunctionPtr.Accept(*this);
491 std::unique_ptr<BoundStatement> assignFunctionPtrStatement(statement.release());
492
493 sngcm::ast::IdentifierNode* unwindInfoNode4 = new IdentifierNode(span, moduleId, U"@unwindInfo");
494 symbolTable.MapSymbol(unwindInfoNode4, unwindInfoVariableSymbol);
495 symbolTable.MapNode(unwindInfoNode4, unwindInfoVariableSymbol);
496 sngcm::ast::AssignmentStatementNode assignUnwindInfoLine(span, moduleId, new sngcm::ast::DotNode(span, moduleId, unwindInfoNode4, new IdentifierNode(span, moduleId, U"line")),
497 new IntLiteralNode(span, moduleId, 0));
498 assignUnwindInfoLine.Accept(*this);
499 std::unique_ptr<BoundStatement> assignUnwindInfoLineStatement(statement.release());
500
501 sngcm::ast::IdentifierNode* prevUnwindInfoNode3 = new IdentifierNode(span, moduleId, U"@prevUnwindInfo");
502 symbolTable.MapSymbol(prevUnwindInfoNode3, prevUnwindInfoVariableSymbol);
503 symbolTable.MapNode(prevUnwindInfoNode3, prevUnwindInfoVariableSymbol);
504 sngcm::ast::InvokeNode* setPrevUnwindInfoListPtr = new sngcm::ast::InvokeNode(span, moduleId, new sngcm::ast::IdentifierNode(span, moduleId, U"RtPopUnwindInfo"));
505 setPrevUnwindInfoListPtr->AddArgument(new CastNode(span, moduleId, new PointerNode(span, moduleId, new VoidNode(span, moduleId)), prevUnwindInfoNode3));
506 sngcm::ast::ExpressionStatementNode setPrevUnwindInfoList(span, moduleId, setPrevUnwindInfoListPtr);
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(span, moduleId, U"@unwindInfo");
519 symbolTable.MapSymbol(unwindInfoNode5, unwindInfoVariableSymbol);
520 sngcm::ast::AssignmentStatementNode setUnwindInfoLine(span, moduleId, new sngcm::ast::DotNode(span, moduleId, unwindInfoNode5, new IdentifierNode(span, moduleId, U"line")),
521 new IntLiteralNode(span, moduleId, 0));
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(&boundCompileUnit, constructorSymbol));
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(currentConstructorSymbol, currentConstructorNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this, true,
566 constructorNode.GetSpan(), constructorNode.ModuleId());
567 currentConstructorNode = prevConstructorNode;
568 boundFunction->SetBody(std::move(boundCompoundStatement));
569 }
570 if (boundFunction->Body())
571 {
572 CheckFunctionReturnPaths(constructorSymbol, constructorNode, containerScope, boundCompileUnit);
573 currentClass->AddMember(std::move(boundFunction));
574 }
575 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(constructorNode.GetAttributes(), symbol, this);
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(&boundCompileUnit, destructorSymbol));
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(currentDestructorSymbol, currentDestructorNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this,
616 currentDestructorNode->GetSpan(), currentDestructorNode->ModuleId());
617 currentDestructorNode = prevDestructorNode;
618 boundFunction->SetBody(std::move(boundCompoundStatement));
619 }
620 if (boundFunction->Body())
621 {
622 CheckFunctionReturnPaths(destructorSymbol, destructorNode, containerScope, boundCompileUnit);
623 currentClass->AddMember(std::move(boundFunction));
624 }
625 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(destructorNode.GetAttributes(), symbol, this);
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(&boundCompileUnit, memberFunctionSymbol));
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(currentMemberFunctionSymbol, currentMemberFunctionNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this, true,
667 memberFunctionNode.GetSpan(), memberFunctionNode.ModuleId());
668 currentMemberFunctionNode = prevMemberFunctionNode;
669 boundFunction->SetBody(std::move(boundCompoundStatement));
670 }
671 if (boundFunction->Body())
672 {
673 CheckFunctionReturnPaths(memberFunctionSymbol, memberFunctionNode, containerScope, boundCompileUnit);
674 currentClass->AddMember(std::move(boundFunction));
675 }
676 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(memberFunctionNode.GetAttributes(), symbol, this);
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(&boundCompileUnit, conversionFunctionSymbol));
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(conversionFunctionSymbol, conversionFunctionNode, containerScope, boundCompileUnit);
706 currentClass->AddMember(std::move(boundFunction));
707 }
708 boundCompileUnit.GetAttributeBinder()->GenerateImplementation(conversionFunctionNode.GetAttributes(), symbol, this);
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(functionId, currentFunction->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(currentStaticConstructorSymbol, currentStaticConstructorNode, boundCompileUnit, boundCompoundStatement.get(), currentFunction, containerScope, this,
758 boundCompoundStatement->GetSpan(), boundCompoundStatement->ModuleId());
759 }
760 else if (currentConstructorSymbol && currentConstructorNode)
761 {
762 GenerateClassInitialization(currentConstructorSymbol, currentConstructorNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this, false,
763 boundCompoundStatement->GetSpan(), boundCompoundStatement->ModuleId());
764 }
765 else if (currentMemberFunctionSymbol && currentMemberFunctionSymbol->GroupName() == U"operator=" && currentMemberFunctionNode)
766 {
767 GenerateClassAssignment(currentMemberFunctionSymbol, currentMemberFunctionNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this, false,
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(currentDestructorSymbol, currentDestructorNode, boundCompoundStatement.get(), currentFunction, boundCompileUnit, containerScope, this,
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_parent, containerScope));
805 classReturnLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, currentFunction->GetFunctionSymbol()->ReturnType()->ClassInterfaceEnumDelegateOrNsScope()));
806 classReturnLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(), boundCompileUnit, currentFunction, containerScope, this, false, returnClassDelegateType,
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_parent, containerScope));
822 rvalueLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(exprType, returnType, containerScope, currentFunction, returnStatementNode.GetSpan(), returnStatementNode.ModuleId(), argumentMatch)));
830 }
831 rvalueArguments.push_back(std::move(expression));
832 std::unique_ptr<BoundExpression> rvalueExpr = ResolveOverload(U"System.Rvalue", containerScope, rvalueLookups, rvalueArguments, boundCompileUnit, currentFunction,
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", containerScope, classReturnLookups, classReturnArgs, boundCompileUnit, currentFunction,
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_parent, containerScope));
867 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::this_and_base_and_parent, returnType->BaseType()->ClassInterfaceEnumDelegateOrNsScope()));
868 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
869 std::unique_ptr<BoundFunctionCall> returnFunctionCall = ResolveOverload(U"@return", containerScope, functionScopeLookups, returnTypeArgs, boundCompileUnit, currentFunction,
870 returnStatementNode.GetSpan(), returnStatementNode.ModuleId());
871 std::unique_ptr<BoundExpression> expression = BindExpression(returnStatementNode.Expression(), boundCompileUnit, currentFunction, containerScope, this, false,
872 returnDelegateType || returnClassDelegateType, returnClassDelegateType);
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(boundCompileUnit, returnFunctionCall->GetFunctionSymbol(), returnValueArguments, functionMatch, ConversionType::implicit_,
881 containerScope, currentFunction, returnStatementNode.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(), boundCompileUnit, currentFunction, containerScope, this);
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(), boundCompileUnit, currentFunction, containerScope, this);
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(), boundCompileUnit, currentFunction, containerScope, this);
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(), boundCompileUnit, currentFunction, containerScope, this);
1104 }
1105 else
1106 {
1107 BooleanLiteralNode trueNode(forStatementNode.GetSpan(), forStatementNode.ModuleId(), true);
1108 condition = BindExpression(&trueNode, boundCompileUnit, currentFunction, containerScope, this);
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_parent, containerScope));
1225 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(argumentNode, boundCompileUnit, currentFunction, containerScope, this, false, constructDelegateOrClassDelegateType);
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", containerScope, functionScopeLookups, arguments, boundCompileUnit, currentFunction,
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(), boundCompileUnit, containerScope, currentFunction,
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(), boundCompileUnit, currentFunction, containerScope, this);
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_parent, containerScope));
1287 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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", containerScope, lookups, arguments, boundCompileUnit, currentFunction, span, moduleId);
1291 CheckAccess(currentFunction->GetFunctionSymbol(), disposeCall->GetFunctionSymbol());
1292 AddStatement(new BoundExpressionStatement(std::move(disposeCall), span, moduleId));
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_parent, containerScope));
1303 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->ClassInterfaceOrNsScope()));
1304 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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", containerScope, lookups, arguments, boundCompileUnit, currentFunction, span, moduleId);
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), span, moduleId));
1314 memFreePtr = BindExpression(deleteStatementNode.Expression(), boundCompileUnit, currentFunction, containerScope, this);
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_parent, containerScope));
1326 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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(memFreeFunctionName, containerScope, lookups, arguments, boundCompileUnit, currentFunction, span, moduleId);
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(), boundCompileUnit, currentFunction, containerScope, this);
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_parent, containerScope));
1366 lookups.push_back(FunctionScopeLookup(ScopeLookup::this_, classType->ClassInterfaceOrNsScope()));
1367 lookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
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", containerScope, lookups, arguments, boundCompileUnit, currentFunction,
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(), boundCompileUnit, currentFunction, containerScope, this, true);
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(), boundCompileUnit, currentFunction, containerScope, this, false, assignDelegateOrClassDelegateType);
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_parent, containerScope));
1428 functionScopeLookups.push_back(FunctionScopeLookup(ScopeLookup::fileScopes, nullptr));
1429 std::unique_ptr<BoundFunctionCall> assignmentCall = ResolveOverload(U"operator=", containerScope, functionScopeLookups, arguments, boundCompileUnit, currentFunction,
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(), boundCompileUnit, currentFunction, containerScope, this);
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(), boundCompileUnit, currentFunction, containerScope, this);
1487 TypeSymbol* plainContainerType = container->GetType()->PlainType(span, moduleId);
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(span, moduleId, U"ConstIterator"));
1497 }
1498 else
1499 {
1500 iteratorTypeNode.reset(new IdentifierNode(span, moduleId, U"Iterator"));
1501 }
1502 CloneContext cloneContext;
1503 std::unique_ptr<CompoundStatementNode> compoundStatementNode(new CompoundStatementNode(span, moduleId));
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(span, moduleId,
1517 new DotNode(span, moduleId, containerTypeNode->Clone(cloneContext), static_cast<IdentifierNode*>(iteratorTypeNode->Clone(cloneContext))), new IdentifierNode(span, moduleId, U"@end"));
1518 if (container->GetType()->IsConstType())
1519 {
1520 constructEndIteratorStatement->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, rangeForStatementNode.Container()->Clone(cloneContext),
1521 new IdentifierNode(span, moduleId, U"CEnd"))));
1522 }
1523 else
1524 {
1525 constructEndIteratorStatement->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, rangeForStatementNode.Container()->Clone(cloneContext),
1526 new IdentifierNode(span, moduleId, U"End"))));
1527 }
1528 compoundStatementNode->AddStatement(constructEndIteratorStatement);
1529 ConstructionStatementNode* constructIteratorStatement = new ConstructionStatementNode(initSpan, moduleId,
1530 new DotNode(span, moduleId, containerTypeNode->Clone(cloneContext), static_cast<IdentifierNode*>(iteratorTypeNode->Clone(cloneContext))), new IdentifierNode(span, moduleId, U"@it"));
1531 if (container->GetType()->IsConstType())
1532 {
1533 constructIteratorStatement->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, rangeForStatementNode.Container()->Clone(cloneContext),
1534 new IdentifierNode(span, moduleId, U"CBegin"))));
1535 }
1536 else
1537 {
1538 constructIteratorStatement->AddArgument(new InvokeNode(span, moduleId, new DotNode(span, moduleId, rangeForStatementNode.Container()->Clone(cloneContext),
1539 new IdentifierNode(span, moduleId, U"Begin"))));
1540 }
1541 Node* itNotEndCond = new NotEqualNode(colonSpan, moduleId, new IdentifierNode(colonSpan, moduleId, U"@it"), new IdentifierNode(colonSpan, moduleId, U"@end"));
1542 StatementNode* incrementItStatement = new ExpressionStatementNode(containerSpan, moduleId, new PrefixIncrementNode(containerSpan, moduleId, new IdentifierNode(containerSpan, moduleId, U"@it")));
1543 CompoundStatementNode* actionStatement = new CompoundStatementNode(actionBeginBraceSpan, moduleId);
1544 actionStatement->SetBeginBraceSpan(actionBeginBraceSpan);
1545 actionStatement->SetEndBraceSpan(actionEndBraceSpan);
1546 ConstructionStatementNode* constructLoopVarStatement = new ConstructionStatementNode(span, moduleId,
1547 rangeForStatementNode.TypeExpr()->Clone(cloneContext), static_cast<IdentifierNode*>(rangeForStatementNode.Id()->Clone(cloneContext)));
1548 constructLoopVarStatement->AddArgument(new DerefNode(span, moduleId, new IdentifierNode(span, moduleId, U"@it")));
1549 actionStatement->AddStatement(constructLoopVarStatement);
1550 actionStatement->AddStatement(static_cast<StatementNode*>(rangeForStatementNode.Action()->Clone(cloneContext)));
1551 ForStatementNode* forStatement = new ForStatementNode(span, moduleId, constructIteratorStatement, itNotEndCond, incrementItStatement, actionStatement);
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(), boundCompileUnit, currentFunction, containerScope, this);
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<IntegralValue, CaseStatementNode*, IntegralValueHash>*prevCaseValueMap=currentCaseValueMap;
1584 std::unordered_map<IntegralValue, CaseStatementNode*, 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(caseExprNode, switchConditionType, containerScope, boundCompileUnit, false, currentFunction, caseExprNode->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(caseExprNode, switchConditionType, containerScope, boundCompileUnit, false, currentFunction, gotoCaseStatementNode.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(boundGotoCaseStatement, IntegralValue(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(exceptionExprNode, boundCompileUnit, currentFunction, containerScope, this);
1748 if (boundExceptionExpr->GetType()->PlainType(span, moduleId)->IsClassTypeSymbol())
1749 {
1750 ClassTypeSymbol* exceptionClassType = static_cast<ClassTypeSymbol*>(boundExceptionExpr->GetType()->PlainType(span, moduleId));
1751 IdentifierNode systemExceptionNode(span, moduleId, U"System.Exception");
1752 TypeSymbol* systemExceptionType = ResolveType(&systemExceptionNode, boundCompileUnit, containerScope);
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(span, moduleId, new IdentifierNode(span, moduleId, exceptionClassType->FullName()));
1758 CloneContext cloneContext;
1759 newNode->AddArgument(throwStatementNode.Expression()->Clone(cloneContext));
1760 if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
1761 {
1762 InvokeNode invokeNode(span, moduleId, new IdentifierNode(span, moduleId, U"RtThrowException"));
1763 invokeNode.AddArgument(newNode);
1764 invokeNode.AddArgument(new UuidLiteralNode(span, moduleId, exceptionClassType->TypeId()));
1765 std::unique_ptr<BoundExpression> throwCallExpr = BindExpression(&invokeNode, boundCompileUnit, currentFunction, containerScope, this);
1766 AddStatement(new BoundThrowStatement(span, moduleId, std::move(throwCallExpr)));
1767 }
1768 else if (GetBackEnd() == BackEnd::cmsx)
1769 {
1770 InvokeNode invokeNode(span, moduleId, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"System"), new IdentifierNode(span, moduleId, U"Throw")));
1771 invokeNode.AddArgument(newNode);
1772 std::unique_ptr<BoundExpression> throwCallExpr = BindExpression(&invokeNode, boundCompileUnit, currentFunction, containerScope, this);
1773 AddStatement(new BoundThrowStatement(span, moduleId, std::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(span, moduleId, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"@exPtr"), new IdentifierNode(span, moduleId, U"Release")));
1791 std::unique_ptr<BoundExpression> releaseCall = BindExpression(&invokeNode, boundCompileUnit, currentFunction, containerScope, this);
1792 AddStatement(new BoundRethrowStatement(span, moduleId, std::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(span, moduleId));
1832 TypeSymbol* catchedType = ResolveType(catchNode.TypeExpr(), boundCompileUnit, containerScope);
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(span, moduleId, new PointerNode(span, moduleId, new IdentifierNode(span, moduleId, U"void")),
1851 new IdentifierNode(span, moduleId, U"@exceptionAddr"));
1852 getExceptionAddr->AddArgument(new InvokeNode(span, moduleId, new IdentifierNode(span, moduleId, U"RtGetException")));
1853 handlerBlock.AddStatement(getExceptionAddr);
1854 }
1855 else if (GetBackEnd() == BackEnd::cmsx)
1856 {
1857 ConstructionStatementNode* getExceptionAddr = new ConstructionStatementNode(span, moduleId, new PointerNode(span, moduleId, new IdentifierNode(span, moduleId, U"void")),
1858 new IdentifierNode(span, moduleId, U"@exceptionAddr"));
1859 getExceptionAddr->AddArgument(new InvokeNode(span, moduleId, new IdentifierNode(span, moduleId, U"do_catch")));
1860 handlerBlock.AddStatement(getExceptionAddr);
1861 }
1862 PointerNode exceptionPtrTypeNode(span, moduleId, new IdentifierNode(span, moduleId, catchedType->BaseType()->FullName()));
1863 CloneContext cloneContext;
1864 ConstructionStatementNode* constructExceptionPtr = new ConstructionStatementNode(span, moduleId, exceptionPtrTypeNode.Clone(cloneContext),
1865 new IdentifierNode(span, moduleId, U"@exceptionPtr"));
1866 constructExceptionPtr->AddArgument(new CastNode(span, moduleId, exceptionPtrTypeNode.Clone(cloneContext), new IdentifierNode(span, moduleId, U"@exceptionAddr")));
1867 handlerBlock.AddStatement(constructExceptionPtr);
1868 TemplateIdNode* uniquePtrNode = new TemplateIdNode(span, moduleId, new IdentifierNode(span, moduleId, U"UniquePtr"));
1869 uniquePtrNode->AddTemplateArgument(new IdentifierNode(span, moduleId, catchedType->BaseType()->FullName()));
1870 ConstructionStatementNode* constructUniquePtrException = new ConstructionStatementNode(span, moduleId, uniquePtrNode, new IdentifierNode(span, moduleId, U"@exPtr"));
1871 constructUniquePtrException->AddArgument(new IdentifierNode(span, moduleId, U"@exceptionPtr"));
1872 handlerBlock.AddStatement(constructUniquePtrException);
1873 if (catchVar)
1874 {
1875 ConstructionStatementNode* setExceptionVar = new ConstructionStatementNode(span, moduleId, catchNode.TypeExpr()->Clone(cloneContext), static_cast<IdentifierNode*>(catchNode.Id()->Clone(cloneContext)));
1876 setExceptionVar->AddArgument(new DerefNode(span, moduleId, new IdentifierNode(span, moduleId, U"@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_parent, symbolTable.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().fileIndex, assertStatementNode.ModuleId())),
1958 GetSourceFilePath(assertStatementNode.GetSpan().fileIndex, assertStatementNode.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(), boundCompileUnit, currentFunction, containerScope, this);
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(failAssertionFunctionName, containerScope, lookups, arguments,
1975 boundCompileUnit, currentFunction, Span(), 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* statementNode, bool 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& span, const boost::uuids::uuid& moduleId)
2131 {
2132 if (insideCatch && !compilingReleaseExceptionStatement)
2133 {
2134 compilingReleaseExceptionStatement = true;
2135 InvokeNode * invokeNode(new InvokeNode(span, moduleId, new DotNode(span, moduleId, new IdentifierNode(span, moduleId, U"@exPtr"), new IdentifierNode(span, moduleId, U"Release"))));
2136 ExpressionStatementNode releaseExceptionStatement(span, moduleId, invokeNode);
2137 CompileStatement(&releaseExceptionStatement, true);
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 } }