1
2
3
4
5
6 #include <cmajor/binder/BoundFunction.hpp>
7 #include <cmajor/binder/BoundCompileUnit.hpp>
8 #include <cmajor/binder/BoundStatement.hpp>
9 #include <cmajor/binder/BoundNodeVisitor.hpp>
10 #include <cmajor/binder/BoundClass.hpp>
11 #include <cmajor/symbols/Exception.hpp>
12 #include <cmajor/symbols/GlobalFlags.hpp>
13 #include <soulng/util/Unicode.hpp>
14
15 namespace cmajor { namespace binder {
16
17 using namespace soulng::unicode;
18
19 BoundFunction::BoundFunction(BoundCompileUnit* boundCompileUnit_, FunctionSymbol* functionSymbol_) :
20 BoundNode(functionSymbol_->GetSpan(), functionSymbol_->SourceModuleId(), BoundNodeType::boundFunction), boundCompileUnit(boundCompileUnit_), functionSymbol(functionSymbol_), hasGotos(false)
21 {
22 }
23
24 void BoundFunction::Load(Emitter& emitter, OperationFlags flags)
25 {
26 throw Exception("cannot load from function", GetSpan(), ModuleId());
27 }
28
29 void BoundFunction::Store(Emitter& emitter, OperationFlags flags)
30 {
31 throw Exception("cannot store to function", GetSpan(), ModuleId());
32 }
33
34 void BoundFunction::Accept(BoundNodeVisitor& visitor)
35 {
36 visitor.Visit(*this);
37 }
38
39 void BoundFunction::SetBody(std::std::unique_ptr<BoundCompoundStatement>&&body_)
40 {
41 body = std::move(body_);
42 }
43
44 void BoundFunction::AddTemporaryDestructorCall(std::std::unique_ptr<BoundFunctionCall>&&destructorCall,
45 BoundFunction* currentFunction, ContainerScope* currentContainerScope, const Span& span, const boost::uuids::uuid& moduleId)
46 {
47 FunctionSymbol* functionSymbol = destructorCall->GetFunctionSymbol();
48 if (functionSymbol->GetSymbolType() == SymbolType::destructorSymbol)
49 {
50 DestructorSymbol* destructorSymbol = static_cast<DestructorSymbol*>(functionSymbol);
51 if (destructorSymbol->IsGeneratedFunction() && !GetGlobalFlag(GlobalFlags::info))
52 {
53 if (destructorSymbol->Parent()->IsClassTypeSymbol())
54 {
55 ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(destructorSymbol->Parent());
56 if (!boundCompileUnit->IsGeneratedDestructorInstantiated(destructorSymbol))
57 {
58 boundCompileUnit->SetGeneratedDestructorInstantiated(destructorSymbol);
59 std::unique_ptr<BoundClass> boundClass(new BoundClass(classType));
60 GenerateDestructorImplementation(boundClass.get(), destructorSymbol, *boundCompileUnit, currentContainerScope, currentFunction, span, moduleId);
61 boundCompileUnit->AddBoundNode(std::move(boundClass));
62 }
63 }
64 }
65 else if (destructorSymbol->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
66 {
67 bool firstTry = GetBoundCompileUnit()->GetClassTemplateRepository().Instantiate(destructorSymbol, currentContainerScope, currentFunction, span, moduleId);
68 if (!firstTry)
69 {
70 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(destructorSymbol->Parent());
71 std::lock_guard<std::recursive_mutex> lock(GetBoundCompileUnit()->GetModule().GetLock());
72 ClassTemplateSpecializationSymbol* copy = GetBoundCompileUnit()->GetSymbolTable().CopyClassTemplateSpecialization(specialization);
73 GetBoundCompileUnit()->GetClassTemplateRepository().BindClassTemplateSpecialization(copy, currentContainerScope, span, moduleId);
74 int index = destructorSymbol->GetIndex();
75 FunctionSymbol* functionSymbol = copy->GetFunctionByIndex(index);
76 bool secondTry = GetBoundCompileUnit()->InstantiateClassTemplateMemberFunction(functionSymbol, currentContainerScope, currentFunction, span, moduleId);
77 if (!secondTry)
78 {
79 throw Exception("internal error: could not instantiate destructor of a class template specialization '" + ToUtf8(specialization->FullName()) + "'",
80 specialization->GetSpan(), specialization->SourceModuleId());
81 }
82 }
83 }
84 }
85 temporaryDestructorCalls.push_back(std::move(destructorCall));
86 }
87
88 void BoundFunction::MoveTemporaryDestructorCallsTo(BoundExpression& expression)
89 {
90 for (std::std::unique_ptr<BoundFunctionCall>&destructorCall : temporaryDestructorCalls)
91 {
92 expression.AddTemporaryDestructorCall(std::move(destructorCall));
93 }
94 temporaryDestructorCalls.clear();
95 }
96
97 void BoundFunction::AddLabeledStatement(BoundStatement* labeledStatement)
98 {
99 labeledStatements.push_back(labeledStatement);
100 }
101
102 void BoundFunction::SetEnterCode(std::std::vector<std::std::unique_ptr<BoundStatement>>&&enterCode_)
103 {
104 enterCode = std::move(enterCode_);
105 }
106
107 void BoundFunction::SetExitCode(std::std::vector<std::std::unique_ptr<BoundStatement>>&&exitCode_)
108 {
109 exitCode = std::move(exitCode_);
110 }
111
112 void BoundFunction::SetLineCode(std::std::unique_ptr<BoundStatement>&&lineCode_)
113 {
114 lineCode.reset(lineCode_.release());
115 }
116
117 } }