/*
 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.hpp"
#include "../ErrorReporting/ErrorContainer.h"
#include "SymbolTable.h"
#include "CompilationUnit.h"
#include "PreprocessFile.h"
#include "CompilationUnit.h"
#include "CompileSourceFile.h"
#include "Compiler.h"
#include "CheckCompile.h"
#include "antlr4-runtime.h"
#include "../DesignCompile/CompileDesign.h"
#include "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 "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 ();
}


