Skip to content

Commit 3424655

Browse files
committed
Fix a crash in loading update_database.ml
This fixes a crash in loading update_database.ml after jrh13#74. The newly written `update_database.ml` is largely based on @chetmurthy's work: https://github.com/chetmurthy/hol-light/blob/99d017c087ee938929d9d40a5fe75022bbee0257/update_database_6.ml ... with the following modifications to address updates in OCaml's Types module as well as crashes when deprecated stdlib modules are to be loaded: ``` diff --git a/update_database_4.14.ml b/update_database_4.14.ml index 79bc6fc..c2b69d4 100755 --- a/update_database_4.14.ml +++ b/update_database_4.14.ml @@ -17,9 +17,11 @@ open Types (* If the given type is simple return its name, otherwise None. *) let rec get_simple_type = function - | Tlink { desc = Tconstr (Pident p,[],_) } -> Some (Ident.name p) + | Tlink texpr -> + (match get_desc texpr with + | Tconstr (Pident p,[],_) -> Some (Ident.name p) + | d -> get_simple_type d) | Tconstr (Path.Pident p, [], _) -> Some (Ident.name p) - | Tlink { desc = d } -> get_simple_type d | _ -> None;; (* Execute any OCaml expression given as a string. *) @@ -45,15 +47,22 @@ let lid_cons lidopt id = | Some li -> Longident.Ldot(li, id) let it_val_1 lidopt s p vd acc = - if (Some "thm") = Ocaml_typing.get_simple_type vd.Types.val_type.desc then + if (Some "thm") = Ocaml_typing.get_simple_type (get_desc vd.Types.val_type) then (lid_cons lidopt s)::acc else acc let it_mod_1 lidopt s p md acc = (lid_cons lidopt s)::acc let enum0 lidopt = - let vl = Env.fold_values (it_val_1 lidopt) lidopt !Toploop.toplevel_env [] in - let ml = Env.fold_modules (it_mod_1 lidopt) lidopt !Toploop.toplevel_env [] in - (vl, ml) + try + let vl = Env.fold_values (it_val_1 lidopt) lidopt !Toploop.toplevel_env [] in + let ml = Env.fold_modules (it_mod_1 lidopt) lidopt !Toploop.toplevel_env [] in + (vl, ml) + with Not_found -> + (* Looking for (Longident.Lident "Stream") raises Not_found. + Stream is a deprecated alias module of "Stdlib.Stream", and the camlp-streams + package that is used by pa_hol_syntax redefines Stream, which seems to + confuse Env.fold_values and Env.fold_modules. *) + ([], []) let rec enum1 lidopt acc = match enum0 lidopt with ``` I checked that the updated `update_database.ml` works well by testing with the `search` commands that are exhibited at the manual from `help "search"`.
1 parent cc46ff3 commit 3424655

File tree

3 files changed

+164
-25
lines changed

3 files changed

+164
-25
lines changed

Makefile

+23-25
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ default: update_database.ml pa_j.cmo;
4242

4343
# Choose an appropriate "update_database.ml" file
4444

45-
update_database.ml:; cp update_database_${OCAML_UNARY_VERSION}.ml update_database.ml
45+
update_database.ml:; if test ${OCAML_VERSION} = "4.14" ; \
46+
then cp update_database_4.14.ml update_database.ml ; \
47+
else cp update_database_${OCAML_UNARY_VERSION}.ml update_database.ml ; \
48+
fi
49+
4650

4751
# Build the camlp4 syntax extension file (camlp5 for OCaml >= 3.10)
4852

4953
pa_j.cmo: pa_j.ml; if test ${OCAML_BINARY_VERSION} = "3.0" ; \
5054
then ocamlc -c -pp "camlp4r pa_extend.cmo q_MLast.cmo" -I `camlp4 -where` pa_j.ml ; \
51-
else if test ${OCAML_BINARY_VERSION} = "3.1" -o ${OCAML_VERSION} = "4.00" -o ${OCAML_VERSION} = "4.01" -o ${OCAML_VERSION} = "4.02" -o ${OCAML_VERSION} = "4.03" -o ${OCAML_VERSION} = "4.04" -o ${OCAML_VERSION} = "4.05" ; \
52-
then ocamlc -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo" -I `camlp5 -where` pa_j.ml ; \
53-
else ocamlc -safe-string -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo" -I `camlp5 -where` -I `ocamlfind query camlp-streams` pa_j.ml ; \
54-
fi \
55+
elif test ${OCAML_BINARY_VERSION} = "3.1" -o ${OCAML_VERSION} = "4.00" -o ${OCAML_VERSION} = "4.01" -o ${OCAML_VERSION} = "4.02" -o ${OCAML_VERSION} = "4.03" -o ${OCAML_VERSION} = "4.04" -o ${OCAML_VERSION} = "4.05" ; \
56+
then ocamlc -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo" -I `camlp5 -where` pa_j.ml ; \
57+
else ocamlc -safe-string -c -pp "camlp5r pa_lexer.cmo pa_extend.cmo q_MLast.cmo" -I `camlp5 -where` -I `ocamlfind query camlp-streams` pa_j.ml ; \
5558
fi
5659

5760
# Choose an appropriate camlp4 or camlp5 syntax extension.
@@ -64,28 +67,23 @@ pa_j.cmo: pa_j.ml; if test ${OCAML_BINARY_VERSION} = "3.0" ; \
6467
# based on the camlp5 version. The main distinction is < 6.00 and >= 6.00, but
6568
# there are some other incompatibilities, unfortunately.
6669

67-
pa_j.ml: pa_j_3.07.ml pa_j_3.08.ml pa_j_3.09.ml pa_j_3.1x_5.xx.ml pa_j_3.1x_6.xx.ml pa_j_8.xx.ml; \
70+
pa_j.ml: pa_j_3.07.ml pa_j_3.08.ml pa_j_3.09.ml pa_j_3.1x_5.xx.ml pa_j_3.1x_6.xx.ml pa_j_4.xx_8.00.ml; \
6871
if test ${OCAML_BINARY_VERSION} = "3.0" ; \
6972
then cp pa_j_${OCAML_VERSION}.ml pa_j.ml ; \
70-
else if test ${CAMLP5_BINARY_VERSION} = "8" ; \
71-
then cp pa_j_8.xx.ml pa_j.ml; \
72-
else if test ${CAMLP5_BINARY_VERSION} = "7" ; \
73-
then if test ${CAMLP5_VERSION} = "7.01" -o ${CAMLP5_VERSION} = "7.02" -o ${CAMLP5_VERSION} = "7.03" -o ${CAMLP5_VERSION} = "7.04" -o ${CAMLP5_VERSION} = "7.05" -o ${CAMLP5_VERSION} = "7.06" ; \
74-
then cp pa_j_4.xx_7.06.ml pa_j.ml; \
75-
else cp pa_j_4.xx_7.xx.ml pa_j.ml; \
76-
fi \
77-
else if test ${CAMLP5_VERSION} = "6.02.1" ; \
78-
then cp pa_j_3.1x_6.02.1.ml pa_j.ml; \
79-
else if test ${CAMLP5_VERSION} = "6.02.2" -o ${CAMLP5_VERSION} = "6.02.3" -o ${CAMLP5_VERSION} = "6.03" -o ${CAMLP5_VERSION} = "6.04" -o ${CAMLP5_VERSION} = "6.05" -o ${CAMLP5_VERSION} = "6.06" ; \
80-
then cp pa_j_3.1x_6.02.2.ml pa_j.ml; \
81-
else if test ${CAMLP5_VERSION} = "6.06" -o ${CAMLP5_VERSION} = "6.07" -o ${CAMLP5_VERSION} = "6.08" -o ${CAMLP5_VERSION} = "6.09" -o ${CAMLP5_VERSION} = "6.10" -o ${CAMLP5_VERSION} = "6.11" -o ${CAMLP5_VERSION} = "6.12" -o ${CAMLP5_VERSION} = "6.13" -o ${CAMLP5_VERSION} = "6.14" -o ${CAMLP5_VERSION} = "6.15" -o ${CAMLP5_VERSION} = "6.16" -o ${CAMLP5_VERSION} = "6.17" ; \
82-
then cp pa_j_3.1x_6.11.ml pa_j.ml; \
83-
else cp pa_j_3.1x_${CAMLP5_BINARY_VERSION}.xx.ml pa_j.ml; \
84-
fi \
85-
fi \
86-
fi \
87-
fi \
88-
fi \
73+
elif test ${CAMLP5_BINARY_VERSION} = "8" ; \
74+
then cp pa_j_4.xx_8.00.ml pa_j.ml; \
75+
elif test ${CAMLP5_BINARY_VERSION} = "7" ; \
76+
then if test ${CAMLP5_VERSION} = "7.01" -o ${CAMLP5_VERSION} = "7.02" -o ${CAMLP5_VERSION} = "7.03" -o ${CAMLP5_VERSION} = "7.04" -o ${CAMLP5_VERSION} = "7.05" -o ${CAMLP5_VERSION} = "7.06" ; \
77+
then cp pa_j_4.xx_7.06.ml pa_j.ml; \
78+
else cp pa_j_4.xx_7.xx.ml pa_j.ml; \
79+
fi \
80+
elif test ${CAMLP5_VERSION} = "6.02.1" ; \
81+
then cp pa_j_3.1x_6.02.1.ml pa_j.ml; \
82+
elif test ${CAMLP5_VERSION} = "6.02.2" -o ${CAMLP5_VERSION} = "6.02.3" -o ${CAMLP5_VERSION} = "6.03" -o ${CAMLP5_VERSION} = "6.04" -o ${CAMLP5_VERSION} = "6.05" -o ${CAMLP5_VERSION} = "6.06" ; \
83+
then cp pa_j_3.1x_6.02.2.ml pa_j.ml; \
84+
elif test ${CAMLP5_VERSION} = "6.06" -o ${CAMLP5_VERSION} = "6.07" -o ${CAMLP5_VERSION} = "6.08" -o ${CAMLP5_VERSION} = "6.09" -o ${CAMLP5_VERSION} = "6.10" -o ${CAMLP5_VERSION} = "6.11" -o ${CAMLP5_VERSION} = "6.12" -o ${CAMLP5_VERSION} = "6.13" -o ${CAMLP5_VERSION} = "6.14" -o ${CAMLP5_VERSION} = "6.15" -o ${CAMLP5_VERSION} = "6.16" -o ${CAMLP5_VERSION} = "6.17" ; \
85+
then cp pa_j_3.1x_6.11.ml pa_j.ml; \
86+
else cp pa_j_3.1x_${CAMLP5_BINARY_VERSION}.xx.ml pa_j.ml; \
8987
fi
9088

9189
# Build a standalone hol image called "hol" (needs Linux and ckpt program)

pa_j_8.xx.ml pa_j_4.xx_8.00.ml

File renamed without changes.

update_database_4.14.ml

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
(* ========================================================================= *)
2+
(* Create search database from OCaml / modify search database dynamically. *)
3+
(* *)
4+
(* This file assigns to "theorems", which is a list of name-theorem pairs. *)
5+
(* The core system already has such a database set up. Use this file if you *)
6+
(* want to update the database beyond the core, so you can search it. *)
7+
(* *)
8+
(* The trickery to get at the OCaml environment is due to Roland Zumkeller *)
9+
(* and Michael Farber. It works by copying some internal data structures and *)
10+
(* casting into the copy using Obj.magic. *)
11+
(* ========================================================================= *)
12+
13+
module Ocaml_typing = struct
14+
15+
open Types
16+
17+
(* If the given type is simple return its name, otherwise None. *)
18+
19+
let rec get_simple_type = function
20+
| Tlink texpr ->
21+
(match get_desc texpr with
22+
| Tconstr (Pident p,[],_) -> Some (Ident.name p)
23+
| d -> get_simple_type d)
24+
| Tconstr (Path.Pident p, [], _) -> Some (Ident.name p)
25+
| _ -> None;;
26+
27+
(* Execute any OCaml expression given as a string. *)
28+
29+
let exec = ignore o Toploop.execute_phrase false Format.std_formatter
30+
o !Toploop.parse_toplevel_phrase o Lexing.from_string
31+
32+
(* Evaluate any OCaml expression given as a string. *)
33+
34+
let eval n =
35+
exec ("let buf__ = ( " ^ n ^ " );;");
36+
Obj.magic (Toploop.getvalue "buf__")
37+
38+
(* Register all theorems added since the last update. *)
39+
end
40+
41+
module Lookuptheorems = struct
42+
open Types
43+
44+
let lid_cons lidopt id =
45+
match lidopt with
46+
None -> Longident.Lident id
47+
| Some li -> Longident.Ldot(li, id)
48+
49+
let it_val_1 lidopt s p vd acc =
50+
if (Some "thm") = Ocaml_typing.get_simple_type (get_desc vd.Types.val_type) then
51+
(lid_cons lidopt s)::acc else acc
52+
53+
let it_mod_1 lidopt s p md acc = (lid_cons lidopt s)::acc
54+
55+
let enum0 lidopt =
56+
try
57+
let vl = Env.fold_values (it_val_1 lidopt) lidopt !Toploop.toplevel_env [] in
58+
let ml = Env.fold_modules (it_mod_1 lidopt) lidopt !Toploop.toplevel_env [] in
59+
(vl, ml)
60+
with Not_found ->
61+
(* Looking for (Longident.Lident "Stream") raises Not_found.
62+
Stream is a deprecated alias module of "Stdlib.Stream", and the camlp-streams
63+
package that is used by pa_hol_syntax redefines Stream, which seems to
64+
confuse Env.fold_values and Env.fold_modules. *)
65+
([], [])
66+
67+
let rec enum1 lidopt acc =
68+
match enum0 lidopt with
69+
(vl, []) -> vl@acc
70+
| (vl, ml) ->
71+
List.fold_left (fun acc mlid ->
72+
enum1 (Some mlid) acc) (vl@acc) ml
73+
74+
let string_of_longident lid =
75+
String.concat "." (Longident.flatten lid)
76+
77+
let all_theorems () =
78+
enum1 None []
79+
|> List.map (fun lid ->
80+
let s = string_of_longident lid in
81+
(s, (Ocaml_typing.eval s : thm)))
82+
end
83+
84+
85+
let update_database () =
86+
theorems := Lookuptheorems.all_theorems()
87+
88+
(* ------------------------------------------------------------------------- *)
89+
(* Put an assignment of a theorem database in the named file. *)
90+
(* ------------------------------------------------------------------------- *)
91+
92+
let make_database_assignment filename =
93+
update_database();
94+
(let allnames = uniq(sort (<) (map fst (!theorems))) in
95+
let names = subtract allnames ["it"] in
96+
let entries = map (fun n -> "\""^n^"\","^n) names in
97+
let text = "needs \"help.ml\";;\n\n"^
98+
"theorems :=\n[\n"^
99+
end_itlist (fun a b -> a^";\n"^b) entries^"\n];;\n" in
100+
file_of_string filename text);;
101+
102+
(* ------------------------------------------------------------------------- *)
103+
(* Search (automatically updates) *)
104+
(* ------------------------------------------------------------------------- *)
105+
106+
let search =
107+
let rec immediatesublist l1 l2 =
108+
match (l1,l2) with
109+
[],_ -> true
110+
| _,[] -> false
111+
| (h1::t1,h2::t2) -> h1 = h2 && immediatesublist t1 t2 in
112+
let rec sublist l1 l2 =
113+
match (l1,l2) with
114+
[],_ -> true
115+
| _,[] -> false
116+
| (h1::t1,h2::t2) -> immediatesublist l1 l2 || sublist l1 t2 in
117+
let exists_subterm_satisfying p (n,th) = can (find_term p) (concl th)
118+
and name_contains s (n,th) = sublist (explode s) (explode n) in
119+
let rec filterpred tm =
120+
match tm with
121+
Comb(Var("<omit this pattern>",_),t) -> not o filterpred t
122+
| Comb(Var("<match theorem name>",_),Var(pat,_)) -> name_contains pat
123+
| Comb(Var("<match aconv>",_),pat) -> exists_subterm_satisfying (aconv pat)
124+
| pat -> exists_subterm_satisfying (can (term_match [] pat)) in
125+
fun pats ->
126+
update_database();
127+
let triv,nontriv = partition is_var pats in
128+
(if triv <> [] then
129+
warn true
130+
("Ignoring plain variables in search: "^
131+
end_itlist (fun s t -> s^", "^t) (map (fst o dest_var) triv))
132+
else ());
133+
(if nontriv = [] && triv <> [] then []
134+
else sort (increasing fst)
135+
(itlist (filter o filterpred) pats (!theorems)));;
136+
137+
(* ------------------------------------------------------------------------- *)
138+
(* Update to bring things back to current state. *)
139+
(* ------------------------------------------------------------------------- *)
140+
141+
update_database();;

0 commit comments

Comments
 (0)