#include <pass/abstractpass.h>
#include "query/containers.h"
#include "passmanager.h"
#include "pass/compilepass.h"

#include "Parser.h"
#include "pass/cfgpass.h"
#include "pass/dfgpass.h"
#include "pass/logging.h"
#include <list>

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(Scanner& scanner){
      Parser parser(&scanner);
      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);

      CFGPass* passCFG = new CFGPass(man);

      man->registerPass(new DFGPass(man), passCFG);
      man->registerPass(passCFG);

      return man;
}



void
PassManager::registerPass(AbstractPassBase* pass, AbstractPassBase* parent)
{
    __passes.emplace(parent, pass);
}

void*
PassManager::run()
{
	runWithoutCompilation();

    CompilePass* compiler = new CompilePass(this);
    compiler->run();

    		//Compiler Dependents:
    Logging* logger = new Logging(this);
	logger->initDependencies(compiler);
	logger->run();

    llvm->print();
    llvm->initJit();
    return llvm->getFunctionPointer(compiler->getEntryFunction());
}

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

		auto range = __passes.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();
	}

    clasp->registerdQuery(new containers::Query());
    clasp->run();
}

PassManager::~PassManager(){}
