ce/main.ml

57 lines
1.5 KiB
OCaml

open Printf
exception Reset_line (* used to indicate ^C is pressed *)
let version = "%%VERSION%%"
let error_to_string e =
try raise e with
| Lex.Token_not_found -> sprintf "invalid token"
| Lex.Unclosed_quote -> sprintf "string not closed"
| Parser.Expected t -> sprintf "expected %s" t
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
| Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string t)
| Eval.No_such_variable v -> sprintf "no such variable %s" v
| Failure f -> sprintf "error on %s" f
| Division_by_zero -> "cannot divide by zero"
| _ -> raise e
let print_error e =
printf "error: %s\n" @@ error_to_string e
let vars = Hashtbl.create 100
(* read-eval-print *)
let rep vars : unit =
printf "> ";
let line = read_line () in
if line = "quit" then raise Exit;
let v =
line
|> Lex.tokenize
|> Parser.parse
|> Eval.eval vars
in
match v with
| Nop -> ()
| _ ->
Hashtbl.replace vars "ans" v;
printf "%s\n" @@ Ast.Value.to_string v
let init_repl () =
Hashtbl.replace vars "ans" (Ast.Value.Int 0);
(* treat Ctrl-C as to reset line *)
let sigintf _ = raise Reset_line in
Sys.(set_signal sigint (Signal_handle sigintf))
(* simple REPL with error handling *)
let rec repl vars : unit =
try rep vars; repl vars with
| Exit | End_of_file -> ()
| Reset_line -> printf "\n"; repl vars
| e -> print_error e; repl vars
let () =
init_repl ();
printf "Configurable Evaluator %s\n" version; (* banner *)
repl vars