/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * xreatemanager-decorators.cpp
 *
 * Author: pgess <v.melnychenko@xreate.org>
 * Created on July 16, 2017, 4:40 PM
 */

/**
 * \file xreatemanager-decorators.h
 * \brief \ref xreate::XreateManager decorators to provide various functionality
 */

#include "aux/xreatemanager-decorators.h"
#include "main/Parser.h"
#include "pass/compilepass.h"
#include "transcendlayer.h"
#include "analysis/transcendtarget.h"
#include "pass/interpretationpass.h"

#ifndef XREATE_CONFIG_MIN
  #include "pass/cfapass.h"
  #include "pass/dfapass.h"
  #include "pass/versionspass.h"
  #include "pass/cfatemporalseqpass.h"
#endif

namespace xreate{

void
XreateManagerDecoratorBase::initPasses() { }

void
XreateManagerDecoratorBase::prepareCode(std::string&& code) {
  grammar::main::Scanner scanner(reinterpret_cast<const unsigned char*> (code.c_str()), code.size());
  grammar::main::Parser parser(&scanner);
  parser.Parse();
  assert(!parser.errors->count && "Parser errors");

  PassManager::prepare(parser.root->finalize());
}

void
XreateManagerDecoratorBase::prepareCode(FILE* code){
  grammar::main::Scanner scanner(code);
  grammar::main::Parser parser(&scanner);
  parser.Parse();
  assert(!parser.errors->count && "Parser errors");

  PassManager::prepare(parser.root->finalize());
}

void
XreateManagerDecoratorBase::analyse() {
    CompilePass::prepareQueries(transcend);
    transcend->run();
}

void
XreateManagerDecoratorFull::initPasses() {
  #ifndef XREATE_CONFIG_MIN
    cfa::CFAPass* passCFG = new cfa::CFAPass(this);
    registerPass(new dfa::DFAPass(this), PassId::DFAPass);
    registerPass(passCFG, PassId::CFAPass);
    registerPass(new versions::VersionsPass(this), PassId::VersionsPass);
    registerPass(new cfa::CFATemporalSeqPass(this), PassId::CFATemporalSeqPass);
  #endif

  registerPass(new interpretation::InterpretationPass(this), PassId::InterpretationPass);
  registerPass(new TranscendPass(this), PassId::TranscendPass);
}

void*
XreateManagerDecoratorFull::run() {
  transcend->deleteReports();
  __compiler = new compilation::CompilePassCustomDecorators<>(this);
  __compiler->run();

  llvm->print();
  llvm->initJit();
  if (options.requireEntryFn){
    assert(__compiler->getEntryFunction());
  }

  if (__compiler->getEntryFunction())
    return llvm->getFunctionPointer(__compiler->getEntryFunction());

  return nullptr;
}

void*
XreateManagerDecoratorFull::getExteriorFn(const string& fnName){
  ManagedFnPtr fnTarget = root->findFunction(fnName);
  assert(fnTarget);

  compilation::IBruteFunction* fnBrute = __compiler->getBruteFn(fnTarget);
  llvm::Function* fnRaw = fnBrute->compile();
  return llvm->getFunctionPointer(fnRaw);
}

} //namespace xreate
