(*
File: VSCODE.ML
Description: Top-level of VSCOde Compiler, scans & parses input,
   checks resulting AST, generates LLVM IR, and dumps the module
*)

module StringMap = Map.Make(String)

type action = Ast | LLVM_IR | Compile

let _ =
  let action = ref Compile in
  let set_action a () = action := a in
  let speclist = [
    ("-a", Arg.Unit (set_action Ast), "Print the AST");
    ("-l", Arg.Unit (set_action LLVM_IR), "Print the generated LLVM IR");
    ("-c", Arg.Unit (set_action Compile),
      "Check and print the generated LLVM IR (default)");
  ] in
  let usage_msg = "usage: ./calc.native [-a|-l|-c] [file.vsc]" in
  let channel = ref stdin in
  Arg.parse speclist (fun filename -> channel := open_in filename) usage_msg;
  try let lexbuf = Lexing.from_channel !channel in
      let ast = Parser.program Scanner.token lexbuf in
      try let _ = Semant.check ast in ignore(Semant.check ast);
        match !action with
          Ast -> print_string("AST: \n") ; print_string (Ast.string_of_program ast)
        | LLVM_IR -> print_string (Llvm.string_of_llmodule (Codegen.translate ast))
        | Compile ->
          try let m = Codegen.translate ast in
            Llvm_analysis.assert_valid_module m;
            print_string (Llvm.string_of_llmodule m)
          with e -> print_string ("Error with codegen: \n" ^ (Printexc.to_string e) ^ "\n");
      with e -> print_string ("Error with semant 😡👺: \n" ^ (Printexc.to_string e) ^ "\n");
  with _ -> Printf.printf "Error with parsing 🧐\n";
