// see License.txt for copyright and terms of use

// Just the main() function.

#include "prcheck.h"
#include "prcheck_cmd.h"
#include "prcheck_global.h"
#include "oink.gr.gen.h"        // CCParse_Oink
#include "trace.h"
#include "oink_util.h"
#include <sys/time.h>

void printTime(const char *str, const struct timeval &from, struct timeval till) {
  till.tv_sec -= from.tv_sec;
  if (from.tv_usec < till.tv_usec) {
    till.tv_usec -= from.tv_usec;
  } else {
    till.tv_sec--;
    till.tv_usec += 1000000 - from.tv_usec;
  }
  cerr << str << ": " << till.tv_sec << "s " << till.tv_usec << "us" << endl;
}
int main(int argc, char **argv) {
  traceAddSys("permissive");
  traceAddFromEnvVar();
  tFac = new TypeFactory_O;
  vFac = new ValueFactory;
  astPrinter = new ASTPrinter_O;
  oinkCmd = prcheckCmd = new PrcheckCmd;
  ExitCode code = NORMAL_ExitCode;
  Prcheck m;
  m.typePrinter = &typePrinterOink;
  try {
    m.init_stage(argc, argv);
    CCParse_Oink ccParse(globalStrTable, globalLang);
    m.parseUserActions = &ccParse;
    m.parseEnv = &ccParse;
    struct timeval from;
    gettimeofday(&from, NULL);
    m.parse_stage();
    struct timeval parseT;
    gettimeofday(&parseT, NULL);
    m.typecheck_stage();
    struct timeval typecheckT;
    gettimeofday(&typecheckT, NULL);
    m.elaborate_stage();
    struct timeval elaborateT;
    gettimeofday(&elaborateT, NULL);
    //m.markRealVars_stage();
    struct timeval markT;
    gettimeofday(&markT, NULL);
    //m.filter_stage();
    struct timeval filterT;
    gettimeofday(&filterT, NULL);
    //m.prettyPrint_stage();
    struct timeval pprintT;
    gettimeofday(&pprintT, NULL);
    m.check(prcheckCmd->debug);
    struct timeval tarasT;
    gettimeofday(&tarasT, NULL);
    if (prcheckCmd->debug) {
      printTime("Parse", from, parseT);
      printTime("Typecheck", parseT, typecheckT);
      printTime("Elaborate", typecheckT, elaborateT);
      printTime("Mark", elaborateT, markT);
      printTime("Filter", markT, filterT);
      printTime("Pretty Print", filterT, pprintT);
      printTime("Taras", pprintT, tarasT);
    }
  } catch (xBase &e) {
    cerr << e << endl;
    code = INTERNALERROR_ExitCode;
    if (UserError *ue = dynamic_cast<UserError*>(&e)) code = ue->exitCode;
  }
  delete prcheckCmd;
  return code;
}
