/*
 Copyright 2019 Alain Dargelas

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/*
 * File:   Compiler.cpp
 * Author: alain
 *
 * Created on March 4, 2017, 5:16 PM
 */
#include "CommandLine/CommandLineParser.h"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/SymbolTable.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/Compiler.h"
#include "SourceCompile/CheckCompile.h"
#include "antlr4-runtime.h"
#include "DesignCompile/CompileDesign.h"
#include "SourceCompile/AnalyzeFile.h"
#include "Library/ParseLibraryDef.h"
#include "Utils/FileUtils.h"
#include "Package/Precompiled.h"
#include "Utils/StringUtils.h"
#include "Utils/Timer.h"
#include <math.h>
using namespace antlr4;

#include "API/PythonAPI.h"
#include "SourceCompile/CheckCompile.h"
#include <mutex>
#include <thread>
#include <vector>
using namespace SURELOG;

Compiler::Compiler(CommandLineParser* commandLineParser, ErrorContainer* errors,
                   SymbolTable* symbolTable)
    : m_commandLineParser(commandLineParser),
      m_errors(errors),
      m_symbolTable(symbolTable),
      m_commonCompilationUnit(NULL) {
  m_design = NULL;
#ifdef USETBB
  if (getCommandLineParser()->useTbb() &&
      (getCommandLineParser()->getNbMaxTreads() > 0))
    tbb::task_scheduler_init init(getCommandLineParser()->getNbMaxTreads());
#endif
}

Compiler::Compiler(const Compiler& orig) {}

Compiler::~Compiler() {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr;
  for (itr = m_antlrPpMap.begin(); itr != m_antlrPpMap.end(); itr++) {
    delete (*itr).second;
  }
  if (m_commonCompilationUnit) {
    delete m_commonCompilationUnit;
  }
  cleanup_();
}

struct FunctorCompileOneFile {
  FunctorCompileOneFile(CompileSourceFile* compileSource,
                        CompileSourceFile::Action action)
      : m_compileSourceFile(compileSource), m_action(action) {}

  int operator()() const {
    if (m_compileSourceFile->getCommandLineParser()->pythonListener() ||
        m_compileSourceFile->getCommandLineParser()
            ->pythonEvalScriptPerFile()) {
      PyThreadState* interpState = PythonAPI::initNewInterp();
      m_compileSourceFile->setPythonInterp(interpState);
    }
    return m_compileSourceFile->compile(m_action);
  }

 private:
  CompileSourceFile* m_compileSourceFile;
  CompileSourceFile::Action m_action;
};

bool Compiler::compileOneFile_(CompileSourceFile* compiler,
                               CompileSourceFile::Action action) {
  bool status = compiler->compile(action);
  return status;
}

bool Compiler::isLibraryFile(SymbolId id) {
  if (m_libraryFiles.find(id) == m_libraryFiles.end()) {
    return false;
  } else {
    return true;
  }
}

bool Compiler::ppinit_() {
  if (!m_commandLineParser->fileunit()) {
    m_commonCompilationUnit = new CompilationUnit(false);
  }

  CompilationUnit* comp_unit = m_commonCompilationUnit;

  // Source files (.v, .sv on the command line)
  std::set<SymbolId> sourceFiles;
  unsigned int size = m_commandLineParser->getSourceFiles().size();
  for (unsigned int i = 0; i < size; i++) {
    SymbolTable* symbols = m_symbolTable;
    if (m_commandLineParser->fileunit()) {
      comp_unit = new CompilationUnit(true);
      m_compilationUnits.push_back(comp_unit);
      symbols = new SymbolTable(*m_commandLineParser->getSymbolTable());
      m_symbolTables.push_back(symbols);
    }
    ErrorContainer* errors = new ErrorContainer(symbols);
    m_errorContainers.push_back(errors);
    errors->regiterCmdLine(m_commandLineParser);

    SymbolId id = m_commandLineParser->getSourceFiles()[i];

    std::string fileName = m_commandLineParser->getSymbolTable()->getSymbol(id);
    std::string fullPath = FileUtils::getFullPath(fileName);
    SymbolId fullPathId =
        m_commandLineParser->getSymbolTable()->registerSymbol(fullPath);
    Library* library = m_librarySet->getLibrary(fullPathId);
    sourceFiles.insert(fullPathId);

    CompileSourceFile* compiler = new CompileSourceFile(
        m_commandLineParser->getSourceFiles()[i], m_commandLineParser, errors,
        this, symbols, comp_unit, library);
    m_compilers.push_back(compiler);
  }

  // Library files
  std::set<SymbolId> libFiles;
  // (-v <file>)
  size = m_commandLineParser->getLibraryFiles().size();
  for (unsigned int i = 0; i < size; i++) {
    SymbolId id = m_commandLineParser->getLibraryFiles()[i];
    libFiles.insert(id);
  }
  // (-y <path> +libext+<ext>)
  for (auto path : m_commandLineParser->getLibraryPaths()) {
    for (auto ext : m_commandLineParser->getLibraryExtensions()) {
      auto files = FileUtils::collectFiles(
          path, ext, m_commandLineParser->getSymbolTable());
      for (auto file : files) {
        libFiles.insert(file);
      }
    }
  }
  for (auto id : libFiles) {
    SymbolTable* symbols = m_symbolTable;
    if (m_commandLineParser->fileunit()) {
      comp_unit = new CompilationUnit(true);
      m_compilationUnits.push_back(comp_unit);
      symbols = new SymbolTable(*m_commandLineParser->getSymbolTable());
      m_symbolTables.push_back(symbols);
    }
    ErrorContainer* errors = new ErrorContainer(symbols);
    m_errorContainers.push_back(errors);
    errors->regiterCmdLine(m_commandLineParser);

    std::string fullPath = FileUtils::getFullPath(
        m_commandLineParser->getSymbolTable()->getSymbol(id));

    // This line registers the file in the "work" library:
    SymbolId fullPathId =
        m_commandLineParser->getSymbolTable()->registerSymbol(fullPath);
    /*Library* library  = */ m_librarySet->getLibrary(fullPathId);
    m_libraryFiles.insert(id);
    m_libraryFiles.insert(fullPathId);
    // No need to register a compiler
    // CompileSourceFile* compiler = new CompileSourceFile
    // (m_commandLineParser->getLibraryFiles ()[i],
    //                                                     m_commandLineParser,
    //                                                     errors, this,
    //                                                     symbols, comp_unit,
    //                                                     library);
    // m_compilers.push_back (compiler);
  }

  // Libraries (.map)
  for (auto& lib : m_librarySet->getLibraries()) {
    for (auto id : lib.getFiles()) {
      std::string fileName = lib.getSymbols()->getSymbol(id);
      if (sourceFiles.find(id) != sourceFiles.end()) {
        // These files are already included in the command line
        continue;
      }

      if (strstr(fileName.c_str(), ".map")) {
        // .map files are not parsed with the regular parser
        continue;
      }
      SymbolTable* symbols = m_symbolTable;
      if (m_commandLineParser->fileunit()) {
        comp_unit = new CompilationUnit(true);
        m_compilationUnits.push_back(comp_unit);
        symbols = new SymbolTable(*m_commandLineParser->getSymbolTable());
        m_symbolTables.push_back(symbols);
      }
      ErrorContainer* errors = new ErrorContainer(symbols);
      m_errorContainers.push_back(errors);
      errors->regiterCmdLine(m_commandLineParser);

      CompileSourceFile* compiler = new CompileSourceFile(
          id, m_commandLineParser, errors, this, symbols, comp_unit, &lib);
      m_compilers.push_back(compiler);
    }
  }

  return true;
}

bool Compiler::parseinit_() {
  Precompiled* prec = Precompiled::getSingleton();
  // Single out the large files.
  // Small files are going to be scheduled in multiple threads based on size.
  // Large files are going to be compiled in a different batch in multithread

  if (!m_commandLineParser->fileunit()) {
    unsigned int size = m_symbolTables.size();
    for (unsigned int i = 0; i < size; i++) {
      delete m_symbolTables[i];
    }
    size = m_errorContainers.size();
    for (unsigned int i = 0; i < size; i++) {
      delete m_errorContainers[i];
    }
    m_symbolTables.clear();
    m_errorContainers.clear();
  }

  std::vector<CompileSourceFile*> tmp_compilers;
  unsigned int size = m_compilers.size();
  for (unsigned int i = 0; i < size; i++) {
    std::string fileName = m_compilers[i]->getSymbolTable()->getSymbol(
        m_compilers[i]->getPpOutputFileId());
    std::string origFile = m_compilers[i]->getSymbolTable()->getSymbol(
        m_compilers[i]->getFileId());
    unsigned int nbThreads = m_commandLineParser->getNbMaxTreads();
    std::string root = fileName;
    root = StringUtils::getRootFileName(root);
    if (prec->isFilePrecompiled(root)) {
      nbThreads = 0;
    }
    int effectiveNbThreads = 0;
    if (nbThreads > 4)
      effectiveNbThreads = (int)(log(((float)nbThreads + 1.0) / 4.0) * 10.0);
    else
      effectiveNbThreads = nbThreads;

    AnalyzeFile* fileAnalyzer = new AnalyzeFile(
        m_commandLineParser, m_design, fileName, origFile, effectiveNbThreads);
    fileAnalyzer->analyze();
    m_compilers[i]->setFileAnalyzer(fileAnalyzer);
    if (fileAnalyzer->getSplitFiles().size() > 1) {
      // Schedule parent
      m_compilersParentFiles.push_back(m_compilers[i]);
      m_compilers[i]->initParser();

      if (!m_commandLineParser->fileunit()) {
        SymbolTable* symbols =
            new SymbolTable(*m_commandLineParser->getSymbolTable());
        m_symbolTables.push_back(symbols);
        m_compilers[i]->setSymbolTable(symbols);
        // fileContent->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->regiterCmdLine(m_commandLineParser);
        m_compilers[i]->setErrorContainer(errors);
      }

      FileContent* fileContent =
          new FileContent(m_compilers[i]->getParser()->getFileId(0),
                          m_compilers[i]->getParser()->getLibrary(),
                          m_compilers[i]->getSymbolTable(),
                          m_compilers[i]->getErrorContainer(), NULL, 0);
      m_compilers[i]->getParser()->setFileContent(fileContent);

      int j = 0;
      for (auto chunk : fileAnalyzer->getSplitFiles()) {
        SymbolTable* symbols =
            new SymbolTable(*m_commandLineParser->getSymbolTable());
        m_symbolTables.push_back(symbols);
        SymbolId ppId = symbols->registerSymbol(chunk);
        symbols->registerSymbol(
            m_compilers[i]->getParser()->getFileName(LINE1));
        CompileSourceFile* chunkCompiler = new CompileSourceFile(
            m_compilers[i], ppId, fileAnalyzer->getLineOffsets()[j]);
        // Schedule chunk
        tmp_compilers.push_back(chunkCompiler);

        chunkCompiler->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->regiterCmdLine(m_commandLineParser);
        chunkCompiler->setErrorContainer(errors);
        // chunkCompiler->getParser ()->setFileContent (fileContent);

        FileContent* fileContent =
            new FileContent(m_compilers[i]->getParser()->getFileId(0),
                            m_compilers[i]->getParser()->getLibrary(), symbols,
                            errors, NULL, ppId);
        chunkCompiler->getParser()->setFileContent(fileContent);
        getDesign()->addFileContent(m_compilers[i]->getParser()->getFileId(0),
                                    fileContent);

        j++;
      }
    } else {
      if (!m_commandLineParser->fileunit()) {
        SymbolTable* symbols =
            new SymbolTable(*m_commandLineParser->getSymbolTable());
        m_symbolTables.push_back(symbols);
        m_compilers[i]->setSymbolTable(symbols);
        ErrorContainer* errors = new ErrorContainer(symbols);
        m_errorContainers.push_back(errors);
        errors->regiterCmdLine(m_commandLineParser);
        m_compilers[i]->setErrorContainer(errors);
      }

      tmp_compilers.push_back(m_compilers[i]);
    }
  }
  m_compilers = tmp_compilers;

  return true;
}

bool Compiler::pythoninit_() { return parseinit_(); }

ErrorContainer::Stats Compiler::getErrorStats() {
  ErrorContainer::Stats stats;
  unsigned int size = m_errorContainers.size();
  for (unsigned int i = 0; i < size; i++) {
    ErrorContainer::Stats tmp;
    tmp = m_errorContainers[i]->getErrorStats();
    stats += tmp;
  }

  return stats;
}

bool Compiler::cleanup_() {
  unsigned int size = m_compilers.size();
  for (unsigned int i = 0; i < size; i++) {
    delete m_compilers[i];
  }
  size = m_compilationUnits.size();
  for (unsigned int i = 0; i < size; i++) {
    delete m_compilationUnits[i];
  }
  size = m_symbolTables.size();
  for (unsigned int i = 0; i < size; i++) {
    delete m_symbolTables[i];
  }
  size = m_errorContainers.size();
  for (unsigned int i = 0; i < size; i++) {
    delete m_errorContainers[i];
  }
  return true;
}

bool Compiler::compileFileSet_(CompileSourceFile::Action action,
                               bool allowMultithread,
                               std::vector<CompileSourceFile*>& container) {
  unsigned short maxThreadCount = m_commandLineParser->getNbMaxTreads();
  if (allowMultithread == false) {
    maxThreadCount = 0;
  }

  if (maxThreadCount == 0) {
    // Single thread
    unsigned int size = container.size();
    for (unsigned int i = 0; i < size; i++) {
      container[i]->setPythonInterp(PythonAPI::getMainInterp());
      bool status = compileOneFile_(container[i], action);
      m_errors->appendErrors(*container[i]->getErrorContainer());
      m_errors->printMessages(m_commandLineParser->muteStdout());
      if ((!status) || container[i]->getErrorContainer()->hasFatalErrors())
        return false;
    }
  } else if (getCommandLineParser()->useTbb() &&
             (action != CompileSourceFile::Action::Parse)) {
#ifdef USETBB
    // TBB Thread management
    int maxThreadCount = m_commandLineParser->getNbMaxTreads();
    if (allowMultithread == false) {
      maxThreadCount = 0;
    }
    unsigned int size = container.size();
    if (maxThreadCount) {
      for (unsigned int i = 0; i < size; i++) {
        m_taskGroup.run(FunctorCompileOneFile(container[i], action));
      }
      m_taskGroup.wait();
      bool fatalErrors = false;
      for (unsigned int i = 0; i < size; i++) {
        // Promote report to master error container
        m_errors->appendErrors(*container[i]->getErrorContainer());
        if (container[i]->getErrorContainer()->hasFatalErrors()) {
          fatalErrors = true;
        }
        if (getCommandLineParser()->pythonListener()) {
          container[i]->shutdownPythonInterp();
        }
        m_errors->printMessages(m_commandLineParser->muteStdout());
      }
      if (fatalErrors) return false;
    } else {
      for (unsigned int i = 0; i < size; i++) {
        container[i]->setPythonInterp(PythonAPI::getMainInterp());
        bool status = compileOneFile_(container[i], action);
        m_errors->appendErrors(*container[i]->getErrorContainer());
        m_errors->printMessages(m_commandLineParser->muteStdout());
        if ((!status) || container[i]->getErrorContainer()->hasFatalErrors())
          return false;
      }
    }
#endif
  } else {
    // Custom Thread management

    // Optimize the load balance, try to even out the work in each thread by the
    // size of the files
    std::vector<std::vector<CompileSourceFile*>> jobArray(maxThreadCount);

    std::vector<unsigned long> jobSize(maxThreadCount);

    for (unsigned short i = 0; i < maxThreadCount; i++) jobSize[i] = 0;

    for (unsigned int i = 0; i < container.size(); i++) {
      unsigned int size = container[i]->getJobSize(action);
      unsigned int newJobIndex = 0;
      unsigned long minJobQueue = ULLONG_MAX;
      for (unsigned short ii = 0; ii < maxThreadCount; ii++) {
        if (jobSize[ii] < minJobQueue) {
          newJobIndex = ii;
          minJobQueue = jobSize[ii];
        }
      }

      jobSize[newJobIndex] += size;
      jobArray[newJobIndex].push_back(container[i]);
    }

    if (getCommandLineParser()->profile()) {
      if (action == CompileSourceFile::Preprocess)
        std::cout << "Preprocessing task\n";
      else if (action == CompileSourceFile::Parse)
        std::cout << "Parsing task\n";
      else
        std::cout << "Misc Task\n";
      for (unsigned short i = 0; i < maxThreadCount; i++) {
        std::cout << "Thread " << i << " : \n";
        int sum = 0;
        for (unsigned int j = 0; j < jobArray[i].size(); j++) {
          std::string fileName;
          if (jobArray[i][j]->getPreprocessor())
            fileName = jobArray[i][j]->getPreprocessor()->getFileName(0);
          if (jobArray[i][j]->getParser())
            fileName = jobArray[i][j]->getParser()->getFileName(0);
          sum += jobArray[i][j]->getJobSize(action);
          std::cout << jobArray[i][j]->getJobSize(action) << " " << fileName
                    << "\n";
        }
        std::cout << ", Total: " << sum << std::endl << std::flush;
      }
    }

    // Create the threads with their respective workloads
    std::vector<std::thread*> threads;
    for (unsigned short i = 0; i < maxThreadCount; i++) {
      std::thread* th = new std::thread([=] {
        for (unsigned int j = 0; j < jobArray[i].size(); j++) {
          if (getCommandLineParser()->pythonListener() ||
              getCommandLineParser()->pythonEvalScriptPerFile()) {
            PyThreadState* interpState = PythonAPI::initNewInterp();
            jobArray[i][j]->setPythonInterp(interpState);
          }

          jobArray[i][j]->compile(action);

          if (getCommandLineParser()->pythonListener() ||
              getCommandLineParser()->pythonEvalScriptPerFile()) {
            jobArray[i][j]->shutdownPythonInterp();
          }
        }
      });
      threads.push_back(th);
    }

    // Sync the threads
    for (unsigned int th = 0; th < threads.size(); th++) {
      threads[th]->join();
    }

    // Delete the threads
    for (unsigned int th = 0; th < threads.size(); th++) {
      delete threads[th];
    }

    // Promote report to master error container
    bool fatalErrors = false;
    for (unsigned int j = 0; j < container.size(); j++) {
      m_errors->appendErrors(*container[j]->getErrorContainer());
      if (container[j]->getErrorContainer()->hasFatalErrors())
        fatalErrors = true;
    }
    m_errors->printMessages(m_commandLineParser->muteStdout());

    if (fatalErrors) return false;
  }
  return true;
}

bool Compiler::compile() {
  std::string profile;
  Timer tmr;
  Timer tmrTotal;
  // Scan the libraries definition
  if (!parseLibrariesDef_()) return false;

  if (m_commandLineParser->profile()) {
    std::string msg = "Scan libraries took " +
                      StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Preprocess
  ppinit_();
  if (!compileFileSet_(CompileSourceFile::Preprocess,
                       m_commandLineParser->fileunit(), m_compilers))
    return false;

  // Single thread post Preprocess
  if (!compileFileSet_(CompileSourceFile::PostPreprocess, false, m_compilers))
    return false;

  if (m_commandLineParser->profile()) {
    std::string msg = "Preprocessing took " +
                      StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Parse
  bool parserInitialized = false;
  if (m_commandLineParser->parse() || m_commandLineParser->pythonListener() ||
      m_commandLineParser->pythonEvalScriptPerFile() ||
      m_commandLineParser->pythonEvalScript()) {
    parseinit_();
    parserInitialized = true;
    if (!compileFileSet_(CompileSourceFile::Parse, true, m_compilers))
      return false;  // Small files and large file chunks
    if (!compileFileSet_(CompileSourceFile::Parse, true,
                         m_compilersParentFiles))
      return false;  // Recombine chunks
  }

  if (m_commandLineParser->profile()) {
    std::string msg =
        "Parsing took " + StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
    for (unsigned int i = 0; i < m_compilersParentFiles.size(); i++) {
      msg += m_compilersParentFiles[i]->getParser()->getProfileInfo();
    }
    for (unsigned int i = 0; i < m_compilers.size(); i++) {
      msg += m_compilers[i]->getParser()->getProfileInfo();
    }

    std::cout << msg << std::endl;
    profile += msg;
    tmr.reset();
  }

  // Check Parsing
  CheckCompile* checkComp = new CheckCompile(this);
  checkComp->check();
  delete checkComp;
  m_errors->printMessages(m_commandLineParser->muteStdout());

  // Python Listener
  if (m_commandLineParser->pythonListener() ||
      m_commandLineParser->pythonEvalScriptPerFile()) {
    if (!parserInitialized) pythoninit_();
    if (!compileFileSet_(CompileSourceFile::PythonAPI, true, m_compilers))
      return false;
    if (!compileFileSet_(CompileSourceFile::PythonAPI, true,
                         m_compilersParentFiles))
      return false;

    if (m_commandLineParser->profile()) {
      std::string msg = "Python file processing took " +
                        StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
      std::cout << msg << std::endl;
      profile += msg;
      tmr.reset();
    }
  }

  if (m_commandLineParser->compile()) {
    // Compile Design, has its own thread management
    CompileDesign* compileDesign = new CompileDesign(this);
    compileDesign->compile();
    m_errors->printMessages(m_commandLineParser->muteStdout());

    if (m_commandLineParser->profile()) {
      std::string msg = "Compilation took " +
                        StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
      std::cout << msg << std::endl;
      profile += msg;
      tmr.reset();
    }

    if (m_commandLineParser->elaborate()) {
      compileDesign->elaborate();
      m_errors->printMessages(m_commandLineParser->muteStdout());

      if (m_commandLineParser->profile()) {
        std::string msg = "Elaboration took " +
                          StringUtils::to_string(tmr.elapsed_rounded()) + "s\n";
        std::cout << msg << std::endl;
        profile += msg;
        tmr.reset();
      }

      if (m_commandLineParser->pythonEvalScript()) {
        PythonAPI::evalScript(m_commandLineParser->getSymbolTable()->getSymbol(
                                  m_commandLineParser->pythonEvalScriptId()),
                              m_design);
        if (m_commandLineParser->profile()) {
          std::string msg = "Python design processing took " +
                            StringUtils::to_string(tmr.elapsed_rounded()) +
                            "s\n";
          profile += msg;
          std::cout << msg << std::endl;
          tmr.reset();
        }
      }
      m_errors->printMessages(m_commandLineParser->muteStdout());
    }

    delete compileDesign;
  }
  if (m_commandLineParser->profile()) {
    std::string msg = "Total time " +
                      StringUtils::to_string(tmrTotal.elapsed_rounded()) +
                      "s\n";
    profile += msg;
    profile = std::string("==============\n") + "PROFILE\n" +
              std::string("==============\n") + profile + "==============\n";
    std::cout << profile << std::endl;
    m_errors->printToLogFile(profile);
  }
  return true;
}

void Compiler::registerAntlrPpHandlerForId(
    SymbolId id, PreprocessFile::AntlrParserHandler* pp) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    delete (*itr).second;
    m_antlrPpMap.erase(itr);
    m_antlrPpMap.insert(std::make_pair(id, pp));
    return;
  }
  m_antlrPpMap.insert(std::make_pair(id, pp));
}

PreprocessFile::AntlrParserHandler* Compiler::getAntlrPpHandlerForId(
    SymbolId id) {
  std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr =
      m_antlrPpMap.find(id);
  if (itr != m_antlrPpMap.end()) {
    PreprocessFile::AntlrParserHandler* ptr = (*itr).second;
    return ptr;
  }
  return NULL;
}

bool Compiler::parseLibrariesDef_() {
  m_librarySet = new LibrarySet();
  m_configSet = new ConfigSet();
  m_design = new Design(this, m_librarySet, m_configSet);
  ParseLibraryDef* libParser = new ParseLibraryDef(
      m_commandLineParser, m_errors, m_symbolTable, m_librarySet, m_configSet);
  return libParser->parseLibrariesDefinition();
}
