/*
 * xreatemanager.cpp
 *
 * Author: pgess <v.melnychenko@xreate.org>
 * Created on July 3, 2017, 6:03 PM
 */

#include "xreatemanager.h"
#include "clasplayer.h"
#include "aux/xreatemanager-decorators.h"
#include "llvmlayer.h"
#include "main/Parser.h"
#include <assert.h>
#include <list>

namespace xreate {
void
PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent)
{
    __passes.emplace(id, pass);
    __passDependencies.emplace(parent, pass);
}

AbstractPassBase*
PassManager::getPassById(const PassId& id){
	assert(__passes.count(id));
	return __passes[id];
}

bool
PassManager::isPassRegistered(const PassId& id){
    return __passes.count(id);
}

void
PassManager::executePasses(){
    std::list<AbstractPassBase*> passes{nullptr};
    while (passes.size()){
        AbstractPassBase* parent = passes.front();

        auto range = __passDependencies.equal_range(parent);

        for (auto i=range.first; i!=range.second; ++i){
            AbstractPassBase* pass = i->second;

            pass->run();
            pass->finish();

            passes.push_back(pass);
        }

        passes.pop_front();
    }
}

void
PassManager::prepare(AST* ast){
    root = ast;
    clasp = new ClaspLayer();
    clasp->ast = ast;
    llvm = new LLVMLayer(ast);
}

PassManager::~PassManager(){}

typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault;

namespace details{ namespace tier2{

XreateManager*
XreateManager::prepare(std::string&& code){
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(std::move(code));
    return man;
}

XreateManager*
XreateManager::prepare(FILE* code){
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(code);
    return man;
}
}}

namespace details { namespace tier1 {

XreateManager*
XreateManager::prepare(std::string&& code){
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(std::move(code));
    return man;
}

XreateManager*
XreateManager::prepare(FILE* code){
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(code);
    return man;
}

}}

XreateManager*
XreateManager::prepare(std::string&& code) {
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(std::move(code));
    return man;
}

XreateManager*
XreateManager::prepare(FILE* code){
    auto man = new XreateManagerImpl<XreateManagerDecoratorDefault>;

    man->prepareCode(code);
    return man;
}

}
