#include <exception>
#include <iostream>
#include <stdexcept>

#include "frontend/AntlrDriver.h"
#include "frontend/SyntaxTreePrinter.h"
#include "ir/IR.h"
#include "irgen/IRGen.h"
#include "mir/MIR.h"
#include "sem/Sema.h"
#include "utils/CLI.h"
#include "utils/Log.h"

int main(int argc, char** argv) {
  try {
    auto opts = ParseCLI(argc, argv);
    if (opts.show_help) {
      PrintHelp(std::cout);
      return 0;
    }

    auto antlr = ParseFileWithAntlr(opts.input);
    bool need_blank_line = false;
    if (opts.emit_parse_tree) {
      PrintSyntaxTree(antlr.tree, antlr.parser.get(), std::cout);
      need_blank_line = true;
    }

    auto* comp_unit = dynamic_cast<SysYParser::CompUnitContext*>(antlr.tree);
    if (!comp_unit) {
      throw std::runtime_error(FormatError("main", "语法树根节点不是 compUnit"));
    }
    auto sema = RunSema(*comp_unit);

    auto module = GenerateIR(*comp_unit, sema);
    if (opts.emit_ir) {
      ir::IRPrinter printer;
      if (need_blank_line) {
        std::cout << "\n";
      }
      printer.Print(*module, std::cout);
      need_blank_line = true;
    }

    if (opts.emit_asm) {
      auto machine_func = mir::LowerToMIR(*module);
      mir::RunRegAlloc(*machine_func);
      mir::RunFrameLowering(*machine_func);
      if (need_blank_line) {
        std::cout << "\n";
      }
      mir::PrintAsm(*machine_func, std::cout);
    }
  } catch (const std::exception& ex) {
    PrintException(std::cerr, ex);
    return 1;
  }
  return 0;
}
