2022-01-11 00:45:25 +09:00
|
|
|
open Printf
|
|
|
|
|
2022-01-13 00:54:40 +09:00
|
|
|
exception Reset_line (* used to indicate ^C is pressed *)
|
|
|
|
|
|
|
|
let version = "%%VERSION%%"
|
|
|
|
|
2022-01-11 00:45:25 +09:00
|
|
|
let error_to_string e =
|
|
|
|
try raise e with
|
2022-01-17 15:21:47 +09:00
|
|
|
| Lex.Token_not_found -> sprintf "invalid token"
|
2022-01-11 00:45:25 +09:00
|
|
|
| Parser.Expected t -> sprintf "expected %s" t
|
|
|
|
| Parser.Unexpected_token t -> sprintf "unexpected token \"%s\"" t
|
2022-01-18 16:52:33 +09:00
|
|
|
| Ast.Invalid_type t -> sprintf "invalid type %s" (Ast.Type.to_string t)
|
2022-01-19 14:17:04 +09:00
|
|
|
| Eval.No_such_variable v -> sprintf "no such variable %s" v
|
2022-01-13 00:54:40 +09:00
|
|
|
| Failure f -> sprintf "error on %s" f
|
2022-01-11 00:45:25 +09:00
|
|
|
| Division_by_zero -> "cannot divide by zero"
|
|
|
|
| _ -> raise e
|
|
|
|
|
|
|
|
let print_error e =
|
|
|
|
printf "error: %s\n" @@ error_to_string e
|
|
|
|
|
2022-01-13 00:54:40 +09:00
|
|
|
(* read-eval-print *)
|
2022-01-19 14:17:04 +09:00
|
|
|
let rep ans : unit =
|
2022-01-11 00:45:25 +09:00
|
|
|
printf "> ";
|
2022-01-10 01:31:47 +09:00
|
|
|
let line = read_line () in
|
2022-01-13 00:54:40 +09:00
|
|
|
if line = "quit" then raise Exit;
|
2022-01-19 14:17:04 +09:00
|
|
|
let v =
|
2022-01-18 16:52:33 +09:00
|
|
|
line
|
|
|
|
|> Lex.tokenize
|
|
|
|
|> Parser.parse
|
2022-01-19 14:17:04 +09:00
|
|
|
|> Eval.eval !ans
|
2022-01-18 16:52:33 +09:00
|
|
|
in
|
2022-01-19 14:17:04 +09:00
|
|
|
match v with
|
2022-01-18 16:52:33 +09:00
|
|
|
| Nop -> ()
|
2022-01-19 14:17:04 +09:00
|
|
|
| _ ->
|
|
|
|
ans := v;
|
|
|
|
printf "%s\n" @@ Ast.Value.to_string v
|
2022-01-13 00:54:40 +09:00
|
|
|
|
|
|
|
let init_repl () =
|
|
|
|
let sigintf _ = raise Reset_line in
|
|
|
|
Sys.(set_signal sigint (Signal_handle sigintf))
|
|
|
|
|
|
|
|
(* simple REPL with error handling *)
|
2022-01-19 14:17:04 +09:00
|
|
|
let rec repl ans : unit =
|
|
|
|
try rep ans; repl ans with
|
2022-01-13 00:54:40 +09:00
|
|
|
| Exit | End_of_file -> ()
|
2022-01-19 14:17:04 +09:00
|
|
|
| Reset_line -> printf "\n"; repl ans
|
|
|
|
| e -> print_error e; repl ans
|
2022-01-13 00:54:40 +09:00
|
|
|
|
|
|
|
let () =
|
2022-01-19 14:17:04 +09:00
|
|
|
let ans = ref @@ Ast.Value.Int 0 in
|
2022-01-13 00:54:40 +09:00
|
|
|
init_repl ();
|
|
|
|
printf "Configurable Evaluator %s\n" version; (* banner *)
|
2022-01-19 14:17:04 +09:00
|
|
|
repl ans
|