1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  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& emitterOperationFlags flags)
 25 {
 26     throw Exception("cannot load from function"GetSpan()ModuleId());
 27 }
 28 
 29 void BoundFunction::Store(Emitter& emitterOperationFlags 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* currentFunctionContainerScope* currentContainerScopeconst Span& spanconst 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*boundCompileUnitcurrentContainerScopecurrentFunctionspanmoduleId);
 61                     boundCompileUnit->AddBoundNode(std::move(boundClass));
 62                 }
 63             }
 64         }
 65         else if (destructorSymbol->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 66         {
 67             bool firstTry = GetBoundCompileUnit()->GetClassTemplateRepository().Instantiate(destructorSymbolcurrentContainerScopecurrentFunctionspanmoduleId);
 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(copycurrentContainerScopespanmoduleId);
 74                 int index = destructorSymbol->GetIndex();
 75                 FunctionSymbol* functionSymbol = copy->GetFunctionByIndex(index);
 76                 bool secondTry = GetBoundCompileUnit()->InstantiateClassTemplateMemberFunction(functionSymbolcurrentContainerScopecurrentFunctionspanmoduleId);
 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 } } // namespace cmajor::binder