ce/main.ml

79 lines
2.2 KiB
OCaml

open Printf
open Eval
let version = "%%VERSION%%"
let debug = ref false
let error_to_string e =
try raise e with
| Lex.Invalid_character (col, c) ->
sprintf "invalid character %c at col %d" c col
| Lex.Expected (col, c) -> sprintf "expected %c at col %d" c col
| Parser.Fatal e -> raise e
| Parser.End_of_tokens -> "expression ended abruptly"
| Parser.Expected (col, t) -> sprintf "expected %s at col %d" t col
| Parser.Unexpected_token (col, t) ->
sprintf "unexpected token \"%s\" at col %d" t col
| Type.Invalid t -> sprintf "invalid type %s" (Type.to_string t)
| Eval.Unbound v -> sprintf "unbound value %s" v
| Eval.No_such_method (m, t) ->
sprintf "no such method %s matching type %s" m (Type.to_string t)
| 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 stdlib = [
"sin"; "cos"; "tan";
"deg"; "rad";
"get_op_pre"; "set_op_pre";
"get_op_assoc"; "set_op_assoc";
"print"; "println";
]
|> List.to_seq
|> Seq.map (fun v -> v, External v)
(* global environment *)
let g =
let g = Hashtbl.create 100 in
Hashtbl.add_seq g stdlib;
g
(* read-eval-print *)
let rep () : unit =
printf "> ";
let line = read_line () in
if line = "quit" then raise Exit;
let ast = line |> Lex.tokenize |> Parser.parse in
if !debug then Ast.print ast;
let var, v = Eval.eval_top g ast in
Hashtbl.replace g "ans" v;
printf "%s: %s = %s\n"
var (Type.to_string @@ Value.typeof v) (Value.to_string v)
exception Reset_line (* used to indicate ^C is pressed *)
let init_repl () =
(* treat Ctrl-C as to reset line *)
let reset_line _ = raise Reset_line in
Sys.(set_signal sigint (Signal_handle reset_line))
(* simple REPL with error handling *)
let rec repl () : unit =
try rep (); repl () with
| Exit | End_of_file (* Ctrl-D *) -> ()
| Noop -> repl ()
| Reset_line -> printf "\n"; repl ()
| e -> print_error e; repl ()
let speclist = [
"--debug", Arg.Set debug, "print debug infos";
]
let () =
Arg.parse speclist (fun _ -> ()) "";
init_repl ();
printf "Configurable Evaluator %s\n" version; (* banner *)
repl ()