main.ml 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. open Lexing
  2. open Printf
  3. open Ast
  4. (* Compile infile to assembly code
  5. * in_channel -> int -> repr *)
  6. let compile infile verbose =
  7. let rec run_phases ir = function
  8. | [] -> ir
  9. | h::t -> run_phases (h ir) t
  10. in
  11. run_phases (Inputfile (infile, verbose)) [
  12. Parse.phase;
  13. Print.phase;
  14. Desug.phase;
  15. Print.phase;
  16. (*
  17. Context_analysis.phase;
  18. Print.phase;
  19. Typecheck.phase;
  20. Extern_vars.phase;
  21. Dim_reduce.phase;
  22. Bool_op.phase;
  23. Assemble.phase;
  24. Peephole.phase;
  25. Print.phase;
  26. *)
  27. ]
  28. let rec repeat str n =
  29. if n = 0 then "" else str ^ (repeat str (n - 1))
  30. let print_fancy_error msg loc verbose =
  31. let (fname, ystart, yend, xstart, xend) = loc in
  32. let line_s = if yend > ystart
  33. then sprintf "lines %d-%d" ystart yend
  34. else sprintf "line %d" ystart
  35. in
  36. let char_s = if xend > xstart || yend > ystart
  37. then sprintf "characters %d-%d" xstart xend
  38. else sprintf "character %d" xstart
  39. in
  40. eprintf "File \"%s\", %s, %s:\n" fname line_s char_s;
  41. eprintf "Error: %s\n" msg;
  42. if verbose >= 2 then (
  43. let file = open_in fname in
  44. (* skip lines until the first matched line *)
  45. for i = 1 to ystart - 1 do input_line file done;
  46. (* for each line in `loc`, print the source line with an underline *)
  47. for l = ystart to yend do
  48. let line = input_line file in
  49. let linewidth = String.length line in
  50. let left = if l = ystart then xstart else 1 in
  51. let right = if l = yend then xend else linewidth in
  52. if linewidth > 0 then (
  53. prerr_endline line;
  54. for i = 1 to left - 1 do prerr_char ' ' done;
  55. for i = left to right do prerr_char '^' done;
  56. prerr_endline ""
  57. )
  58. done
  59. )
  60. (* Main function, returns exit status
  61. * () -> int *)
  62. let main () =
  63. let filename = ref None in
  64. let verbose = ref 2 in
  65. let args = [
  66. ("-v", Arg.Int (fun i -> verbose := i), "Set verbosity")
  67. ] in
  68. let usage = "Usage: " ^ Sys.argv.(0) ^ " [ -v VERBOSITY ] FILE" in
  69. try
  70. Arg.parse args (fun s -> filename := Some s) usage;
  71. let _ = compile !filename !verbose in
  72. 0
  73. with
  74. | CompileError msg ->
  75. prerr_endline ("Error: " ^ msg);
  76. 1
  77. | LocError (msg, loc) ->
  78. print_fancy_error msg loc !verbose;
  79. 1
  80. let _ = exit (main ())