-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.ml
132 lines (126 loc) · 3.83 KB
/
main.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
open Lisp
open Eval
let print_trace trace =
let rec join l s =
match l with
[x] -> x
| h::t -> h^s^(join t s)
| [] -> ""
in
print_string ("\nHistory: "^(join trace " <- "))
let update_repl_histvars char newvalue =
let starstarstar = String.make 3 char in
let starstar = String.make 2 char in
let star = String.make 1 char in
begin
try
bind starstarstar (Hashtbl.find variables starstar)
with Not_found -> ()
end;
begin
try
bind starstar (Hashtbl.find variables star)
with Not_found -> ()
end;
bind star newvalue
let _ =
let deparse = ref Deparse.deparse in
let tracefun = ref ignore in
let timings = ref false in
let infiles = ref [] in
let curfile = ref None in
let prompt = ref "#> " in
Arg.parse (Arg.align [
("-camlrepr",
Arg.Unit (fun () -> deparse := Deparse.caml_repr),
" deparse as OCaml");
("-bt", Arg.Unit
(fun () -> Eval.dotrace := true; tracefun := print_trace),
" print backtrace on errors");
("-maxdepth", Arg.Set_int Eval.max_depth, " set max eval depth");
("-timings", Arg.Set timings, " print timings");
("-noprompt", Arg.Unit (fun () -> prompt := ""), " disable prompt")])
(fun arg -> infiles := arg::!infiles) "minilisp";
infiles := List.rev !infiles;
let interactive = !infiles = [] in
let repl () =
if interactive then
begin
print_string !prompt;
flush stdout;
end;
begin
let input =
Reader.read_channel (
if interactive then
stdin
else begin
match !curfile with
Some file -> file
| None ->
begin
let fn = List.hd !infiles in
let file = open_in fn in
curfile := Some file;
file
end
end) in
let start_time = Unix.gettimeofday() in
begin
Eval.depth := 0;
Eval.entry_time := Sys.time();
Eval.trace := [];
bind "-" input;
let result = eval input in
update_repl_histvars '+' input;
update_repl_histvars '*' result;
print_string (!deparse result)
end;
print_newline();
(if !timings then
Printf.printf "(%.5fs)\n" (
Unix.gettimeofday() -. start_time));
end
in
bind "t" (Atom(Symbol "t"));
Functions.setup();
defun "show-scope" (Camlfun lisp_show_scope);
defun "load-library" (Camlfun lisp_load_library);
while true do
begin
try
repl ()
with Lexer.Eof ->
begin
Reader.close_channel();
curfile := None;
if !infiles = [] then exit 0;
infiles := List.tl !infiles;
if !infiles = [] then exit 0
end
| Lisp.Void_variable v ->
print_string ("Void variable '"^v^"'"); !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| Lisp.Void_function f ->
print_string ("Void function '"^f^"'"); !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| Lisp.Eval_error msg ->
print_string ("Evaluation stopped: "^msg); !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| Lisp.Type_mismatch ->
print_string "Type mismatch somewhere"; !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| Lisp.Argument_mismatch ->
print_string "Argument mismatch"; !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| Dynlink.Error e ->
print_string (Dynlink.error_message e); !tracefun !Eval.trace;
print_newline(); Reader.close_channel()
| any_other_exception ->
begin
print_string ("Uncaught OCaml exception: "^
(Printexc.to_string any_other_exception)^"\n");
Reader.close_channel()
end
end
done