ce/main.ml

59 lines
1.5 KiB
OCaml
Raw Normal View History

2022-01-11 00:45:25 +09:00
open Printf
2022-01-13 00:54:40 +09:00
let version = "%%VERSION%%"
2022-01-11 00:45:25 +09:00
let error_to_string e =
try raise e with
2022-01-28 01:52:57 +09:00
| Lex.Invalid_character c -> sprintf "invalid character %c" c
| Lex.Expected c -> sprintf "expected %c" c
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-29 20:01:48 +09:00
| Eval.No_such_function f -> sprintf "no such function \"%s\"" f
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-02-01 02:13:14 +09:00
let g = Env.init_global ()
2022-01-20 01:35:18 +09:00
2022-01-13 00:54:40 +09:00
(* read-eval-print *)
2022-02-01 02:13:14 +09:00
let rep env : 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-02-01 02:13:14 +09:00
|> Eval.eval env
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
| _ ->
2022-02-01 02:13:14 +09:00
Env.set env "ans" v;
2022-01-19 14:17:04 +09:00
printf "%s\n" @@ Ast.Value.to_string v
2022-01-13 00:54:40 +09:00
2022-01-28 01:52:57 +09:00
exception Reset_line (* used to indicate ^C is pressed *)
2022-01-13 00:54:40 +09:00
let init_repl () =
2022-02-01 02:13:14 +09:00
Env.set g "ans" (Ast.Value.Int 0);
2022-01-20 01:35:18 +09:00
(* treat Ctrl-C as to reset line *)
2022-01-28 01:52:57 +09:00
let reset_line _ = raise Reset_line in
Sys.(set_signal sigint (Signal_handle reset_line))
2022-01-13 00:54:40 +09:00
(* simple REPL with error handling *)
2022-02-01 02:13:14 +09:00
let rec repl env : unit =
try rep env; repl env with
2022-01-28 01:52:57 +09:00
| Exit | End_of_file (* Ctrl-D *) -> ()
2022-02-01 02:13:14 +09:00
| Reset_line -> printf "\n"; repl env
| e -> print_error e; repl env
2022-01-13 00:54:40 +09:00
let () =
init_repl ();
printf "Configurable Evaluator %s\n" version; (* banner *)
2022-02-01 02:13:14 +09:00
repl g