
#include "passmanager.h"
#include <pass/abstractpass.h>
#include "Parser.h"
#include "clasplayer.h"

#include <list>
#include <stdio.h>

using namespace xreate;
using namespace std;

PassManager*
PassManager::prepareForCode(std::string&& code){
      Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
      return prepareForCode(&scanner);
}

PassManager*
PassManager::prepareForCode(FILE* code){
      Scanner scanner(code);
      return prepareForCode(&scanner);
}

PassManager*
PassManager::prepareForCode(Scanner* code){
    Parser parser(code);
    parser.Parse();
    assert(!parser.errors->count && "Parser errors");

    PassManager* man = new PassManager;
    AST* ast = new AST(parser.root);

    man->root = ast;
    man->clasp = new ClaspLayer();

    man->clasp->ast = man->root;
    man->llvm = new LLVMLayer(man->root);

    return man;
}

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();
    }
}



PassManager::~PassManager(){}
