-
Notifications
You must be signed in to change notification settings - Fork 78
/
inline_load.ml
100 lines (88 loc) · 4.17 KB
/
inline_load.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
(* ========================================================================= *)
(* HOL LIGHT *)
(* *)
(* Modern OCaml version of the HOL theorem prover *)
(* *)
(* John Harrison *)
(* *)
(* (c) Copyright, University of Cambridge 1998 *)
(* (c) Copyright, John Harrison 1998-2024 *)
(* (c) Copyright, Juneyoung Lee 2024 *)
(* ========================================================================= *)
let argn = Array.length Sys.argv;;
if argn < 3 || argn > 4 then
let _ = Printf.eprintf "inline_load.ml <input.ml> <output.ml> [-omit-prelude]\n" in
let _ = Printf.eprintf " -omit-prelude: omit 'open Hol_lib;;' and 'open Hol_loader;;'.\n" in
exit 1;;
try
let v = Sys.getenv "HOLLIGHT_DIR" in
if v = "" then Printf.printf "Warning: HOLLIGHT_DIR is not set\n%!"
with Not_found -> Printf.printf "Warning: HOLLIGHT_DIR is not set\n%!";;
let filename = Sys.argv.(1);;
let fout = open_out (Sys.argv.(2));;
let omit_prelude = argn >= 4 && Sys.argv.(3) = "-omit-prelude";;
if not omit_prelude then
Printf.fprintf fout "open Hol_lib;;\nopen Hol_loader;;\n";;
#use "hol_loader.ml";;
let parse_load_statement fnname stmt: (string * string) option =
let stmt = String.trim stmt in
if not (String.starts_with ~prefix:fnname stmt) then None else
let n = String.length fnname in
let stmt = String.trim (String.sub stmt n (String.length stmt - n)) in
if not (stmt.[0] = '"') then None else
let stmt = String.sub stmt 1 (String.length stmt - 1) in
let idx = String.index stmt '"' in
if idx = -1 then None else
let path = String.sub stmt 0 idx in
let stmt = String.sub stmt (idx + 1) (String.length stmt - idx - 1) in
let stmt = String.trim stmt in
if not (String.starts_with ~prefix:";;" stmt) then None else
let stmt = String.sub stmt 2 (String.length stmt - 2) in
Some (path,stmt);;
let strings_of_file filename =
let fd =
try open_in filename
with Sys_error _ -> failwith("strings_of_file: can't open "^filename) in
let rec suck_lines acc =
let l = try [input_line fd] with End_of_file -> [] in
if l = [] then List.rev acc else suck_lines(List.hd l::acc) in
let data = suck_lines [] in
(close_in fd; data);;
file_loader := fun filename ->
let open Printf in
fprintf fout "(* %s *)\n" filename;
let lines = strings_of_file filename in
let fail_if_nonexistent f x = try f x with _ -> failwith x in
List.iter
(fun line ->
match parse_load_statement "loadt" line with
| Some (path,line') -> fail_if_nonexistent loadt path; fprintf fout "%s\n" line' | None ->
(match parse_load_statement "loads" line with
| Some (path,line') -> begin
if path = "update_database.ml"
then Printf.printf "Warning: 'loads \"update_database.ml\";;' is omitted\n"
else (fail_if_nonexistent loads path; fprintf fout "%s\n" line')
end
| None ->
(match parse_load_statement "needs" line with
| Some (path,line') -> fail_if_nonexistent needs path; fprintf fout "%s\n" line'
| None -> fprintf fout "%s\n" line (* no linebreak needed! *))))
lines;
(* add digest *)
let digest_str = Digest.file filename in
let digest = Bytes.of_string digest_str in
let the_str = ref "" in
Bytes.iter (fun c ->
let i = Char.code c in
if !the_str = ""
then the_str := string_of_int i
else the_str := !the_str ^ "; " ^ (string_of_int i))
digest;
fprintf fout "(* update digest *)\n";
fprintf fout "loaded_files := \n";
fprintf fout " let digest_bytes = [|%s|] in\n" !the_str;
fprintf fout " let digest = Bytes.init (Array.length digest_bytes) (fun i -> Char.chr digest_bytes.(i)) in\n";
fprintf fout " (\"%s\", Bytes.to_string digest)::!loaded_files;;\n\n" (Filename.basename filename);
true;;
loadt filename;;
close_out fout;;