(* ========================================================================= *)
(* Proof-objects for HOL-light *)
(* *)
(* Steven Obua, TU München, December 2004 *)
(* *)
(* based on Sebastian Skalberg's HOL4 proof-objects *)
(* ========================================================================= *)
#load "unix.cma";;
module type Proofobject_primitives =
sig
type proof
val proof_REFL : term -> proof
val proof_TRANS : proof * proof -> proof
val proof_MK_COMB : proof * proof -> proof
val proof_ASSUME : term -> proof
val proof_EQ_MP : proof -> proof -> proof
val proof_IMPAS : proof -> proof -> proof
val proof_DISCH : proof -> term -> proof
val proof_DEDUCT_ANTISYM_RULE : proof * term -> proof * term -> proof
val proof_BETA : term -> proof
val proof_ABS : term -> proof -> proof
val proof_INST_TYPE : (hol_type * hol_type) list -> proof -> proof
val proof_INST : (term * term) list -> proof -> proof
val proof_new_definition : string -> hol_type -> term -> proof
val proof_CONJ : proof -> proof -> proof
val proof_CONJUNCT1 : proof -> proof
val proof_CONJUNCT2 : proof -> proof
val proof_new_basic_type_definition :
string -> string * string -> term * term -> proof -> proof
val proof_SPEC : term -> proof -> proof
val proof_SYM : proof -> proof
val proof_GEN : proof -> term -> proof
val proof_DISJ1 : proof -> term -> proof
val proof_DISJ2 : proof -> term -> proof
val proof_NOTI : proof -> proof
val proof_NOTE : proof -> proof
val proof_CONTR : proof -> term -> proof
val proof_DISJCASES : proof -> proof -> proof -> proof
val proof_CHOOSE : term -> proof -> proof -> proof
val proof_EXISTS : term -> term -> proof -> proof
val new_axiom_name : string -> string
val proof_new_axiom : string -> term -> proof
val save_proof : string -> proof -> (term option) -> unit
val proof_database : unit -> ((string * proof * (term option)) list)
val export_proofs : string option -> (string * proof * (term option)) list -> unit
val export_saved_proofs : string option -> unit
end;;
module Proofobjects : Proofobject_primitives = struct
let writeln s p = p;;
(* let q = s^"\n" in
(output stdout q 0 (String.length q); p);;*)
type tag = string
type proof_info_rec =
{disk_info: (string * string) option ref;
status: int ref;
references: int ref;
queued: bool ref}
type proof_info = Info of proof_info_rec
type ('a, 'b) libsubst_rec = {redex:'a; residue:'b}
type ('a, 'b) libsubst = (('a,'b) libsubst_rec) list
let pair2libsubstrec =
fun (a,b) -> {redex=b;residue=a}
(* note: not all of the proof_content constructors are actually used, some are just legacy from the HOL4 proof objects *)
type proof =
Proof of (proof_info * proof_content * (unit -> unit))
and proof_content =
Prefl of term
| Pinstt of proof * ((hol_type,hol_type) libsubst)
| Psubst of proof list * term * proof
| Pabs of proof * term
| Pdisch of proof * term
| Pmp of proof * proof
| Phyp of term
| Paxm of string * term
| Pdef of string * string * term
| Ptmspec of string * string list * proof
| Ptydef of string * string * proof
| Ptyintro of string * string * string * string * term * term * proof
| Poracle of tag * term list * term
| Pdisk
| Pspec of proof * term
| Pinst of proof * (term,term) libsubst
| Pgen of proof * term
| Pgenabs of proof * term option * term list
| Psym of proof
| Ptrans of proof * proof
| Pcomb of proof * proof
| Peqmp of proof * proof
| Peqimp of proof
| Pexists of proof * term * term
| Pchoose of term * proof * proof
| Pconj of proof * proof
| Pconjunct1 of proof
| Pconjunct2 of proof
| Pdisj1 of proof * term
| Pdisj2 of proof * term
| Pdisjcases of proof * proof * proof
| Pnoti of proof
| Pnote of proof
| Pcontr of proof * term
| Pimpas of proof * proof
let THEORY_NAME = "hollight"
let content_of (Proof (_,p,_)) = p
let inc_references (Proof(Info{references=r},_,_) as p) = (
let
old = !r
in
r := old + 1;
p)
let concat = String.concat ""
let dummy_fun () = ()
let mk_proof p = Proof(Info {disk_info = ref None; status = ref 0; references = ref 0; queued = ref false},p, dummy_fun)
let global_ax_counter = let counter = ref 1 in let f = fun () -> (let x = !counter in counter := !counter+1; x) in f
let new_axiom_name n = concat["ax_"; n; "_"; string_of_int(global_ax_counter())]
let proof_REFL t = writeln "REFL" (mk_proof (Prefl t))
let proof_TRANS (p,q) = writeln "TRANS" (
match (content_of p, content_of q) with
(Prefl _,_) -> q
| (_, Prefl _) -> p
| _ -> mk_proof (Ptrans (inc_references p, inc_references q)))
let proof_MK_COMB (p1,p2) = writeln "MK_COMB" (
(match (content_of p1, content_of p2) with
(Prefl tm1, Prefl tm2) -> proof_REFL (mk_comb (tm1, tm2))
| _ -> mk_proof (Pcomb (inc_references p1, inc_references p2))))
let proof_ASSUME t = writeln "ASSUME "(mk_proof (Phyp t))
let proof_EQ_MP p q = writeln "EQ_MP" (
(match content_of p with
Prefl _ -> q
| _ -> mk_proof (Peqmp(inc_references p, inc_references q))))
let proof_IMPAS p1 p2 = writeln "IMPAS" (
mk_proof (Pimpas (inc_references p1, inc_references p2)))
let proof_DISCH p t = writeln "DISCH" (mk_proof (Pdisch(inc_references p,t)))
let proof_DEDUCT_ANTISYM_RULE (p1,t1) (p2,t2) = writeln "DEDUCT_ANTISYM_RULE" (
proof_IMPAS (proof_DISCH p1 t2) (proof_DISCH p2 t1))
let proof_BETA t = writeln "BETA" (mk_proof (Prefl t))
let proof_ABS x p = writeln "ABS" (
(match (content_of p) with
Prefl tm -> proof_REFL (mk_abs(x,tm))
| _ -> mk_proof (Pabs(inc_references p,x))))
let proof_INST_TYPE s p = writeln "INST_TYPE" (mk_proof (Pinstt(inc_references p, map pair2libsubstrec s)))
let proof_INST s p = writeln "INST" (mk_proof (Pinst(inc_references p, map pair2libsubstrec s)))
let proof_new_definition cname _ t = writeln "new_definition" (mk_proof (Pdef (THEORY_NAME, cname, t)))
let proof_new_axiom axname t = writeln "new_axiom" (mk_proof (Paxm (axname, t)))
let proof_CONJ p1 p2 = writeln "CONJ" (mk_proof (Pconj (inc_references p1, inc_references p2)))
let proof_CONJUNCT1 p = writeln "CONJUNCT1" (mk_proof (Pconjunct1 (inc_references p)))
let proof_CONJUNCT2 p = writeln "CONJUNCT2" (mk_proof (Pconjunct2 (inc_references p)))
let proof_new_basic_type_definition tyname (absname, repname) (pt,tt) p = writeln "new_basic_type_definition" (
mk_proof(Ptyintro (THEORY_NAME, tyname, absname, repname, pt, tt,inc_references p)))
(* ---- used only in substitute_proof calls ---- *)
let proof_SPEC s p = writeln "SPEC" (mk_proof (Pspec(inc_references p, s)))
let proof_SYM p = writeln "SYM" (mk_proof (Psym(inc_references p)))
let proof_GEN p a = writeln "GEN" (mk_proof (Pgen(inc_references p, a)))
let proof_DISJ1 p a = writeln "DISJ1" (mk_proof (Pdisj1 (inc_references p, a)))
let proof_DISJ2 p a = writeln "DISJ2" (mk_proof (Pdisj2 (inc_references p, a)))
let proof_NOTI p = writeln "NOTI" (mk_proof (Pnoti (inc_references p)))
let proof_NOTE p = writeln "NOTE" (mk_proof (Pnote (inc_references p)))
let proof_CONTR p a = writeln "CONTR" (mk_proof (Pcontr (inc_references p, a)))
let proof_DISJCASES p q r = writeln "DISJCASES" (mk_proof (Pdisjcases (inc_references p, inc_references q, inc_references r)))
let proof_CHOOSE a p q = writeln "CHOOSE" (mk_proof (Pchoose (a, inc_references p, inc_references q)))
let proof_EXISTS x y p = writeln "EXISTS" (mk_proof (Pexists (inc_references p, x, y)))
(* ---- formerly known as proofio.ml ---- *)
let ensure_export_directory thyname =
let dir = Sys.getenv "HOLPROOFEXPORTDIR" in
let dirsub = Filename.concat dir "hollight" in
let dirsubsub = Filename.concat dirsub thyname in
let mk d = if Sys.file_exists d then () else Unix.mkdir d 509
in
(mk dir;
mk dirsub;
mk dirsubsub;
dirsubsub);;
(* ---- Useful functions on terms ---- *)
let rec types_of tm =
if is_var tm
then [type_of tm]
else if is_const tm
then [type_of tm]
else if is_comb tm
then
let
(f,a) = dest_comb tm
in
union (types_of f) (types_of a)
else
let
(x,a) = dest_abs tm
in
insert (type_of x) (types_of a);;
let beta_conv tm =
try let (f,arg) = dest_comb tm in
let (v,bod) = dest_abs f in
vsubst [(arg,v)] bod
with Failure _ -> failwith "beta_conv: Not a beta-redex";;
let eta_conv tm =
try
(let (v, bod) = dest_abs tm in
let (f, arg) = dest_comb bod in
if (arg = v && (not(vfree_in v f))) then
f
else failwith "")
with
Failure _ -> failwith "eta_conv: Not an eta-redex";;
let rec be_contract tm =
let rec bec tm = try try Some (beta_conv tm)
with Failure _ ->
Some (eta_conv tm)
with Failure _ ->
if is_comb tm
then
(let
(f,x) = dest_comb tm
in
match bec f with
Some f' -> Some (mk_comb(f',x))
| None -> (match bec x with
Some x' -> Some (mk_comb(f,x'))
| None -> None))
else if is_abs tm
then
(let
(x,body) = dest_abs tm
in
(match bec body with
Some body' -> Some (mk_abs(x,body'))
| None -> None))
else None
in
(match bec tm with
Some tm' -> be_contract tm'
| None -> tm);;
let rec polymorphic x =
if is_vartype x then true else exists polymorphic (snd (dest_type x))
(* ---- From Lib etc. ---- *)
let rec append = fun xlist l ->
(match xlist with
[] -> l
| (x::xs) -> x::(append xs l));;
let assoc1 item =
let rec assc =
(function (((key,_) as e)::rst) -> if item=key then Some e else assc rst
| [] -> None)
in
assc;;
let rec listconcat =
function [] -> []
| (l::ls) -> append l (listconcat ls);;
let listnull =
function [] -> true | _ -> false;;
(* ---- exported ---- *)
let encodeXMLEntities m = m;;let encodeXMLEntities s =
let len = String.length s in
let encodeChar = function '<' -> "<" | '>' -> ">" | '&' -> "&" | '\'' -> "'" | '"' -> """ | c -> String.make 1 c in
let rec encodeStr i = if (i<len) then (encodeChar (String.get s i))::(encodeStr (i+1)) else [] in
String.concat "" (encodeStr 0);;
let encodeXMLEntitiesOut out = function x -> out (encodeXMLEntities x);;
let content_of (Proof (_,x,_)) = x;;
let rec explode_subst =
function [] -> []
| ({redex=x;residue=y}::rest) -> x::y::(explode_subst rest);;
let rec app f =
function [] -> ()
| (x::l) -> (f x; app f l);;
let disk_info_of (Proof(Info {disk_info=di},_,_)) = !di;;
let set_disk_info_of (Proof(Info {disk_info=di},_,_)) thyname thmname =
di := Some (thyname,thmname);;
let references (Proof (Info info,_,_)) = !(info.references);;
let wrap b e s = b^s^e;;
let xml_empty_tag = wrap "<" "/>";;
let xml_start_tag = wrap "<" ">";;
let xml_end_tag = wrap "</" ">";;
let xml_attr attr =
itlist (function (tag,v) ->
function s ->
concat[" ";tag;"=\"";v;"\"";s]
)
attr "";;
let xml_element tag attr children =
let
header = tag ^ (xml_attr attr)
in
(if listnull children
then xml_empty_tag header
else wrap (xml_start_tag header) (xml_end_tag tag) (concat children));;
let id_to_atts curthy id = [("n", encodeXMLEntities id)];; (* There is only one theory in Hol-Light, therefore id_to_atts is superfluous *)
let glob_counter = ref 1;;
let get_counter () =
let
res = !glob_counter
in
glob_counter := res + 1;
res;;
let get_iname = string_of_int o get_counter;;
let next_counter () = !glob_counter;;
let trivial p =
match (content_of p) with
Prefl _ -> true
| Paxm _ -> true
| Pdisk -> true
| Phyp _ -> true
| Poracle _ -> true
| _ -> false;;
let do_share p = references p > 1 & not (trivial p);;
exception Err of string*string;;
(* ---- The General List Formerly Known As Net ---- *)
type 'a exprnet = (('a list) ref) * ('a -> ('a list))
let empty_net f () = (ref [], f);;
let rec lookup'_net net x =
match net with
[] -> raise Not_found
| (a::l) -> if (a = x) then 0 else 1+(lookup'_net l x);;
let lookup_net (net,f) x = lookup'_net (!net) x;;
let insert'_net (net,f) x =
try lookup'_net !net x; () with Not_found -> ((net := (!net)@[x]);());;
let rec insert_net ((net,f) as n) x =
(app (insert_net n) (f x); insert'_net n x);;
let to_list_net (net,f) = !net;;
(* ---- The Type Net (it's not a net any more!) ---- *)
type yy_net = hol_type exprnet;;
let yy_empty = empty_net (function x -> if is_type x then snd (dest_type x) else []);;
let yy_lookup = lookup_net;;
let yy_output_types out thyname net =
let
all_types = to_list_net net in let rec
xml_index ty = xml_element "tyi" [("i",string_of_int (yy_lookup net ty))] []
and xml_const id = xml_element "tyc" (id_to_atts thyname id) []
and out_type ty =
if is_vartype ty then out (xml_element "tyv" [("n",encodeXMLEntities (dest_vartype ty))] [])
else (
match dest_type ty with
(id, []) -> out (xml_const id)
| (id, tl) -> out (xml_element "tya" [] ((xml_const id)::(map xml_index tl)))
)
in
out "<tylist i=\"";
out (string_of_int (length all_types));
out "\">";
app out_type all_types;
out "</tylist>";;
let yy_insert = insert_net;;
(* ---- The Term Net (it's not a net anymore!) ---- *)
type mm_net = term exprnet;;
let mm_empty = empty_net (
function tm ->
if is_abs tm then
(let (x,b) = dest_abs tm in [x; b])
else if is_comb tm then
(let (s,t) = dest_comb tm in [s; t])
else
[])
let mm_lookup net x = lookup_net net (be_contract x);;
let mm_insert net x = insert_net net (be_contract x);;
let mm_output_terms out thyname types net =
let all_terms = to_list_net net in
let xml_type ty = xml_element "tyi" [("i",string_of_int (yy_lookup types ty))] [] in
let xml_index tm = xml_element "tmi" [("i",string_of_int (mm_lookup net tm))] [] in
let out_term tm =
if is_var tm
then
let
(name,ty) = dest_var tm
in
out (xml_element "tmv" [("n",encodeXMLEntities name);("t", string_of_int (yy_lookup types ty))] [])
else if is_const tm
then
let (name, ty) = (dest_const tm) in
let general_ty = get_const_type name in
let atts = [("n",encodeXMLEntities name)]
in
if polymorphic general_ty then
out (xml_element "tmc" (atts@[("t",string_of_int (yy_lookup types ty))]) [])
else out (xml_element "tmc" atts [])
else if is_comb tm
then
let
(f,a) = dest_comb tm
in
out (xml_element "tma" [("f", string_of_int (mm_lookup net f));("a",string_of_int (mm_lookup net a))] [])
else
let
(x,a) = dest_abs tm
in
out (xml_element "tml" [("x", string_of_int (mm_lookup net x));("a",string_of_int (mm_lookup net a))] [])
in
out "<tmlist i=\"";
out (string_of_int(length all_terms));
out "\">";
app out_term all_terms;
out "</tmlist>";;
(* ---- collect_types_terms ---- *)
let collect_types_terms thyname out prf c_opt =
let
will_be_shared prf = (
match disk_info_of prf with
Some _ -> true
| None -> do_share prf) in let
types = yy_empty () in let
terms = mm_empty () in let
insert_type ty = yy_insert types ty in let
insert_term tm = (mm_insert terms tm;
app (yy_insert types) (types_of tm)) in let rec
ct' prf =
(match content_of prf with
Pinstt(prf,tsubst) -> (app (function {redex=x;residue=u}->(insert_type x; insert_type u))
tsubst;
ct prf)
| Psubst(prfs,tm,prf) -> (insert_term tm;
ct prf;
app ct prfs)
| Pabs(prf,tm) -> (insert_term tm;
ct prf)
| Pdisch(prf,tm) -> (insert_term tm;
ct prf)
| Pmp(prf1,prf2) -> (ct prf1; ct prf2)
| Poracle(_,tms,tm) -> (insert_term tm;
app insert_term tms)
| Pdef(_,_,tm) -> insert_term tm
| Ptmspec(_,_,prf) -> ct prf
| Ptydef(_,_,prf) -> ct prf
| Ptyintro(_,_,_,_,pt,tt,prf) -> (insert_term pt; insert_term tt;ct prf)
| Pspec(prf,tm) -> (insert_term tm; ct prf)
| Pinst(prf,subst) -> (app (fun{redex=x;residue=u}->(insert_term x;
insert_term u))
subst;
ct prf)
| Pgen(prf,tm) -> (insert_term tm; ct prf)
| Pgenabs(prf,tm_opt,tms) -> (match tm_opt with
Some tm -> insert_term tm
| None -> ();
app insert_term tms;
ct prf)
| Psym prf -> ct prf
| Ptrans(prf1,prf2) -> (ct prf1; ct prf2)
| Pcomb(prf1,prf2) -> (ct prf1; ct prf2)
| Peqmp(prf1,prf2) -> (ct prf1; ct prf2)
| Peqimp prf -> ct prf
| Pexists(prf,ex,w) -> (insert_term ex;
insert_term w;
ct prf)
| Pchoose(v,prf1,prf2) -> (insert_term v; ct prf1; ct prf2)
| Pconj(prf1,prf2) -> (ct prf1; ct prf2)
| Pconjunct1 prf -> ct prf
| Pconjunct2 prf -> ct prf
| Pdisj1(prf,tm) -> (insert_term tm;
ct prf)
| Pdisj2(prf,tm) -> (insert_term tm;
ct prf)
| Pdisjcases(prf1,prf2,prf3) -> (ct prf1; ct prf2; ct prf3)
| Pnoti prf -> ct prf
| Pnote prf -> ct prf
| Pcontr(prf,tm) -> (insert_term tm;
ct prf)
| Prefl tm -> insert_term tm
| Phyp tm -> insert_term tm
| Pdisk -> ()
| Paxm (_,tm) -> insert_term tm
| Pimpas (prf1,prf2) -> (ct prf1; ct prf2))
and ct prf =
if will_be_shared prf
then ()
else ct' prf in let
_ = ct' prf in let
_ = (match c_opt with
Some c -> insert_term c
| None -> ()) in let
_ = yy_output_types out thyname types in let
_ = mm_output_terms out thyname types terms
in
(types,terms);;
let rec export_proof path thyname thmname p c_opt il =
let outchannel = open_out (Filename.concat path (thmname^".prf")) in
let out = output_string outchannel in
let nout = encodeXMLEntitiesOut out in
let
_ = out "<proof>" in let
(types,terms) = collect_types_terms thyname out p c_opt in let
wti att tm =
(out " ";
out att;
out "=\"";
out (string_of_int (mm_lookup terms tm));
out "\"") in let
wt tm = try (out "<tmi"; wti "i" tm; out "/>") with Not_found -> raise (Err("export_proof","Term not found!")) in let
wty ty =
try (out "<tyi i=\"";
out (string_of_int (yy_lookup types ty));
out "\"/>") with Not_found -> raise (Err("export_proof","Type not found!")) in let
wdi thy thm =
(out "<pfact ";
if not (thy = thyname)
then (out "s=\"";
out thy;
out "\" ")
else ();
out "n=\"";
nout thm;
out "\"/>") in let
write_proof p il =
(let rec
share_info_of p il =
(match (disk_info_of p) with
Some (thyname,thmname) -> Some(thyname,thmname,il)
| None ->
if do_share p then
let name = get_iname() in set_disk_info_of p thyname name; Some(thyname,name,(name,p,None)::il)
else
None
)
and
dump str il prfs =
(let
_ = out (xml_start_tag str) in let
res = rev_itlist (function p -> function il -> wp il p) prfs il in let
_ = out (xml_end_tag str)
in
res)
and
wp' il =
(function
(Prefl tm) -> (out "<prefl"; wti "i" tm; out "/>"; il)
| (Pinstt(p,lambda)) ->
(let
_ = out "<pinstt>" in let
res = wp il p in let
_ = app wty (explode_subst lambda) in let
_ = out "</pinstt>"
in
res)
| (Psubst(ps,t,p)) ->
(let
_ = (out "<psubst"; wti "i" t; out ">") in let
il' = wp il p in let
res = rev_itlist (function p -> function il -> wp il p) ps il' in let
_ = out "</psubst>"
in
res)
| (Pabs(p,t)) ->
(let
_ = (out "<pabs"; wti "i" t; out ">") in let
res = wp il p in let
_ = out "</pabs>"
in
res)
| (Pdisch(p,tm)) ->
(let
_ = (out "<pdisch"; wti "i" tm; out ">") in let
res = wp il p in let
_ = out "</pdisch>"
in
res)
| (Pmp(p1,p2)) -> dump "pmp" il [p1;p2]
| (Phyp tm) -> (out "<phyp"; wti "i" tm; out "/>"; il)
| (Paxm(name,tm)) ->
(out "<paxiom n=\"";
nout name;
out "\"";
wti "i" tm;
out "/>";
il)
| (Pdef(seg,name,tm)) ->
(out "<pdef s=\"";
out seg;
out "\" n=\"";
nout name;
out "\"";
wti "i" tm;
out "/>";
il)
| (Ptmspec(seg,names,p)) ->
(let
_ = (out "<ptmspec s=\""; out seg; out "\">") in let
res = wp il p in let
_ = app (function s -> (out "<name n=\""; nout s; out "\"/>")) names in let
_ = out "</ptmspec>"
in
res)
| (Ptydef(seg,name,p)) ->
(let
_ = (out "<ptydef s=\""; out seg; out "\" n=\""; nout name; out "\">") in let
res = wp il p in let
_ = out "</ptydef>"
in
res)
| (Ptyintro(seg,name,abs,rep,pt,tt,p)) ->
(let
_ = (out "<ptyintro s=\""; out seg; out "\" n=\""; nout name;
out "\" a=\""; out abs; out "\" r=\""; out rep; out "\">") in let
_ = wt pt in let
_ = wt tt in let
res = wp il p in let
_ = out "</ptyintro>"
in
res)
| (Poracle(tg,asl,c)) -> raise (Err("export_proof", "sorry, oracle export is not implemented!"))
(* (out "<poracle>";
app (function s -> (out "<oracle n=\""; nout s; out "\"/>")) (Tag.oracles_of tg);
wt c;
app wt asl;
out "</poracle>";
il)*)
| (Pspec(p,t)) ->
(let
_ = (out "<pspec"; wti "i" t; out ">") in let
res = wp il p in let
_ = out "</pspec>"
in
res)
| (Pinst(p,theta)) ->
(let
_ = out "<pinst>" in let
res = wp il p in let
_ = app wt (explode_subst theta) in let
_ = out "</pinst>"
in
res)
| (Pgen(p,x)) ->
(let
_ = (out "<pgen"; wti "i" x; out ">") in let
res = wp il p in let
_ = out "</pgen>"
in
res)
| (Pgenabs(p,opt,vl)) ->
(let
_ = out "<pgenabs" in let
_ = (match opt with
Some c -> wti "i" c
| None -> ()) in let
_ = out ">" in let
res = wp il p in let
_ = app wt vl in let
_ = out "</pgenabs>"
in
res)
| (Psym p) -> dump "psym" il [p]
| (Ptrans(p1,p2)) -> dump "ptrans" il [p1;p2]
| (Pcomb(p1,p2)) -> dump "pcomb" il [p1;p2]
| (Peqmp(p1,p2)) -> dump "peqmp" il [p1;p2]
| (Peqimp p) -> dump "peqimp" il [p]
| (Pexists(p,ex,w)) ->
(let
_ = (out "<pexists"; wti "e" ex; wti "w" w; out ">") in let
res = wp il p in let
_ = out "</pexists>"
in
res)
| (Pchoose(v,p1,p2)) ->
(let
_ = (out "<pchoose"; wti "i" v; out ">") in let
il' = wp il p1 in let
res = wp il' p2 in let
_ = out "</pchoose>"
in
res)
| (Pconj(p1,p2)) -> dump "pconj" il [p1;p2]
| (Pimpas(p1,p2)) -> dump "pimpas" il [p1;p2]
| (Pconjunct1 p) -> dump "pconjunct1" il [p]
| (Pconjunct2 p) -> dump "pconjunct2" il [p]
| (Pdisj1(p,tm)) ->
(let
_ = (out "<pdisj1"; wti "i" tm; out ">") in let
res = wp il p in let
_ = out "</pdisj1>"
in
res)
| (Pdisj2(p,tm)) ->
(let
_ = (out "<pdisj2"; wti "i" tm; out ">") in let
res = wp il p in let
_ = out "</pdisj2>"
in
res)
| (Pdisjcases(p1,p2,p3)) -> dump "pdisjcases" il [p1;p2;p3]
| (Pnoti p) -> dump "pnoti" il [p]
| (Pnote p) -> dump "pnote" il [p]
| (Pcontr(p,tm)) ->
(let
_ = (out "<pcontr"; wti "i" tm; out ">") in let
res = wp il p in let
_ = out "</pcontr>"
in
res)
| Pdisk -> raise (Err("wp'","shouldn't try to write pdisk"))
)
and wp il p =
(let
res = match (share_info_of p il) with
Some(thyname',thmname,il') -> (wdi thyname' thmname; il')
| None -> wp' il (content_of p)
in res) in let
res = (match disk_info_of p with
Some(thyname',thmname') ->
if thyname' = thyname &
thmname' = thmname
then
wp' il (content_of p)
else
(wdi thyname' thmname';
il)
| None -> wp' il (content_of p))
in res) in let
il = write_proof p il in let
_ = (match c_opt with
Some c -> wt c
| None -> ()) in let
_ = (out "</proof>\n";(close_out outchannel)) in let
_ = set_disk_info_of p thyname thmname
in
match il with
[] -> () (* everything has been written *)
| ((thmname',prf,c_opt)::rest) -> export_proof path thyname thmname' prf c_opt rest;;
let export_proofs theory_name l' =
let theory_name = match theory_name with None -> THEORY_NAME | Some n -> n in
let path = ensure_export_directory theory_name in
let ostrm = open_out (Filename.concat path "facts.lst") in
let out = output_string ostrm in
let _ = app (function (s,_,_) -> out (s^"\n")) l' in
let _ = flush ostrm in
let _ =
(match l' with
[] -> ()
| ((thmname,p,c_opt)::rest) -> export_proof path theory_name thmname p c_opt rest) in
let num_int_thms = next_counter() - 1 in
let _ = out ((string_of_int num_int_thms)^"\n");(close_out ostrm) in
();;
let the_proof_database = ref ([]:(string*proof*(term option)) list);;
exception Duplicate_proof_name;;
let rec search_proof_name n db =
match db with [] -> () | ((m, a, b)::db') -> if n=m then (raise Duplicate_proof_name) else search_proof_name n db'
let save_proof name p c_opt =
let _ = search_proof_name name (!the_proof_database)
in
(the_proof_database :=
(name, p, c_opt)::(!the_proof_database));;
let proof_database () = !the_proof_database;;
(* this is a little bit dangerous, because the function is not injective,
but I guess one can live with that *)
let make_filesystem_compatible s =
let modify = function
| "/" -> "_slash_"
| "\\" -> "_backslash_"
| "=" -> "_equal_"
| ">" -> "_greaterthan_"
| "<" -> "_lessthan_"
| "?" -> "_questionmark_"
| "!" -> "_exclamationmark_"
| "*" -> "_star_"
| s -> s
in
implode (map modify (explode s));;
let export_saved_proofs thy =
let context = rev (proof_database ()) in
export_proofs thy (map (function (s,p,c) -> (make_filesystem_compatible s,p,c)) context);;
end;;
include Proofobjects;;