1 (* ========================================================================= *)
2 (* Proof-objects for HOL-light *)
4 (* Steven Obua, TU München, December 2004 *)
6 (* based on Sebastian Skalberg's HOL4 proof-objects *)
7 (* ========================================================================= *)
11 module type Proofobject_primitives =
16 val proof_REFL : term -> proof
17 val proof_TRANS : proof * proof -> proof
18 val proof_MK_COMB : proof * proof -> proof
19 val proof_ASSUME : term -> proof
20 val proof_EQ_MP : proof -> proof -> proof
21 val proof_IMPAS : proof -> proof -> proof
22 val proof_DISCH : proof -> term -> proof
23 val proof_DEDUCT_ANTISYM_RULE : proof * term -> proof * term -> proof
24 val proof_BETA : term -> proof
25 val proof_ABS : term -> proof -> proof
26 val proof_INST_TYPE : (hol_type * hol_type) list -> proof -> proof
27 val proof_INST : (term * term) list -> proof -> proof
28 val proof_new_definition : string -> hol_type -> term -> proof
29 val proof_CONJ : proof -> proof -> proof
30 val proof_CONJUNCT1 : proof -> proof
31 val proof_CONJUNCT2 : proof -> proof
32 val proof_new_basic_type_definition :
33 string -> string * string -> term * term -> proof -> proof
34 val proof_SPEC : term -> proof -> proof
35 val proof_SYM : proof -> proof
36 val proof_GEN : proof -> term -> proof
37 val proof_DISJ1 : proof -> term -> proof
38 val proof_DISJ2 : proof -> term -> proof
39 val proof_NOTI : proof -> proof
40 val proof_NOTE : proof -> proof
41 val proof_CONTR : proof -> term -> proof
42 val proof_DISJCASES : proof -> proof -> proof -> proof
43 val proof_CHOOSE : term -> proof -> proof -> proof
44 val proof_EXISTS : term -> term -> proof -> proof
46 val new_axiom_name : string -> string
47 val proof_new_axiom : string -> term -> proof
49 val save_proof : string -> proof -> (term option) -> unit
50 val proof_database : unit -> ((string * proof * (term option)) list)
52 val export_proofs : string option -> (string * proof * (term option)) list -> unit
53 val export_saved_proofs : string option -> unit
56 module Proofobjects : Proofobject_primitives = struct
60 (output stdout q 0 (String.length q); p);;*)
65 {disk_info: (string * string) option ref;
70 type proof_info = Info of proof_info_rec
72 type ('a, 'b) libsubst_rec = {redex:'a; residue:'b}
73 type ('a, 'b) libsubst = (('a,'b) libsubst_rec) list
75 let pair2libsubstrec =
76 fun (a,b) -> {redex=b;residue=a}
78 (* note: not all of the proof_content constructors are actually used, some are just legacy from the HOL4 proof objects *)
80 Proof of (proof_info * proof_content * (unit -> unit))
83 | Pinstt of proof * ((hol_type,hol_type) libsubst)
84 | Psubst of proof list * term * proof
85 | Pabs of proof * term
86 | Pdisch of proof * term
87 | Pmp of proof * proof
89 | Paxm of string * term
90 | Pdef of string * string * term
91 | Ptmspec of string * string list * proof
92 | Ptydef of string * string * proof
93 | Ptyintro of string * string * string * string * term * term * proof
94 | Poracle of tag * term list * term
96 | Pspec of proof * term
97 | Pinst of proof * (term,term) libsubst
98 | Pgen of proof * term
99 | Pgenabs of proof * term option * term list
101 | Ptrans of proof * proof
102 | Pcomb of proof * proof
103 | Peqmp of proof * proof
105 | Pexists of proof * term * term
106 | Pchoose of term * proof * proof
107 | Pconj of proof * proof
108 | Pconjunct1 of proof
109 | Pconjunct2 of proof
110 | Pdisj1 of proof * term
111 | Pdisj2 of proof * term
112 | Pdisjcases of proof * proof * proof
115 | Pcontr of proof * term
116 | Pimpas of proof * proof
118 let THEORY_NAME = "hollight"
120 let content_of (Proof (_,p,_)) = p
122 let inc_references (Proof(Info{references=r},_,_) as p) = (
129 let concat = String.concat ""
131 let dummy_fun () = ()
133 let mk_proof p = Proof(Info {disk_info = ref None; status = ref 0; references = ref 0; queued = ref false},p, dummy_fun)
135 let global_ax_counter = let counter = ref 1 in let f = fun () -> (let x = !counter in counter := !counter+1; x) in f
137 let new_axiom_name n = concat["ax_"; n; "_"; string_of_int(global_ax_counter())]
139 let proof_REFL t = writeln "REFL" (mk_proof (Prefl t))
141 let proof_TRANS (p,q) = writeln "TRANS" (
142 match (content_of p, content_of q) with
145 | _ -> mk_proof (Ptrans (inc_references p, inc_references q)))
147 let proof_MK_COMB (p1,p2) = writeln "MK_COMB" (
148 (match (content_of p1, content_of p2) with
149 (Prefl tm1, Prefl tm2) -> proof_REFL (mk_comb (tm1, tm2))
150 | _ -> mk_proof (Pcomb (inc_references p1, inc_references p2))))
152 let proof_ASSUME t = writeln "ASSUME "(mk_proof (Phyp t))
154 let proof_EQ_MP p q = writeln "EQ_MP" (
155 (match content_of p with
157 | _ -> mk_proof (Peqmp(inc_references p, inc_references q))))
159 let proof_IMPAS p1 p2 = writeln "IMPAS" (
160 mk_proof (Pimpas (inc_references p1, inc_references p2)))
162 let proof_DISCH p t = writeln "DISCH" (mk_proof (Pdisch(inc_references p,t)))
164 let proof_DEDUCT_ANTISYM_RULE (p1,t1) (p2,t2) = writeln "DEDUCT_ANTISYM_RULE" (
165 proof_IMPAS (proof_DISCH p1 t2) (proof_DISCH p2 t1))
167 let proof_BETA t = writeln "BETA" (mk_proof (Prefl t))
169 let proof_ABS x p = writeln "ABS" (
170 (match (content_of p) with
171 Prefl tm -> proof_REFL (mk_abs(x,tm))
172 | _ -> mk_proof (Pabs(inc_references p,x))))
174 let proof_INST_TYPE s p = writeln "INST_TYPE" (mk_proof (Pinstt(inc_references p, map pair2libsubstrec s)))
176 let proof_INST s p = writeln "INST" (mk_proof (Pinst(inc_references p, map pair2libsubstrec s)))
178 let proof_new_definition cname _ t = writeln "new_definition" (mk_proof (Pdef (THEORY_NAME, cname, t)))
180 let proof_new_axiom axname t = writeln "new_axiom" (mk_proof (Paxm (axname, t)))
182 let proof_CONJ p1 p2 = writeln "CONJ" (mk_proof (Pconj (inc_references p1, inc_references p2)))
184 let proof_CONJUNCT1 p = writeln "CONJUNCT1" (mk_proof (Pconjunct1 (inc_references p)))
186 let proof_CONJUNCT2 p = writeln "CONJUNCT2" (mk_proof (Pconjunct2 (inc_references p)))
188 let proof_new_basic_type_definition tyname (absname, repname) (pt,tt) p = writeln "new_basic_type_definition" (
189 mk_proof(Ptyintro (THEORY_NAME, tyname, absname, repname, pt, tt,inc_references p)))
191 (* ---- used only in substitute_proof calls ---- *)
193 let proof_SPEC s p = writeln "SPEC" (mk_proof (Pspec(inc_references p, s)))
195 let proof_SYM p = writeln "SYM" (mk_proof (Psym(inc_references p)))
197 let proof_GEN p a = writeln "GEN" (mk_proof (Pgen(inc_references p, a)))
199 let proof_DISJ1 p a = writeln "DISJ1" (mk_proof (Pdisj1 (inc_references p, a)))
201 let proof_DISJ2 p a = writeln "DISJ2" (mk_proof (Pdisj2 (inc_references p, a)))
203 let proof_NOTI p = writeln "NOTI" (mk_proof (Pnoti (inc_references p)))
205 let proof_NOTE p = writeln "NOTE" (mk_proof (Pnote (inc_references p)))
207 let proof_CONTR p a = writeln "CONTR" (mk_proof (Pcontr (inc_references p, a)))
209 let proof_DISJCASES p q r = writeln "DISJCASES" (mk_proof (Pdisjcases (inc_references p, inc_references q, inc_references r)))
211 let proof_CHOOSE a p q = writeln "CHOOSE" (mk_proof (Pchoose (a, inc_references p, inc_references q)))
213 let proof_EXISTS x y p = writeln "EXISTS" (mk_proof (Pexists (inc_references p, x, y)))
215 (* ---- formerly known as proofio.ml ---- *)
217 let ensure_export_directory thyname =
218 let dir = Sys.getenv "HOLPROOFEXPORTDIR" in
219 let dirsub = Filename.concat dir "hollight" in
220 let dirsubsub = Filename.concat dirsub thyname in
221 let mk d = if Sys.file_exists d then () else Unix.mkdir d 509
228 (* ---- Useful functions on terms ---- *)
229 let rec types_of tm =
239 union (types_of f) (types_of a)
244 insert (type_of x) (types_of a);;
247 try let (f,arg) = dest_comb tm in
248 let (v,bod) = dest_abs f in
250 with Failure _ -> failwith "beta_conv: Not a beta-redex";;
254 (let (v, bod) = dest_abs tm in
255 let (f, arg) = dest_comb bod in
256 if (arg = v && (not(vfree_in v f))) then
260 Failure _ -> failwith "eta_conv: Not an eta-redex";;
262 let rec be_contract tm =
263 let rec bec tm = try try Some (beta_conv tm)
273 Some f' -> Some (mk_comb(f',x))
274 | None -> (match bec x with
275 Some x' -> Some (mk_comb(f,x'))
280 (x,body) = dest_abs tm
283 Some body' -> Some (mk_abs(x,body'))
288 Some tm' -> be_contract tm'
291 let rec polymorphic x =
292 if is_vartype x then true else exists polymorphic (snd (dest_type x))
294 (* ---- From Lib etc. ---- *)
297 let rec append = fun xlist l ->
300 | (x::xs) -> x::(append xs l));;
304 (function (((key,_) as e)::rst) -> if item=key then Some e else assc rst
312 | (l::ls) -> append l (listconcat ls);;
315 function [] -> true | _ -> false;;
317 (* ---- exported ---- *)
318 let encodeXMLEntities m = m;;let encodeXMLEntities s =
319 let len = String.length s in
320 let encodeChar = function '<' -> "<" | '>' -> ">" | '&' -> "&" | '\'' -> "'" | '"' -> """ | c -> String.make 1 c in
321 let rec encodeStr i = if (i<len) then (encodeChar (String.get s i))::(encodeStr (i+1)) else [] in
322 String.concat "" (encodeStr 0);;
324 let encodeXMLEntitiesOut out = function x -> out (encodeXMLEntities x);;
327 let content_of (Proof (_,x,_)) = x;;
329 let rec explode_subst =
331 | ({redex=x;residue=y}::rest) -> x::y::(explode_subst rest);;
335 | (x::l) -> (f x; app f l);;
337 let disk_info_of (Proof(Info {disk_info=di},_,_)) = !di;;
339 let set_disk_info_of (Proof(Info {disk_info=di},_,_)) thyname thmname =
340 di := Some (thyname,thmname);;
342 let references (Proof (Info info,_,_)) = !(info.references);;
344 let wrap b e s = b^s^e;;
346 let xml_empty_tag = wrap "<" "/>";;
347 let xml_start_tag = wrap "<" ">";;
348 let xml_end_tag = wrap "</" ">";;
350 itlist (function (tag,v) ->
352 concat[" ";tag;"=\"";v;"\"";s]
355 let xml_element tag attr children =
357 header = tag ^ (xml_attr attr)
359 (if listnull children
360 then xml_empty_tag header
361 else wrap (xml_start_tag header) (xml_end_tag tag) (concat children));;
363 let id_to_atts curthy id = [("n", encodeXMLEntities id)];; (* There is only one theory in Hol-Light, therefore id_to_atts is superfluous *)
365 let glob_counter = ref 1;;
371 glob_counter := res + 1;
374 let get_iname = string_of_int o get_counter;;
376 let next_counter () = !glob_counter;;
379 match (content_of p) with
387 let do_share p = references p > 1 & not (trivial p);;
389 exception Err of string*string;;
391 (* ---- The General List Formerly Known As Net ---- *)
393 type 'a exprnet = (('a list) ref) * ('a -> ('a list))
395 let empty_net f () = (ref [], f);;
397 let rec lookup'_net net x =
399 [] -> raise Not_found
400 | (a::l) -> if (a = x) then 0 else 1+(lookup'_net l x);;
402 let lookup_net (net,f) x = lookup'_net (!net) x;;
404 let insert'_net (net,f) x =
405 try lookup'_net !net x; () with Not_found -> ((net := (!net)@[x]);());;
407 let rec insert_net ((net,f) as n) x =
408 (app (insert_net n) (f x); insert'_net n x);;
410 let to_list_net (net,f) = !net;;
412 (* ---- The Type Net (it's not a net any more!) ---- *)
414 type yy_net = hol_type exprnet;;
416 let yy_empty = empty_net (function x -> if is_type x then snd (dest_type x) else []);;
418 let yy_lookup = lookup_net;;
420 let yy_output_types out thyname net =
422 all_types = to_list_net net in let rec
423 xml_index ty = xml_element "tyi" [("i",string_of_int (yy_lookup net ty))] []
424 and xml_const id = xml_element "tyc" (id_to_atts thyname id) []
426 if is_vartype ty then out (xml_element "tyv" [("n",encodeXMLEntities (dest_vartype ty))] [])
428 match dest_type ty with
429 (id, []) -> out (xml_const id)
430 | (id, tl) -> out (xml_element "tya" [] ((xml_const id)::(map xml_index tl)))
434 out (string_of_int (length all_types));
436 app out_type all_types;
439 let yy_insert = insert_net;;
441 (* ---- The Term Net (it's not a net anymore!) ---- *)
443 type mm_net = term exprnet;;
445 let mm_empty = empty_net (
448 (let (x,b) = dest_abs tm in [x; b])
449 else if is_comb tm then
450 (let (s,t) = dest_comb tm in [s; t])
454 let mm_lookup net x = lookup_net net (be_contract x);;
456 let mm_insert net x = insert_net net (be_contract x);;
458 let mm_output_terms out thyname types net =
459 let all_terms = to_list_net net in
460 let xml_type ty = xml_element "tyi" [("i",string_of_int (yy_lookup types ty))] [] in
461 let xml_index tm = xml_element "tmi" [("i",string_of_int (mm_lookup net tm))] [] in
466 (name,ty) = dest_var tm
468 out (xml_element "tmv" [("n",encodeXMLEntities name);("t", string_of_int (yy_lookup types ty))] [])
471 let (name, ty) = (dest_const tm) in
472 let general_ty = get_const_type name in
473 let atts = [("n",encodeXMLEntities name)]
475 if polymorphic general_ty then
476 out (xml_element "tmc" (atts@[("t",string_of_int (yy_lookup types ty))]) [])
477 else out (xml_element "tmc" atts [])
483 out (xml_element "tma" [("f", string_of_int (mm_lookup net f));("a",string_of_int (mm_lookup net a))] [])
488 out (xml_element "tml" [("x", string_of_int (mm_lookup net x));("a",string_of_int (mm_lookup net a))] [])
491 out (string_of_int(length all_terms));
493 app out_term all_terms;
497 (* ---- collect_types_terms ---- *)
499 let collect_types_terms thyname out prf c_opt =
501 will_be_shared prf = (
502 match disk_info_of prf with
504 | None -> do_share prf) in let
506 types = yy_empty () in let
507 terms = mm_empty () in let
509 insert_type ty = yy_insert types ty in let
511 insert_term tm = (mm_insert terms tm;
512 app (yy_insert types) (types_of tm)) in let rec
515 (match content_of prf with
516 Pinstt(prf,tsubst) -> (app (function {redex=x;residue=u}->(insert_type x; insert_type u))
519 | Psubst(prfs,tm,prf) -> (insert_term tm;
522 | Pabs(prf,tm) -> (insert_term tm;
524 | Pdisch(prf,tm) -> (insert_term tm;
526 | Pmp(prf1,prf2) -> (ct prf1; ct prf2)
527 | Poracle(_,tms,tm) -> (insert_term tm;
529 | Pdef(_,_,tm) -> insert_term tm
530 | Ptmspec(_,_,prf) -> ct prf
531 | Ptydef(_,_,prf) -> ct prf
532 | Ptyintro(_,_,_,_,pt,tt,prf) -> (insert_term pt; insert_term tt;ct prf)
533 | Pspec(prf,tm) -> (insert_term tm; ct prf)
534 | Pinst(prf,subst) -> (app (fun{redex=x;residue=u}->(insert_term x;
538 | Pgen(prf,tm) -> (insert_term tm; ct prf)
539 | Pgenabs(prf,tm_opt,tms) -> (match tm_opt with
540 Some tm -> insert_term tm
545 | Ptrans(prf1,prf2) -> (ct prf1; ct prf2)
546 | Pcomb(prf1,prf2) -> (ct prf1; ct prf2)
547 | Peqmp(prf1,prf2) -> (ct prf1; ct prf2)
548 | Peqimp prf -> ct prf
549 | Pexists(prf,ex,w) -> (insert_term ex;
552 | Pchoose(v,prf1,prf2) -> (insert_term v; ct prf1; ct prf2)
553 | Pconj(prf1,prf2) -> (ct prf1; ct prf2)
554 | Pconjunct1 prf -> ct prf
555 | Pconjunct2 prf -> ct prf
556 | Pdisj1(prf,tm) -> (insert_term tm;
558 | Pdisj2(prf,tm) -> (insert_term tm;
560 | Pdisjcases(prf1,prf2,prf3) -> (ct prf1; ct prf2; ct prf3)
561 | Pnoti prf -> ct prf
562 | Pnote prf -> ct prf
563 | Pcontr(prf,tm) -> (insert_term tm;
565 | Prefl tm -> insert_term tm
566 | Phyp tm -> insert_term tm
568 | Paxm (_,tm) -> insert_term tm
569 | Pimpas (prf1,prf2) -> (ct prf1; ct prf2))
571 if will_be_shared prf
576 _ = (match c_opt with
577 Some c -> insert_term c
579 _ = yy_output_types out thyname types in let
580 _ = mm_output_terms out thyname types terms
584 let rec export_proof path thyname thmname p c_opt il =
585 let outchannel = open_out (Filename.concat path (thmname^".prf")) in
586 let out = output_string outchannel in
587 let nout = encodeXMLEntitiesOut out in
589 _ = out "<proof>" in let
591 (types,terms) = collect_types_terms thyname out p c_opt in let
597 out (string_of_int (mm_lookup terms tm));
600 wt tm = try (out "<tmi"; wti "i" tm; out "/>") with Not_found -> raise (Err("export_proof","Term not found!")) in let
603 try (out "<tyi i=\"";
604 out (string_of_int (yy_lookup types ty));
605 out "\"/>") with Not_found -> raise (Err("export_proof","Type not found!")) in let
609 if not (thy = thyname)
621 (match (disk_info_of p) with
622 Some (thyname,thmname) -> Some(thyname,thmname,il)
625 let name = get_iname() in set_disk_info_of p thyname name; Some(thyname,name,(name,p,None)::il)
632 _ = out (xml_start_tag str) in let
633 res = rev_itlist (function p -> function il -> wp il p) prfs il in let
634 _ = out (xml_end_tag str)
640 (Prefl tm) -> (out "<prefl"; wti "i" tm; out "/>"; il)
641 | (Pinstt(p,lambda)) ->
643 _ = out "<pinstt>" in let
645 _ = app wty (explode_subst lambda) in let
649 | (Psubst(ps,t,p)) ->
651 _ = (out "<psubst"; wti "i" t; out ">") in let
653 res = rev_itlist (function p -> function il -> wp il p) ps il' in let
659 _ = (out "<pabs"; wti "i" t; out ">") in let
666 _ = (out "<pdisch"; wti "i" tm; out ">") in let
671 | (Pmp(p1,p2)) -> dump "pmp" il [p1;p2]
672 | (Phyp tm) -> (out "<phyp"; wti "i" tm; out "/>"; il)
680 | (Pdef(seg,name,tm)) ->
689 | (Ptmspec(seg,names,p)) ->
691 _ = (out "<ptmspec s=\""; out seg; out "\">") in let
693 _ = app (function s -> (out "<name n=\""; nout s; out "\"/>")) names in let
697 | (Ptydef(seg,name,p)) ->
699 _ = (out "<ptydef s=\""; out seg; out "\" n=\""; nout name; out "\">") in let
704 | (Ptyintro(seg,name,abs,rep,pt,tt,p)) ->
706 _ = (out "<ptyintro s=\""; out seg; out "\" n=\""; nout name;
707 out "\" a=\""; out abs; out "\" r=\""; out rep; out "\">") in let
712 _ = out "</ptyintro>"
715 | (Poracle(tg,asl,c)) -> raise (Err("export_proof", "sorry, oracle export is not implemented!"))
717 app (function s -> (out "<oracle n=\""; nout s; out "\"/>")) (Tag.oracles_of tg);
724 _ = (out "<pspec"; wti "i" t; out ">") in let
729 | (Pinst(p,theta)) ->
731 _ = out "<pinst>" in let
733 _ = app wt (explode_subst theta) in let
739 _ = (out "<pgen"; wti "i" x; out ">") in let
744 | (Pgenabs(p,opt,vl)) ->
746 _ = out "<pgenabs" in let
756 | (Psym p) -> dump "psym" il [p]
757 | (Ptrans(p1,p2)) -> dump "ptrans" il [p1;p2]
758 | (Pcomb(p1,p2)) -> dump "pcomb" il [p1;p2]
759 | (Peqmp(p1,p2)) -> dump "peqmp" il [p1;p2]
760 | (Peqimp p) -> dump "peqimp" il [p]
761 | (Pexists(p,ex,w)) ->
763 _ = (out "<pexists"; wti "e" ex; wti "w" w; out ">") in let
768 | (Pchoose(v,p1,p2)) ->
770 _ = (out "<pchoose"; wti "i" v; out ">") in let
771 il' = wp il p1 in let
772 res = wp il' p2 in let
776 | (Pconj(p1,p2)) -> dump "pconj" il [p1;p2]
777 | (Pimpas(p1,p2)) -> dump "pimpas" il [p1;p2]
778 | (Pconjunct1 p) -> dump "pconjunct1" il [p]
779 | (Pconjunct2 p) -> dump "pconjunct2" il [p]
782 _ = (out "<pdisj1"; wti "i" tm; out ">") in let
789 _ = (out "<pdisj2"; wti "i" tm; out ">") in let
794 | (Pdisjcases(p1,p2,p3)) -> dump "pdisjcases" il [p1;p2;p3]
795 | (Pnoti p) -> dump "pnoti" il [p]
796 | (Pnote p) -> dump "pnote" il [p]
799 _ = (out "<pcontr"; wti "i" tm; out ">") in let
804 | Pdisk -> raise (Err("wp'","shouldn't try to write pdisk"))
808 res = match (share_info_of p il) with
809 Some(thyname',thmname,il') -> (wdi thyname' thmname; il')
810 | None -> wp' il (content_of p)
813 res = (match disk_info_of p with
814 Some(thyname',thmname') ->
815 if thyname' = thyname &
818 wp' il (content_of p)
820 (wdi thyname' thmname';
822 | None -> wp' il (content_of p))
825 il = write_proof p il in let
826 _ = (match c_opt with
829 _ = (out "</proof>\n";(close_out outchannel)) in let
830 _ = set_disk_info_of p thyname thmname
833 [] -> () (* everything has been written *)
834 | ((thmname',prf,c_opt)::rest) -> export_proof path thyname thmname' prf c_opt rest;;
836 let export_proofs theory_name l' =
837 let theory_name = match theory_name with None -> THEORY_NAME | Some n -> n in
838 let path = ensure_export_directory theory_name in
839 let ostrm = open_out (Filename.concat path "facts.lst") in
840 let out = output_string ostrm in
841 let _ = app (function (s,_,_) -> out (s^"\n")) l' in
842 let _ = flush ostrm in
846 | ((thmname,p,c_opt)::rest) -> export_proof path theory_name thmname p c_opt rest) in
847 let num_int_thms = next_counter() - 1 in
848 let _ = out ((string_of_int num_int_thms)^"\n");(close_out ostrm) in
851 let the_proof_database = ref ([]:(string*proof*(term option)) list);;
853 exception Duplicate_proof_name;;
855 let rec search_proof_name n db =
856 match db with [] -> () | ((m, a, b)::db') -> if n=m then (raise Duplicate_proof_name) else search_proof_name n db'
858 let save_proof name p c_opt =
859 let _ = search_proof_name name (!the_proof_database)
861 (the_proof_database :=
862 (name, p, c_opt)::(!the_proof_database));;
864 let proof_database () = !the_proof_database;;
866 (* this is a little bit dangerous, because the function is not injective,
867 but I guess one can live with that *)
868 let make_filesystem_compatible s =
869 let modify = function
871 | "\\" -> "_backslash_"
873 | ">" -> "_greaterthan_"
874 | "<" -> "_lessthan_"
875 | "?" -> "_questionmark_"
876 | "!" -> "_exclamationmark_"
880 implode (map modify (explode s));;
882 let export_saved_proofs thy =
883 let context = rev (proof_database ()) in
884 export_proofs thy (map (function (s,p,c) -> (make_filesystem_compatible s,p,c)) context);;
888 include Proofobjects;;