diff --git a/src/main.ml b/src/main.ml index e591aa4..6c1f250 100644 --- a/src/main.ml +++ b/src/main.ml @@ -1,12 +1,86 @@ open Ast -let _ = - try - let oi = open_in "test.node" in - let lexbuf = Lexing.from_channel oi in - let result = Parser.main Lexer.token lexbuf in - Format.printf "%a" Pp.pp_prog result; - close_in oi - with Lexer.Lexing_error s -> - Format.printf "Code d'erreur:\n\t%s\n\n" s +let exit_error (s: string) : unit = + Format.printf "\n\tCritical error: %s\n\n" s + +let print_debug d s = + if d then Format.printf "\x1b[31;01;04mDebug :\x1b[0m %s\n" s else () + +let print_verbose v s = + if v then Format.printf "\x1b[33;01;04mStatus:\x1b[0m %s\n" s else () + +(** The following function should check whether the program is well-formed, by + * induction: + * - for any applications of the form (n, arg1, ..., argn) + * + n exists + * + n waits n arguments + * + arg1, ..., argn sont bien formés + * - The expressions are well-typed + * - The equations are well typed + * - The output is set + *) +let check_well_formedness (a: p_prog) = Some a +let check_dependencies (a: p_prog) = Some a +let simplify_prog (a: p_prog) = Some a + +let run verbose debug (passes: (p_prog -> p_prog option) list) + = verbose "kjlksjf" + +let _ = + (** Usage and argument parsing. *) + let default_passes = ["check_form"; "check_dependencies"; "simplify_prog"] in + let usage_msg = "Usage: main [-passes p1,...,pn] [-ast] [-verbose] [-debug] [-o output_file] source_file" in + let verbose = ref false in + let debug = ref false in + let ppast = ref false in + let passes = ref [] in + let source_file = ref "" in + let output_file = ref "out.c" in + let anon_fun filename = source_file := filename in + let speclist = + [ + ("-ast", Arg.Set ppast, "Only print the AST of the input file"); + ("-verbose", Arg.Set verbose, "Output some debug information"); + ("-debug", Arg.Set debug, "Output a lot of debug information"); + ("-p", Arg.String (fun s -> passes := s :: !passes), + "Add a pass to the compilation process"); + ("-o", Arg.Set_string output_file, "Output file (defaults to [out.c])"); + ] in + Arg.parse speclist anon_fun usage_msg ; + if !source_file = "" then exit_error "No source file specified" else + if !passes = [] then passes := default_passes; + let print_verbose = print_verbose !verbose in + let print_debug = print_debug !verbose in + + (** Definition of the passes table *) + let passes_table : (string, p_prog -> p_prog option) Hashtbl.t = Hashtbl.create 100 in + List.iter (fun (s, k) -> Hashtbl.add passes_table s k) + [ + ("check_form", check_well_formedness); + ("check_dependencies", check_dependencies); + ("simplify_prog", simplify_prog); + ]; + + (** Main functionnalyty below *) + print_verbose "Parsing the source file..."; + let ast = + try + begin + let inchan = open_in !source_file in + let res = Parser.main Lexer.token (Lexing.from_channel inchan) in + close_in inchan; res + end + with Lexer.Lexing_error s -> + exit_error (Format.sprintf "Code d'erreur:\n\t%s\n\n" s); exit 0 in + + if !ppast then Format.printf "%a" Pp.pp_prog ast + else + let passes = List.map (fun (pass: string) -> + match Hashtbl.find_opt passes_table pass with + | None -> + (exit_error (Format.sprintf "The pass %s does not exist." pass); exit 0) + | Some f -> + (print_debug ("The pass "^pass^" has been selected."); f)) !passes in + run print_verbose print_debug passes; + print_verbose "End of the program, exiting gracefully."