File: update_database.ml

package info (click to toggle)
hol-light 1%3A3.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 49,876 kB
  • sloc: ml: 752,857; cpp: 439; makefile: 420; sh: 380; lisp: 286; java: 279; yacc: 108; perl: 78; ansic: 57; python: 53; sed: 39
file content (181 lines) | stat: -rw-r--r-- 7,738 bytes parent folder | download | duplicates (4)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
(* ========================================================================= *)
(* Create search database from OCaml / modify search database dynamically.   *)
(*                                                                           *)
(* This file assigns to "theorems", which is a list of name-theorem pairs.   *)
(* The core system already has such a database set up. Use this file if you  *)
(* want to update the database beyond the core, so you can search it.        *)
(*                                                                           *)
(* The trickery to get at the OCaml environment is due to oleg@pobox.com     *)
(* (see his message to the caml-list on Tuesday 26th September 2006).        *)
(* ========================================================================= *)

(* !!!!!!! You must set this to point at the source directory in
   !!!!!!! which OCaml was built. (And don't do "make clean" beforehand.)
 *)

let ocaml_source_dir =
  Filename.concat (Sys.getenv "HOME")
  ("software/ocaml-"^Sys.ocaml_version);;

do_list (fun s -> Topdirs.dir_directory(Filename.concat ocaml_source_dir s))
        ["parsing"; "typing"; "toplevel"; "utils"];;

(* This must be loaded first! It is stateful, and affects Predef *)
#load "ident.cmo";;

#load "misc.cmo";;
#load "path.cmo";;
#load "types.cmo";;
#load "btype.cmo";;
#load "tbl.cmo";;
#load "subst.cmo";;
#load "predef.cmo";;
#load "datarepr.cmo";;
#load "config.cmo";;
#load "consistbl.cmo";;
#load "clflags.cmo";;
#load "env.cmo";;
#load "ctype.cmo";;
#load "printast.cmo";;
#load "oprint.cmo";;
#load "primitive.cmo";;
#load "printtyp.cmo";;

(* ------------------------------------------------------------------------- *)
(* Get the toplevel environment as raw data.                                 *)
(* ------------------------------------------------------------------------- *)

let get_value_bindings env =
   let rec get_val acc = function
        | Env.Env_empty -> acc
        | Env.Env_value (next, ident, val_descr) ->
                get_val ((ident,val_descr)::acc) next
        | Env.Env_type (next,_,_) -> get_val acc next
        | Env.Env_exception (next,_,_) -> get_val acc next
        | Env.Env_module (next,_,_) -> get_val acc next
        | Env.Env_modtype (next,_,_) -> get_val acc next
        | Env.Env_class (next,_,_) -> get_val acc next
        | Env.Env_cltype (next,_,_) -> get_val acc next
        | Env.Env_open (next,_) -> get_val acc next
  in get_val [] (Env.summary env);;

(* ------------------------------------------------------------------------- *)
(* Convert a type to a string, for ease of comparison.                       *)
(* ------------------------------------------------------------------------- *)

let type_to_str (x : Types.type_expr) =
  Printtyp.type_expr Format.str_formatter x;
         Format.flush_str_formatter ();;

(* ------------------------------------------------------------------------- *)
(* Put an assignment of a theorem database in the named file.                *)
(* ------------------------------------------------------------------------- *)

let make_database_assignment filename =
  let all_bnds = get_value_bindings (!Toploop.toplevel_env) in
  let thm_bnds = filter (fun (ident,val_descr) ->
                          type_to_str val_descr.Types.val_type = "thm")
                        all_bnds in
  let names =
    subtract (map (fun (ident,val_descr) -> Ident.name ident) thm_bnds)
             ["it"] in
  let entries = map (fun n -> "\""^n^"\","^n) (uniq(sort (<) names)) in
  let text = "theorems :=\n[\n"^
             end_itlist (fun a b -> a^";\n"^b) entries^"\n];;\n" in
  file_of_string filename text;;

(* ------------------------------------------------------------------------- *)
(* Remove bindings in first list from second assoc list (all ordered).       *)
(* ------------------------------------------------------------------------- *)

let rec demerge s l =
  match (s,l) with
    u::t,(x,y as p)::m ->
        if u = x then demerge t m
        else if u < x then demerge t l
        else p::(demerge s m)
  | _ -> l;;

(* ------------------------------------------------------------------------- *)
(* Incrementally update database.                                            *)
(* ------------------------------------------------------------------------- *)

let update_database =
  let value_bindings_checked = ref 0
  and theorem_bindings_existing = ref undefined in
  let listify l = if l = [] then "[]"
                  else "[\n"^end_itlist (fun a b -> a^";\n"^b) l^"\n]\n" in
  let purenames = map (fun n -> "\""^n^"\"")
  and pairnames = map (fun n -> "\""^n^"\","^n) in
  fun () ->
    let old_count = !value_bindings_checked
    and old_ths = !theorem_bindings_existing in
    let all_bnds = get_value_bindings (!Toploop.toplevel_env) in
    let new_bnds = funpow old_count tl all_bnds in
    let new_count = old_count + length new_bnds
    and new_ths =
      rev_itlist (fun (ident,val_descr) ->
        let n = Ident.name ident in
        if type_to_str val_descr.Types.val_type = "thm" && n <> "it"
        then (n |-> ()) else undefine n) new_bnds old_ths in
    value_bindings_checked := new_count;
    if new_ths = old_ths then () else
    (print_string "Updating search database\n";
     theorem_bindings_existing := new_ths;
     let all_ths = combine (fun _ _ -> ()) (fun _ -> false) old_ths new_ths in
     let del_ths = combine (fun _ _ -> ()) (fun _ -> true) all_ths new_ths
     and add_ths = combine (fun _ _ -> ()) (fun _ -> true) all_ths old_ths in
     let del_names = mergesort (<) (foldr (fun a _ l -> a::l) del_ths [])
     and add_names = mergesort (<) (foldr (fun a _ l -> a::l) add_ths []) in
     let exptext =
      "theorems :=\n merge (increasing fst) (demerge "^
      (listify(purenames del_names))^
      " (!theorems)) "^
      (listify(pairnames add_names))^
      ";;\n" in
     (let filename = Filename.temp_file "database" ".ml" in
      file_of_string filename exptext;
      loadt filename;
      Sys.remove filename));;

(* ------------------------------------------------------------------------- *)
(* Include a call to this on each search.                                    *)
(* ------------------------------------------------------------------------- *)

let search =
  let rec immediatesublist l1 l2 =
    match (l1,l2) with
      [],_ -> true
    | _,[] -> false
    | (h1::t1,h2::t2) -> h1 = h2 && immediatesublist t1 t2 in
  let rec sublist l1 l2 =
    match (l1,l2) with
      [],_ -> true
    | _,[] -> false
    | (h1::t1,h2::t2) -> immediatesublist l1 l2 || sublist l1 t2 in
  let exists_subterm_satisfying p (n,th) = can (find_term p) (concl th)
  and name_contains s (n,th) = sublist (explode s) (explode n) in
  let rec filterpred tm =
    match tm with
      Comb(Var("<omit this pattern>",_),t) -> not o filterpred t
    | Comb(Var("<match theorem name>",_),Var(pat,_)) -> name_contains pat
    | Comb(Var("<match aconv>",_),pat) -> exists_subterm_satisfying (aconv pat)
    | pat -> exists_subterm_satisfying (can (term_match [] pat)) in
  fun pats ->
    update_database();
    let triv,nontriv = partition is_var pats in
    (if triv <> [] then
      warn true
         ("Ignoring plain variables in search: "^
          end_itlist (fun s t -> s^", "^t) (map (fst o dest_var) triv))
     else ());
    (if nontriv = [] && triv <> [] then []
     else itlist (filter o filterpred) pats (!theorems));;

(* ------------------------------------------------------------------------- *)
(* Update to bring things back to current state.                             *)
(* ------------------------------------------------------------------------- *)

theorems := [];;

update_database();;