(* ======================================================================================== *)
(* Proof-objects for HOL-light, exportation to Coq *)
(* *)
(* Steven Obua, TU Mnchen, December 2004 *)
(* Chantal Keller, Laboratoire d'Informatique de Polytechnique (France), January 2010 *)
(* *)
(* based on Sebastian Skalberg's HOL4 proof-objects *)
(* ======================================================================================== *)
#load "unix.cma";;
#load "depgraph.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_saved_proofs : unit -> unit
val export_one_proof : string -> unit
val export_list : string list -> unit
end;;
module Proofobjects : Proofobject_primitives = struct
let THEORY_NAME = "hollight";;
(****** Utilities ******)
(* this is a little bit dangerous, because the function is not injective,
but I guess one can live with that *)
let modify = function
| "/" -> "_slash_"
| "\\" -> "_backslash_"
| "=" -> "_equal_"
| ">" -> "_greaterthan_"
| "<" -> "_lessthan_"
| "?" -> "_questionmark_"
| "!" -> "_exclamationmark_"
| "*" -> "_star_"
| "~" -> "_tilde_"
| "," -> "_comma_"
| "@" -> "_at_"
| "+" -> "_plus_"
| "-" -> "_minus_"
| "%" -> "_percent_"
| "$" -> "_dollar_"
| "." -> "_dot_"
| "'" -> "_quote_"
| "|" -> "_pipe_"
| ":" -> "_colon_"
| s -> s;;
let mfc s = implode (map modify (explode s));;
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;;
(****** Proofs ******)
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 proof =
| Proof of (proof_info * proof_content * (unit -> unit))
and proof_content =
| Prefl of term
| Pbeta of string * hol_type * term
| Pinstt of proof * (string * hol_type) list
| Pabs of proof * string * hol_type
| Pdisch of proof * term
| Phyp of term
| Pspec of proof * term
| Pinst of proof * (string * hol_type * term) list
| Pgen of proof * string * hol_type
| Psym of proof
| Ptrans of proof * proof
| Pcomb of proof * proof
| Peqmp of proof * proof
| Pexists of proof * term * term
| Pchoose of string * hol_type * 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
| Paxm of string * term
| Pdef of string * hol_type * term
| Ptyintro of hol_type * string * hol_type list * string * string * term;;
let content_of (Proof (_,p,_)) = p;;
let inc_references (Proof(Info{references=r},_,_) as p) = incr r; p;;
let mk_proof p = Proof(Info {disk_info = ref None; status = ref 0; references = ref 0; queued = ref false}, p, fun () -> ());;
let global_ax_counter = let counter = ref 1 in let f = fun () -> (incr counter; !counter - 1) in f;;
let new_axiom_name n = "ax_"^n^"_"^(string_of_int (global_ax_counter () ));;
(* corresponds to REFL *)
let proof_REFL t = mk_proof (Prefl t);;
(* corresponds to TRANS, with a simple improvment *)
let proof_TRANS (p,q) =
match (content_of p, content_of q) with
| (Prefl _,_) -> q
| (_, Prefl _) -> p
| _ -> mk_proof (Ptrans (inc_references p, inc_references q));;
(* corresponds to MK_COMB -> Pcomb *)
let proof_MK_COMB (p1,p2) =
match (content_of p1, content_of p2) with
| (Prefl tm1, Prefl tm2) -> mk_proof (Prefl (mk_comb (tm1, tm2)))
| _ -> mk_proof (Pcomb (inc_references p1, inc_references p2));;
(* corresponds to ASSUME -> Phyp *)
let proof_ASSUME t = mk_proof (Phyp t);;
(* corresponds to EQ_MP, with a simple improvment *)
let proof_EQ_MP p q =
match content_of p with
| Prefl _ -> q
| _ -> mk_proof (Peqmp(inc_references p, inc_references q));;
(* corresponds to IMP_ANTISYM_RULE th1 th2
not a base rule
used only in the extended mode *)
(* A1 |- t1 ==> t2 A2 |- t2 ==> t1 *)
(* ------------------------------------- IMP_ANTISYM_RULE *)
(* A1 u A2 |- t1 <=> t2 *)
let proof_IMPAS p1 p2 = mk_proof (Pimpas (inc_references p1, inc_references p2));;
(* corresponds to DISCH
not a base rule
used only in the extended mode *)
(* A |- t *)
(* -------------------- DISCH `u` *)
(* A - {u} |- u ==> t *)
let proof_DISCH p t = mk_proof (Pdisch(inc_references p, t));;
(* corresponds to DEDUCT_ANTISYM_RULE *)
(* made with IMPAS and DISCH (whereas in HOL-Light IMPAS is made with DAR and UNDISCH...) *)
(* A |- p B |- q *)
(* ---------------------------------- *)
(* (A - {q}) u (B - {p}) |- p <=> q *)
let proof_DEDUCT_ANTISYM_RULE (p1,t1) (p2,t2) =
proof_IMPAS (proof_DISCH p1 t2) (proof_DISCH p2 t1);;
(* BETA is a base rule *)
let proof_BETA tm =
try
let f,_ = dest_comb tm in
let v,bod = dest_abs f in
let (x, ty) = dest_var v in
mk_proof (Pbeta (x, ty, bod))
with
| _ -> failwith "proof_BETA"
(* corresponds to ABS, with a simple improvment *)
let proof_ABS x p =
match x with
| Var(s, ty) ->
mk_proof (Pabs(inc_references p, s, ty))
| _ -> failwith "proof_ABS: not a variable";;
(* corresponds to INST_TYPE -> Pinstt *)
let proof_INST_TYPE s p =
mk_proof (Pinstt(inc_references p, List.map (
fun (ty1, ty2) -> match ty2 with
| Tyvar s -> (s, ty1)
| _ -> failwith "proof_INST_TYPE: some redex is not a type variable"
) s));;
(* corresponds to INST *)
let proof_INST s p =
mk_proof (Pinst(inc_references p, List.map (
fun (t1, t2) -> match t2 with
| Var(s, ty) ->
(s, ty, t1)
| _ -> failwith "proof_INST: some redex is not a term variable"
) s));;
(* proof_new_definition is called in Thm.new_basic_definition. This
latter helps to define basic concepts such as T, AND... (almost
everything in Bool)... and to define derived rules!! -> Pdef *)
let proof_new_definition cname ty t =
mk_proof (Pdef (cname, ty, t));;
(* proof_new_axiom is called in Thm.new_axiom. This latter transforms
a term of type bool into a theorem. The main three axioms are
ETA_AX, SELECT_AX and INFINITY_AX. The other axiom is ax (in
drule.ml) -> Paxm *)
let proof_new_axiom axname t = mk_proof (Paxm (axname, t));;
(* corresponds to CONJ
not a base rule
used only in the extended mode *)
let proof_CONJ p1 p2 = mk_proof (Pconj (inc_references p1, inc_references p2));;
(* corresponds to CONJUNCT1
not a base rule
used only in the extended mode
also used in Thm.new_basic_definition *)
let proof_CONJUNCT1 p = mk_proof (Pconjunct1 (inc_references p));;
(* corresponds to CONJUNCT2
not a base rule
used only in the extended mode
also used in Thm.new_basic_definition *)
let proof_CONJUNCT2 p = mk_proof (Pconjunct2 (inc_references p));;
(* used only in Thm.new_basic_definition for the same purpose as for
CONJUNCTi -> Ptyintro *)
let proof_new_basic_type_definition tyname (absname, repname) (pt,tt) _ =
let rty = type_of tt in
let tyvars = sort (<=) (type_vars_in_term pt) in
mk_proof(Ptyintro(rty, tyname, tyvars, absname, repname, pt));;
(* ---- used only in substitute_proof calls ---- *)
(* corresponds to Bool.SPEC, the !-elimination rule *)
let proof_SPEC s p = mk_proof (Pspec(inc_references p, s));;
(* corresponds to Equal.SYM, the symmetry rule *)
let proof_SYM p = mk_proof (Psym(inc_references p));;
(* corresponds to Bool.GEN, the !-introduction rule *)
let proof_GEN p a =
match a with
| Var(s, ty) ->
mk_proof (Pgen(inc_references p, s, ty))
| _ -> failwith "proof_GEN: not a term variable";;
(* corresponds to Bool.DISJ1, the \/-left introduction rule *)
let proof_DISJ1 p a = mk_proof (Pdisj1 (inc_references p, a));;
(* corresponds to Bool.DISJ2, the \/-right introduction rule *)
let proof_DISJ2 p a = mk_proof (Pdisj2 (inc_references p, a));;
(* corresponds to Bool.NOT_INTRO, the following rule: *)
(* A |- t ==> F *)
(* -------------- NOT_INTRO *)
(* A |- ~t *)
let proof_NOTI p = mk_proof (Pnoti (inc_references p));;
(* corresponds to Bool.NOT_ELIM, the following rule: *)
(* A |- ~t *)
(* -------------- NOT_ELIM *)
(* A |- t ==> F *)
let proof_NOTE p = mk_proof (Pnote (inc_references p));;
(* corresponds to Bool.CONTR, the intuitionistic F-elimination rule: *)
(* A |- F *)
(* -------- CONTR `t` *)
(* A |- t *)
let proof_CONTR p a = mk_proof (Pcontr (inc_references p, a));;
(* corresponds to Bool.DISJ_CASES, the \/-elimination rule: *)
(* A |- t1 \/ t2 A1 u {t1} |- t A2 u {t2} |- t *)
(* ------------------------------------------------------ DISJ_CASES *)
(* A u A1 u A2 |- t *)
let proof_DISJCASES p q r =
mk_proof (Pdisjcases (inc_references p, inc_references q, inc_references r));;
(* corresponds to Bool.CHOOSE, the ?-elimination rule: *)
(* A1 |- ?x. s[x] A2 |- t *)
(* ------------------------------- CHOOSE (`v`,(A1 |- ?x. s)) *)
(* A1 u (A2 - {s[v/x]}) |- t *)
(* Where v is not free in A2 - {s[v/x]} or t. *)
let proof_CHOOSE a p q =
let (x,ty) = dest_var a in
mk_proof (Pchoose (x, ty, inc_references p, inc_references q));;
(* corresponds to Bool.EXISTS, the ?-introduction rule: *)
(* A |- p[u/x] *)
(* ------------- EXISTS (`?x. p`,`u`) *)
(* A |- ?x. p *)
(* x is p, y is u *)
let proof_EXISTS etm y p =
let _,x = dest_comb etm in
mk_proof (Pexists (inc_references p, x, y));;
(****** Utilities for exportation ******)
let content_of (Proof (_,x,_)) = x;;
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 reset_disk_info_of1 ((Proof(Info {disk_info=di}, _, _)) as p) =
di := None; p;;
let reset_disk_info_of2 (Proof(Info {disk_info=di}, _, _)) =
di := None;;
let references (Proof (Info info,_,_)) = !(info.references);;
let glob_counter = ref 0;;
let get_counter () = incr glob_counter; !glob_counter;;
let get_iname = string_of_int o get_counter;;
let next_counter () = !glob_counter;;
let trivial p =
match (content_of p) with
| Prefl _ -> true
| Pbeta _ -> true
| Paxm _ -> true
| Phyp _ -> true
| _ -> false;;
let do_share p = references p > 1 & not (trivial p);;
(****** Types and terms modification ******)
let idT = Hashtbl.create 17;;
let defT = Hashtbl.create 17;;
let idT_ref = ref 1;;
let defT_ref = ref 1;;
let make_idT x =
try Hashtbl.find idT x with | Not_found -> let n = !idT_ref in incr idT_ref; Hashtbl.add idT x n; n;;
let make_defT x =
try Hashtbl.find defT x with | Not_found -> let n = !defT_ref in incr defT_ref; Hashtbl.add defT x n; n;;
type ntype =
| Ntvar of int
| Nbool
| Nnum
| Narrow of ntype * ntype
| Ntdef of int * ntype list;;
let rec hol_type2ntype = function
| Tyvar x -> Ntvar (make_idT x)
| Tyapp (s, _) when s = "bool" -> Nbool
(* | Tyapp (s, _) when s = "ind" -> Nnum *)
| Tyapp (s, l) when s = "fun" ->
(match l with
| [a;b] -> Narrow (hol_type2ntype a, hol_type2ntype b)
| _ -> failwith "hol_type2ntype: wrong number of arguments for fun")
| Tyapp (s, l) -> Ntdef (make_defT s, List.map hol_type2ntype l);;
let idV = Hashtbl.create 17;;
let defV = Hashtbl.create 17;;
let idV_ref = ref 1;;
let defV_ref = ref 1;;
let make_idV x X =
try
fst (Hashtbl.find idV x)
with | Not_found ->
let n = !idV_ref in incr idV_ref; Hashtbl.add idV x (n,X); n;;
let make_defV x X f =
try let (a,_,_) = (Hashtbl.find defV x) in a with | Not_found -> let n = !defV_ref in incr defV_ref; Hashtbl.add defV x (n,X,f); n;;
type ncst =
| Heq of ntype
| Heps of ntype
| Hand
| Hor
| Hnot
| Himp
| Htrue
| Hfalse
| Hforall of ntype
| Hexists of ntype;;
type nterm =
| Ndbr of int
| Nvar of int * ntype
| Ncst of ncst
| Ndef of int * ntype
| Napp of nterm * nterm
| Nabs of ntype * nterm;;
let rec ext_var x (ty: ntype) i = function
| [] -> Nvar (make_idV x ty, ty)
| (y,typ)::l -> if ((x = y) && (ty = typ)) then Ndbr i else ext_var x ty (i+1) l;;
let rec term2nterm l = function
| Var (x, ty) -> ext_var x (hol_type2ntype ty) 0 l
| Comb (t1, t2) -> Napp (term2nterm l t1, term2nterm l t2)
| Abs (t1, t2) ->
(match t1 with
| Var (x, ty) ->
let typ = hol_type2ntype ty in
Nabs (typ, term2nterm ((x,typ)::l) t2)
| _ -> failwith "term2nterm: first argument of an abstraction is not a variable")
| Const (s, ty) when s = "=" ->
(match hol_type2ntype ty with
| Narrow(a, _) -> Ncst (Heq a)
| _ -> failwith "term2nterm: constant = must have arrow type")
| Const (s, ty) when s = "@" ->
(match hol_type2ntype ty with
| Narrow(_, a) -> Ncst (Heps a)
| _ -> failwith "term2nterm: constant @ must have arrow type")
| Const (s, ty) when s = "/\\" -> Ncst Hand
| Const (s, ty) when s = "\\/" -> Ncst Hor
| Const (s, ty) when s = "~" -> Ncst Hnot
| Const (s, ty) when s = "==>" -> Ncst Himp
| Const (s, ty) when s = "T" -> Ncst Htrue
| Const (s, ty) when s = "F" -> Ncst Hfalse
| Const (s, ty) when s = "_FALSITY_" -> Ncst Hfalse
| Const (s, ty) when s = "!" ->
(match hol_type2ntype ty with
| Narrow(Narrow (a, _), _) -> Ncst (Hforall a)
| _ -> failwith "term2nterm: constant ! must have arrow type")
| Const (s, ty) when s = "?" ->
(match hol_type2ntype ty with
| Narrow(Narrow (a, _), _) -> Ncst (Hexists a)
| _ -> failwith "term2nterm: constant ? must have arrow type")
| Const (s, ty) ->
let typ = hol_type2ntype ty in
Ndef(make_defV s typ true, typ);;
let term2nterm t = term2nterm [] t;;
(****** Proof exportation ******)
let rec print_list out str snil scons = function
| [] -> out snil
| t::q -> out "("; out scons; out " "; str t; out " "; print_list out str snil scons q; out ")";;
let print_names out x = out (string_of_int x); out "%positive";;
let print_type (out: string -> unit) ty =
let rec print_ntype = function
| Ntvar x -> out "(TVar "; print_names out x; out ")"
| Nbool -> out "Bool"
| Nnum -> out "Num"
| Narrow(a, b) -> out "("; print_ntype a; out " --> "; print_ntype b; out ")"
| Ntdef(s, l) -> out "(TDef "; print_names out s; out " "; print_list out print_ntype "Tnil" "Tcons" l; out ")" in
print_ntype ty;;
let print_cst out = function
| Heq ty -> out "(Heq "; print_type out ty; out ")"
| Heps ty -> out "(Heps "; print_type out ty; out ")"
| Hand -> out "Hand"
| Hor -> out "Hor"
| Hnot -> out "Hnot"
| Himp -> out "Himp"
| Htrue -> out "Htrue"
| Hfalse -> out "Hfalse"
| Hforall ty -> out "(Hforall "; print_type out ty; out ")"
| Hexists ty -> out "(Hexists "; print_type out ty; out ")";;
let print_term out t =
let rec print_nterm = function
| Ndbr n -> out "(Dbr "; out (string_of_int n); out ")"
| Nvar(x, ty) -> out "(Var "; print_names out x; out " "; print_type out ty; out ")"
| Ncst c -> out "(Cst "; print_cst out c; out ")"
| Ndef(a, ty) -> out "(Def "; print_names out a; out " "; print_type out ty; out ")"
| Napp(t1, t2) -> out "(App "; print_nterm t1; out " "; print_nterm t2; out ")"
| Nabs(ty, t) -> out "(Abs "; print_type out ty; out " "; print_nterm t; out ")" in
print_nterm t;;
(* Exportation *)
let total = ref 0;;
type nproof_content =
| Nprefl of nterm
| Npbeta of int * ntype * nterm
| Npinstt of nproof_content * (int * ntype) list
| Npabs of nproof_content * int * ntype
| Npdisch of nproof_content * nterm
| Nphyp of nterm
| Npspec of nproof_content * nterm
| Npinst of nproof_content * (int * ntype * nterm) list
| Npgen of nproof_content * int * ntype
| Npsym of nproof_content
| Nptrans of nproof_content * nproof_content
| Npcomb of nproof_content * nproof_content
| Npeqmp of nproof_content * nproof_content
| Npexists of nproof_content * nterm * nterm
| Npchoose of int * ntype * nproof_content * nproof_content
| Npconj of nproof_content * nproof_content
| Npconjunct1 of nproof_content
| Npconjunct2 of nproof_content
| Npdisj1 of nproof_content * nterm
| Npdisj2 of nproof_content * nterm
| Npdisjcases of nproof_content * nproof_content * nproof_content
| Npnoti of nproof_content
| Npnote of nproof_content
| Npcontr of nproof_content * nterm
| Npimpas of nproof_content * nproof_content
| Npaxm of string * nterm
| Npdef of int * ntype * nterm
| Nptyintro of ntype * ntype * int * int * nterm
| Nfact of string;;
let the_types = Hashtbl.create 17;;
let count_types = ref (-1);;
let share_types out ty =
let rec share_types ty =
try Hashtbl.find the_types ty with
| Not_found ->
incr count_types;
let name = THEORY_NAME^"_type_"^(string_of_int !count_types) in
(match ty with
| Narrow(a,b) ->
let n1 = share_types a in
let n2 = share_types b in
out "\nDefinition "; out name; out " := "; out n1; out " --> "; out n2; out "."
| Ntdef(i,l) ->
let names = List.map share_types l in
out "\nDefinition "; out name; out " := TDef "; print_names out i; out " "; print_list out out "Tnil" "Tcons" names; out "."
| t -> out "\nDefinition "; out name; out " := "; print_type out t; out ".");
Hashtbl.add the_types ty name;
name in
share_types ty;;
let the_terms = Hashtbl.create 17;;
let count_terms = ref (-1);;
let share_csts out out_types name = function
| Heq a ->
let n = share_types out_types a in
out "\nDefinition "; out name; out " := Cst (Heq "; out n; out ")."
| Heps a ->
let n = share_types out_types a in
out "\nDefinition "; out name; out " := Cst (Heps "; out n; out ")."
| Hand -> out "\nDefinition "; out name; out " := Cst Hand."
| Hor -> out "\nDefinition "; out name; out " := Cst Hor."
| Hnot -> out "\nDefinition "; out name; out " := Cst Hnot."
| Himp -> out "\nDefinition "; out name; out " := Cst Himp."
| Htrue -> out "\nDefinition "; out name; out " := Cst Htrue."
| Hfalse -> out "\nDefinition "; out name; out " := Cst Hfalse."
| Hforall a ->
let n = share_types out_types a in
out "\nDefinition "; out name; out " := Cst (Hforall "; out n; out ")."
| Hexists a ->
let n = share_types out_types a in
out "\nDefinition "; out name; out " := Cst (Hexists "; out n; out ")."
let share_terms out out_types tm =
let rec share_terms tm =
try Hashtbl.find the_terms tm with
| Not_found ->
incr count_terms;
let name = THEORY_NAME^"_term_"^(string_of_int !count_terms) in
(match tm with
| Napp(t1,t2) ->
let n1 = share_terms t1 in
let n2 = share_terms t2 in
out "\nDefinition "; out name; out " := App "; out n1; out " "; out n2; out "."
| Nabs(ty,t) ->
let n = share_terms t in
let ny = share_types out_types ty in
out "\nDefinition "; out name; out " := Abs "; out ny; out " "; out n; out "."
| Nvar(i,ty) ->
let ny = share_types out_types ty in
out "\nDefinition "; out name; out " := Var "; print_names out i; out " "; out ny; out "."
| Ndef(i,ty) ->
let ny = share_types out_types ty in
out "\nDefinition "; out name; out " := Def "; print_names out i; out " "; out ny; out "."
| Ncst c -> share_csts out out_types name c
| t -> out "\nDefinition "; out name; out " := "; print_term out t; out ".");
Hashtbl.add the_terms tm name;
name in
share_terms tm;;
let export_proof out share_type share_term p =
let rec wp = function
| Nprefl tm ->
let tm2 = share_term tm in
out "(Prefl "; out tm2; out ")"
| Npbeta (n, ty, tm) ->
let tm2 = share_term tm in
let ty2 = share_type ty in
out "(Pbeta "; print_names out n; out " "; out ty2; out " "; out tm2; out ")"
| Npinstt(p,lambda) ->
out "(Pinstt ";
wp p;
out " "; print_list out (fun (s, ty) ->
let ty2 = share_type ty in
out "("; print_names out s; out ", "; out ty2; out ")") "nil" "cons" lambda; out ")"
| Npabs(p,x,ty) ->
let ty2 = share_type ty in
out "(Pabs ";
wp p;
out " "; print_names out x;
out " "; out ty2; out ")"
| Npdisch(p,tm) ->
let tm2 = share_term tm in
out "(Pdisch ";
wp p;
out " "; out tm2; out ")"
| Nphyp tm ->
let tm2 = share_term tm in
out "(Phyp "; out tm2; out ")"
| Npaxm(_, _) -> ()
| Npdef(_, _, _) -> ()
| Nptyintro(_, _, _, _, _) -> ()
| Npspec(p,t) ->
let t2 = share_term t in
out "(Pspec ";
wp p;
out " "; out t2; out ")"
| Npinst(p,theta) ->
out "(Pinst ";
wp p;
out " "; print_list out (fun (s, ty, t) ->
let t2 = share_term t in
let ty2 = share_type ty in
out "("; print_names out s; out ", "; out ty2; out ", "; out t2; out ")") "nil" "cons" theta; out ")"
| Npgen(p,x,ty) ->
let ty2 = share_type ty in
out "(Pgen ";
wp p;
out " "; print_names out x; out " "; out ty2; out ")"
| Npsym p ->
out "(Psym ";
wp p;
out ")"
| Nptrans(p1,p2) ->
out "(Ptrans ";
wp p1;
out " ";
wp p2;
out ")"
| Npcomb(p1,p2) ->
out "(Pcomb ";
wp p1;
out " ";
wp p2;
out ")"
| Npeqmp(p1,p2) ->
out "(Peqmp ";
wp p1;
out " ";
wp p2;
out ")"
| Npexists(p,ex,w) ->
let ex2 = share_term ex in
let w2 = share_term w in
out "(Pexists ";
wp p;
out " "; out ex2; out " "; out w2; out ")"
| Npchoose(x,ty,p1,p2) ->
let ty2 = share_type ty in
out "(Pchoose "; print_names out x; out " "; out ty2; out " ";
wp p1;
out " ";
wp p2;
out ")"
| Npconj(p1,p2) ->
out "(Pconj ";
wp p1;
out " ";
wp p2;
out ")"
| Npimpas(p1,p2) ->
out "(Pimpas ";
wp p1;
out " ";
wp p2;
out ")"
| Npconjunct1 p ->
out "(Pconjunct1 ";
wp p;
out ")"
| Npconjunct2 p ->
out "(Pconjunct2 ";
wp p;
out ")"
| Npdisj1(p,tm) ->
let tm2 = share_term tm in
out "(Pdisj1 ";
wp p;
out " "; out tm2; out ")"
| Npdisj2(p,tm) ->
let tm2 = share_term tm in
out "(Pdisj2 ";
wp p;
out " "; out tm2; out ")"
| Npdisjcases(p1,p2,p3) ->
out "(Pdisjcases ";
wp p1;
out " ";
wp p2;
out " ";
wp p3;
out ")"
| Npnoti p ->
out "(Pnoti ";
wp p;
out ")"
| Npnote p ->
out "(Pnote ";
wp p;
out ")"
| Npcontr(p,tm) ->
let tm2 = share_term tm in
out "(Pcontr ";
wp p;
out " "; out tm2; out ")"
| Nfact(thm) -> out "(Poracle "; out thm; out "_def)" in
wp p;;
let export_ht out share_term h t thmname =
out "\n\n\nDefinition "; out thmname; out "_h := ";
(match h with
| [] -> out "hyp_empty"
| _ -> print_list out (fun tm ->
let tm2 = share_term tm in
out tm2) "nil" "cons" h);
out ".\n\nDefinition "; out thmname; out "_t := ";
let t2 = share_term t in
out t2; out ".";;
let export_lemma out share_type share_term p thmname =
out "\n\nLemma "; out thmname; out "_lemma : deriv "; out thmname; out "_h "; out thmname;
out "_t.\nProof.\n vm_cast_no_check (proof2deriv_correct "; export_proof out share_type share_term p; out ").\nQed.";;
let export_lemma_def out tree thmname =
out "\n\nLemma "; out thmname; out "_lemma : deriv "; out thmname; out "_h "; out thmname;
out "_t.\nProof.\n vm_cast_no_check (proof2deriv_correct "; out tree; out ").\nQed.";;
let export_sig out thmname =
out "\n\nDefinition "; out thmname; out "_def := my_exist "; out thmname; out "_lemma.";;
let export_def out thmname =
out "\n\nParameter "; out thmname; out "_lemma : deriv "; out thmname; out "_h "; out thmname; out "_t.";;
let export_tdef out thmname =
out "\n\nParameter "; out thmname; out "_lemma : deriv "; out thmname; out "_h "; out thmname; out "_t.";;
let export_axiom out thmname =
out "\n\nAxiom "; out thmname; out "_lemma : deriv "; out thmname; out "_h "; out thmname; out "_t.";;
(* Transforming a proof into a derivation *)
let rec opt_nth n l =
match (n, l) with
| 0, (x::_) -> Some x
| 0, [] -> None
| p, (_::l) -> opt_nth (p-1) l
| _, _ -> None;;
let type_cst = function
| Heq a -> Narrow(a, Narrow(a, Nbool))
| Heps a -> Narrow(Narrow(a, Nbool), a)
| Hand -> Narrow(Nbool, Narrow(Nbool, Nbool))
| Hor -> Narrow(Nbool, Narrow(Nbool, Nbool))
| Hnot -> Narrow(Nbool, Nbool)
| Himp -> Narrow(Nbool, Narrow(Nbool, Nbool))
| Htrue -> Nbool
| Hfalse -> Nbool
| Hforall a -> Narrow(Narrow(a, Nbool), Nbool)
| Hexists a -> Narrow(Narrow(a, Nbool), Nbool);;
let rec infer g = function
| Ndbr n -> opt_nth n g
| Nvar (_, a) -> Some a
| Ncst c -> Some (type_cst c)
| Ndef (_, a) -> Some a
| Napp (t1, t2) ->
(match infer g t1, infer g t2 with
| Some (Narrow (u1, u2)), Some v -> if u1 = v then Some u2 else None
| _, _ -> None)
| Nabs (a, u) ->
(match infer (a::g) u with
| Some b -> Some (Narrow (a, b))
| None -> None);;
let rec close_aux t x a i =
match t with
| Ndbr n -> Ndbr (if n < i then n else n+1)
| Nvar (y, b) -> if ((x = y) && (a = b)) then Ndbr i else Nvar (y, b)
| Napp (t1, t2) -> Napp (close_aux t1 x a i, close_aux t2 x a i)
| Nabs (b, u) -> Nabs(b, close_aux u x a (i+1))
| u -> u;;
let close t x a = close_aux t x a 0;;
let rec subst_idt_type_aux x = function
| [] -> Ntvar x
| (y,a)::q -> if x = y then a else subst_idt_type_aux x q;;
let rec subst_idt_type t s =
match t with
| Ntvar x -> subst_idt_type_aux x s
| Ntdef (a, l) -> Ntdef (a, subst_idt_list_type l s)
| Narrow (a, b) -> Narrow (subst_idt_type a s, subst_idt_type b s)
| u -> u
and subst_idt_list_type l s = List.map (fun t -> subst_idt_type t s) l;;
let rec subst_idt t s =
match t with
| Nvar (x, y) -> Nvar (x, subst_idt_type y s)
| Ncst (Heq a) -> Ncst (Heq (subst_idt_type a s))
| Ncst (Heps a) -> Ncst (Heps (subst_idt_type a s))
| Ncst (Hforall a) -> Ncst (Hforall (subst_idt_type a s))
| Ncst (Hexists a) -> Ncst (Hexists(subst_idt_type a s))
| Ndef (c, d) -> Ndef (c, subst_idt_type d s)
| Napp (t1, t2) -> Napp (subst_idt t1 s, subst_idt t2 s)
| Nabs (a, t) -> Nabs (subst_idt_type a s, subst_idt t s)
| u -> u;;
let subst_idt_context g s = List.map (fun a -> subst_idt_type a s) g;;
let rec subst_idv_aux x y s =
match s with
| [] -> Nvar (x, y)
| (z, t, u)::q -> if ((x = z) && (y = t)) then u else subst_idv_aux x y q;;
let rec subst_idv t s =
match t with
| Nvar (x, y) -> subst_idv_aux x y s
| Napp (t1, t2) -> Napp (subst_idv t1 s, subst_idv t2 s)
| Nabs (a, t) -> Nabs (a, subst_idv t s)
| u -> u;;
let rec wf_substitution_idv = function
| [] -> true
| (_,y,t)::q ->
match infer [] t with
| Some z -> if (y = z) then wf_substitution_idv q else false
| None -> false;;
let rec is_not_free x y = function
| Nvar (z, t) -> (x != z) or (not (y = t))
| Napp (t1, t2) -> (is_not_free x y t1) && (is_not_free x y t2)
| Nabs (_, u) -> is_not_free x y u
| _ -> true;;
let rec lift_term u i j =
match u with
| Ndbr n -> if n >= i then Ndbr (j + n) else Ndbr n
| Napp (u1, u2) -> Napp (lift_term u1 i j, lift_term u2 i j)
| Nabs (a, t) -> Nabs (a, lift_term t (i+1) j)
| u -> u;;
let rec subst_db t n u =
match t with
| Ndbr i -> if i < n then Ndbr i else if i = n then u else Ndbr (i-1)
| Napp (t1, t2) -> Napp (subst_db t1 n u, subst_db t2 n u)
| Nabs (a, t) -> Nabs (a, subst_db t (n+1) (lift_term u 0 1))
| u -> u;;
let nopen t u = subst_db t 0 u;;
let heq a t u = Napp (Napp (Ncst (Heq a), t), u);;
let hequiv t u = Napp (Napp (Ncst (Heq Nbool), t), u);;
let himp t u = Napp (Napp (Ncst Himp, t), u);;
let hand t u = Napp (Napp (Ncst Hand, t), u);;
let hor t u = Napp (Napp (Ncst Hor, t), u);;
let hnot t = Napp (Ncst Hnot, t);;
let htrue = Ncst Htrue;;
let hfalse = Ncst Hfalse;;
let hforall a p = Napp (Ncst (Hforall a), Nabs (a, p));;
let hexists a p = Napp (Ncst (Hexists a), Nabs (a, p));;
let hyp_empty = [];;
let rec hyp_remove e = function
| [] -> []
| t::q -> if (e = t) then q else t::(hyp_remove e q);;
let rec hyp_add e = function
| [] -> [e]
| t::q -> if (e = t) then t::q else t::(hyp_add e q);;
let hyp_union l m = List.fold_left (fun n e -> hyp_add e n) m l;;
let hyp_map f l = List.fold_left (fun m e -> hyp_add (f e) m) [] l;;
let hyp_singl e = [e];;
let rec hyp_is_not_free x y = function
| [] -> true
| t::q -> (is_not_free x y t) && (hyp_is_not_free x y q);;
let hyp_subst_idt h s = hyp_map (fun t -> subst_idt t s) h;;
let hyp_subst_idv h s = hyp_map (fun t -> subst_idv t s) h;;
let rec eq_type a b = match (a,b) with
| Ntvar i, Ntvar j -> i = j
| Nbool, Nbool -> true
| Nnum, Nnum -> true
| Narrow(a1, b1), Narrow(a2, b2) -> (eq_type a1 a2) && (eq_type b1 b2)
| Ntdef(i,l), Ntdef(j,m) -> (i = j) && (eq_list_type l m)
| _, _ -> false
and eq_list_type l m = match (l,m) with
| [], [] -> true
| t1::q1, t2::q2 -> (eq_type t1 t2) && (eq_list_type q1 q2)
| _, _ -> false;;
let eq_cst a b = match (a,b) with
| Heq a, Heq b -> eq_type a b
| Heps a, Heps b -> eq_type a b
| Hand, Hand -> true
| Hor, Hor -> true
| Hnot, Hnot -> true
| Himp, Himp -> true
| Htrue, Htrue -> true
| Hfalse, Hfalse -> true
| Hforall a, Hforall b -> eq_type a b
| Hexists a, Hexists b -> eq_type a b
| _, _ -> false;;
let rec eq_term a b = match (a,b) with
| Ndbr i, Ndbr j -> i = j
| Nvar(i,a), Nvar(j,b) -> (i = j) && (eq_type a b)
| Ncst c, Ncst d -> eq_cst c d
| Ndef(i,a), Ndef(j,b) -> (i = j) && (eq_type a b)
| Napp(a1,b1), Napp(a2,b2) -> (eq_term a1 a2) && (eq_term b1 b2)
| Nabs(t1,a1), Nabs(t2,a2) -> (eq_type t1 t2) && (eq_term a1 a2)
| _, _ -> false;;
let derivs = Hashtbl.create 17;;
let rec proof2deriv = function
| Nprefl t ->
(match infer [] t with
| Some a -> Some (hyp_empty, heq a t t)
| None -> (print_string "Nprefl\n"); None)
| Npbeta (x, y, t) ->
(match infer [] t with
| Some a -> Some (hyp_empty,
heq a (Napp (Nabs (y, close t x y), Nvar (x, y))) t)
| None -> (print_string "Npbeta\n"); None)
| Npinstt (q, l) ->
(match proof2deriv q with
| Some (h,v) -> Some (hyp_subst_idt h l, subst_idt v l)
| None -> (print_string "Npinstt\n"); None)
| Npabs (q, x, y) ->
(match proof2deriv q with
| Some (h, t) ->
(match t with
| Napp (Napp (Ncst (Heq a), t1), t2) ->
if hyp_is_not_free x y h then
Some (h, heq (Narrow (y, a)) (Nabs (y, close t1 x y)) (Nabs (y, close t2 x y)))
else ((print_string "Npabs\n"); None)
| _ -> (print_string "Npabs\n"); None)
| None -> (print_string "Npabs\n"); None)
| Npdisch (q, t) ->
(match proof2deriv q, infer [] t with
| Some (h, u), Some Nbool -> Some (hyp_remove t h, himp t u)
| _, _ -> (print_string "Npdisch\n"); None)
| Nphyp t ->
(match infer [] t with
| Some Nbool -> Some (hyp_singl t, t)
| _ -> (print_string "Nphyp\n"); None)
| Npspec (q, t) ->
(match proof2deriv q, infer [] t with
| Some (h, u), Some a ->
(match u with
| Napp (Ncst (Hforall b), Nabs (c, v)) ->
if ((eq_type a b) && (eq_type b c)) then
Some (h, nopen v t)
else ((print_string "Npspec\n"); None)
| _ -> (print_string "Npspec\n"); None)
| _, _ -> (print_string "Npspec\n"); None)
| Npinst (q, l) ->
(match proof2deriv q, wf_substitution_idv l with
| Some (h, v), true -> Some (hyp_subst_idv h l, subst_idv v l)
| _, _ -> (print_string "Npinst\n"); None)
| Npgen (q, x, y) ->
(match proof2deriv q with
| Some (h, t) ->
if hyp_is_not_free x y h then
Some (h, hforall y (close t x y))
else ((print_string "Npgen\n"); None)
| None -> (print_string "Npgen\n"); None)
| Npsym q ->
(match proof2deriv q with
| Some (h, t) ->
(match t with
| Napp (Napp (Ncst (Heq a), u), v) -> Some (h, heq a v u)
| _ -> (print_string "Npsym\n"); None)
| None -> (print_string "Npsym\n"); None)
| Nptrans (q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, t1), Some (h2, t2) ->
(match t1, t2 with
| Napp (Napp (Ncst (Heq a), u1), u2),
Napp (Napp (Ncst (Heq b), v2), v3) ->
if ((eq_type a b) && (eq_term u2 v2)) then
Some (hyp_union h1 h2, heq a u1 v3)
else ((print_string "Nptrans\n"); None)
| _, _ -> (print_string "Nptrans\n"); None)
| _, _ -> (print_string "Nptrans\n"); None)
| Npcomb (q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, t1), Some (h2, t2) ->
(match t1, t2 with
| Napp (Napp (Ncst (Heq (Narrow (a, b))), f), g),
Napp (Napp (Ncst (Heq c), u), v) ->
if (eq_type a c) then
Some (hyp_union h1 h2, heq b (Napp (f, u)) (Napp (g, v)))
else ((print_string "Npcomb\n"); None)
| _, _ -> (print_string "Npcomb\n"); None)
| _, _ -> (print_string "Npcomb\n"); None)
| Npeqmp (q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, t1), Some (h2, t2) ->
(match t1 with
| Napp (Napp (Ncst (Heq Nbool), a), b) ->
if (eq_term a t2) then
Some (hyp_union h1 h2, b)
else ((print_string "Npeqmp\n"); None)
| _ -> (print_string "Npeqmp\n"); None)
| _, _ -> (print_string "Npeqmp\n"); None)
| Npexists (q, b, t) ->
(match proof2deriv q, b, infer [] t with
| Some (h, u), Nabs (bb, a), Some aa ->
if ((eq_type aa bb) && (eq_term (nopen a t) u)) then
Some (h, hexists aa a)
else ((print_string "Npexists\n"); None)
| _, _, _ -> (print_string "Npexists\n"); None)
| Npchoose (v, aa, q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, t), Some (h2, c) ->
(match t with
| Napp (Ncst (Hexists bb), Nabs (cc, a)) ->
let s = hyp_remove (nopen a (Nvar (v, aa))) h2 in
if ((eq_type aa bb) && (eq_type bb cc) && (hyp_is_not_free v aa s) && (is_not_free v aa c)
&& (is_not_free v aa a)) then
Some (hyp_union h1 s, c)
else ((print_string "Npchoose\n"); None)
| _ -> (print_string "Npchoose\n"); None)
| _, _ -> (print_string "Npchoose\n"); None)
| Npconj (q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, a), Some (h2, b) ->
Some (hyp_union h1 h2, hand a b)
| _, _ -> (print_string "Npconj\n"); None)
| Npconjunct1 q ->
(match proof2deriv q with
| Some (h, v) ->
(match v with
| Napp (Napp (Ncst Hand, t), u) ->
Some (h, t)
| _ -> (print_string "Npconjunct1\n"); None)
| _ -> (print_string "Npconjunct1\n"); None)
| Npconjunct2 q ->
(match proof2deriv q with
| Some (h, v) ->
(match v with
| Napp (Napp (Ncst Hand, t), u) ->
Some (h, u)
| _ -> (print_string "Npconjunct2\n"); None)
| _ -> (print_string "Npconjunct2\n"); None)
| Npdisj1 (q, b) ->
(match proof2deriv q, infer [] b with
| Some (h, a), Some Nbool -> Some (h, hor a b)
| _, _ -> (print_string "Npdisj1\n"); None)
| Npdisj2 (q, a) ->
(match proof2deriv q, infer [] a with
| Some (h, b), Some Nbool -> Some (h, hor a b)
| _, _ -> (print_string "Npdisj1\n"); None)
| Npdisjcases (q1, q2, q3) ->
(match proof2deriv q1, proof2deriv q2, proof2deriv q3 with
| Some (h1, t), Some (h2, c1), Some (h3, c2) ->
(match t with
| Napp (Napp (Ncst Hor, a), b) ->
if (eq_term c1 c2) then
Some (hyp_union h1 (hyp_union (hyp_remove a h2) (hyp_remove b h3)), c1)
else ((print_string "Npdisjcases\n"); None)
| _ -> (print_string "Npdisjcases\n"); None)
| _, _, _ -> (print_string "Npisjcases\n"); None)
| Npnoti q ->
(match proof2deriv q with
| Some (h, t) ->
(match t with
| Napp (Napp (Ncst Himp, a), Ncst Hfalse) -> Some (h, hnot a)
| _ -> (print_string "Npnoti\n"); None)
| _ -> (print_string "Npnoti\n"); None)
| Npnote q ->
(match proof2deriv q with
| Some (h, t) ->
(match t with
| Napp (Ncst Hnot, a) -> Some (h, himp a hfalse)
| _ -> (print_string "Npnote\n"); None)
| _ -> (print_string "Npnote\n"); None)
| Npcontr (q, a) ->
(match proof2deriv q, infer [] a with
| Some (h, t), Some Nbool ->
(match t with
| Ncst Hfalse -> Some (hyp_remove (hnot a) h, a)
| _ -> (print_string "Npcontr\n"); None)
| _, _ -> (print_string "Npcontr\n"); None)
| Npimpas (q1, q2) ->
(match proof2deriv q1, proof2deriv q2 with
| Some (h1, t), Some (h2, u) ->
(match t, u with
| Napp (Napp (Ncst Himp, a1), b1),
Napp (Napp (Ncst Himp, b2), a2) ->
if ((eq_term a1 a2) && (eq_term b1 b2)) then
Some (hyp_union h1 h2, hequiv b1 a1)
else ((print_string ("Npimpas1; 1: "^(string_of_bool (eq_term a1 a2))^"; 2: "^(string_of_bool (eq_term b1 b2))^"\n"));
let out = print_string in
print_term out a1; out "\n"; print_term out a2; out "\n"; print_term out b1; out "\n"; print_term out b2; out "\n"; None)
| _, _ -> (print_string "Npimpas2\n"); None)
| _, _ -> (print_string "Npimpas3\n"); None)
| Nfact thm ->
(try Some (Hashtbl.find derivs thm) with
| Not_found -> (print_string ("Nfact "^thm^"\n")); None)
| Npdef (i, a, t) -> Some (hyp_empty, heq a (Ndef (i, a)) t)
| Npaxm (_, t) -> Some (hyp_empty, t)
| Nptyintro (rty, aty, mk_name, dest_name, p) ->
let mk_type = Narrow(rty, aty) in
let dest_type = Narrow(aty, rty) in
let a_name = make_idV "a" aty in
let a = Nvar(a_name, aty) in
let r_name = make_idV "r" rty in
let r = Nvar(r_name, rty) in
Some (hyp_empty, hand (heq aty (Napp (Ndef (mk_name, mk_type), Napp (Ndef (dest_name, dest_type), a))) a)
(hequiv (Napp (p, r)) (heq rty (Napp (Ndef (dest_name, dest_type), Napp (Ndef (mk_name, mk_type), r))) r)));;
(* Dealing with dependencies *)
let rec make_dependencies_aux dep_graph proof_of_thm = function
| [] -> ()
| (thmname, p, c_opt)::il ->
incr total;
let wdi thm =
Depgraph.Dep.add_dep dep_graph thm thmname;
Nfact thm 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 = THEORY_NAME^"_"^(get_iname ()) in
set_disk_info_of p THEORY_NAME name;
Depgraph.Dep.add_thm dep_graph name;
Some(THEORY_NAME,name,(name,p,None)::il)
else
None
and wp' il = function
| Prefl tm -> Nprefl (term2nterm tm), il
| Pbeta(x, ty, tm) ->
let typ = hol_type2ntype ty in
Npbeta(make_idV x typ , typ, term2nterm tm), il
| Pinstt(p,lambda) ->
let p', res = wp il p in
Npinstt(p', List.map (
fun (s,ty) -> (make_idT s, hol_type2ntype ty)
) lambda), res
| Pabs(p,x,ty) ->
let p', res = wp il p in
let typ = hol_type2ntype ty in
Npabs(p',make_idV x typ,typ), res
| Pdisch(p,tm) ->
let p', res = wp il p in
Npdisch(p', term2nterm tm), res
| Phyp tm -> Nphyp (term2nterm tm), il
| Paxm(th,tm) -> Npaxm(th, term2nterm tm), il
| Pdef(name,ty,tm) ->
let typ = hol_type2ntype ty in
Npdef(make_defV name typ true, typ, term2nterm tm), il
| Ptyintro(rty2, tyname, tyvars, absname, repname, pt) ->
let rty = hol_type2ntype rty2 in
let new_name = make_defT tyname in
let ntyvars = List.map hol_type2ntype tyvars in
let aty = Ntdef(new_name, ntyvars) in
let mk_name = make_defV absname (Narrow(rty, aty)) false in
let dest_name = make_defV repname (Narrow(aty, rty)) false in
Nptyintro(rty, aty, mk_name, dest_name, term2nterm pt), il
| Pspec(p,t) ->
let p', res = wp il p in
Npspec(p', term2nterm t), res
| Pinst(p,theta) ->
let p', res = wp il p in
Npinst(p', List.map (
fun (s,ty,te) ->
let typ = hol_type2ntype ty in
(make_idV s typ, typ, term2nterm te)
) theta), res
| Pgen(p,x,ty) ->
let p', res = wp il p in
let typ = hol_type2ntype ty in
Npgen(p', make_idV x typ, typ), res
| Psym p ->
let p', res = wp il p in
Npsym p', res
| Ptrans(p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
Nptrans(p1', p2'), res
| Pcomb(p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
Npcomb(p1', p2'), res
| Peqmp(p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
Npeqmp(p1', p2'), res
| Pexists(p,ex,w) ->
let p', res = wp il p in
Npexists(p', term2nterm ex, term2nterm w), res
| Pchoose(x,ty,p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
let typ = hol_type2ntype ty in
Npchoose(make_idV x typ, typ, p1', p2'), res
| Pconj(p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
Npconj(p1', p2'), res
| Pimpas(p1,p2) ->
let p1', il' = wp il p1 in
let p2', res = wp il' p2 in
Npimpas(p1', p2'), res
| Pconjunct1 p ->
let p', res = wp il p in
Npconjunct1 p', res
| Pconjunct2 p ->
let p', res = wp il p in
Npconjunct2 p', res
| Pdisj1(p,tm) ->
let p', res = wp il p in
Npdisj1(p', term2nterm tm), res
| Pdisj2(p,tm) ->
let p', res = wp il p in
Npdisj2(p', term2nterm tm), res
| Pdisjcases(p1,p2,p3) ->
let p1', il' = wp il p1 in
let p2', il'' = wp il' p2 in
let p3', res = wp il'' p3 in
Npdisjcases(p1', p2', p3'), res
| Pnoti p ->
let p', res = wp il p in
Npnoti p', res
| Pnote p ->
let p', res = wp il p in
Npnote p', res
| Pcontr(p,tm) ->
let p', res = wp il p in
Npcontr(p', term2nterm tm), res
and wp il p =
match share_info_of p il with
| Some(_, thmname, il') -> wdi thmname, il'
| None -> wp' il (content_of p) in
match disk_info_of p with
| Some(_, thmname') -> if thmname' = thmname then wp' il (content_of p) else (wdi thmname', il)
| None -> wp' il (content_of p) in
let p', il = write_proof p il in
set_disk_info_of p THEORY_NAME thmname;
Hashtbl.add proof_of_thm thmname p';
make_dependencies_aux dep_graph proof_of_thm il;;
let make_dependencies out out_share out_sharet new_file count_thms path ((thmname, pr, _) as p) =
let dep_graph = Depgraph.Dep.create () in
let proof_of_thm = Hashtbl.create (references pr) in
Depgraph.Dep.add_thm dep_graph thmname;
make_dependencies_aux dep_graph proof_of_thm [p];
let share_type ty = share_types out_sharet ty in
let share_term ty = share_terms out_share out_sharet ty in
if thmname = (THEORY_NAME^"_DEF_T") then (
match content_of pr with
| Pdef (_, _, t) ->
let tm = hequiv htrue (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_T" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__slash__backslash_") then (
match content_of pr with
| Pdef (_, _, t) ->
let tm = heq (Narrow (Nbool, Narrow (Nbool, Nbool))) (Ncst Hand) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_AND" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__equal__equal__greaterthan_") then (
match content_of pr with
| Pdef (_, _, t) ->
let tm = heq (Narrow (Nbool, Narrow (Nbool, Nbool))) (Ncst Himp) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_IMP" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__exclamationmark_") then (
match content_of pr with
| Pdef (_, a, t) ->
let a2 = hol_type2ntype a in
(match a2 with
| Narrow (Narrow (b, _), _) ->
let tm = heq a2 (Ncst (Hforall b)) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_FORALL" thmname;
export_sig out thmname
| _ -> ())
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__questionmark_") then (
match content_of pr with
| Pdef (_, a, t) ->
let a2 = hol_type2ntype a in
(match a2 with
| Narrow (Narrow (b, _), _) ->
let tm = heq a2 (Ncst (Hexists b)) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_EXISTS" thmname;
export_sig out thmname
| _ -> ())
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__backslash__slash_") then (
match content_of pr with
| Pdef (_, _, t) ->
let tm = heq (Narrow (Nbool, Narrow (Nbool, Nbool))) (Ncst Hor) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_OR" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF_F") then (
match content_of pr with
| Pdef (_, _, t) ->
let tm = hequiv (Ncst Hfalse) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_F" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__tilde_") then (
match content_of pr with
| Pdef(_, _, t) ->
let tm = heq (Narrow (Nbool, Nbool)) (Ncst Hnot) (term2nterm t) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "DEF_NOT" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_DEF__FALSITY_") then (
let tm = heq Nbool (Ncst Hfalse) (Ncst Hfalse) in
Hashtbl.add derivs thmname (hyp_empty, tm);
export_ht out share_term hyp_empty tm thmname;
export_lemma_def out "(Prefl (Cst Hfalse))" thmname;
export_sig out thmname
) else if thmname = (THEORY_NAME^"_ax__1") then (
match content_of pr with
| Paxm (_, tm) ->
let tm2 = term2nterm tm in
Hashtbl.add derivs thmname (hyp_empty, tm2);
export_ht out share_term hyp_empty tm2 thmname;
export_lemma_def out "ETA_AX" thmname;
export_sig out thmname
| _ -> ()
) else if thmname = (THEORY_NAME^"_ax__2") then (
match content_of pr with
| Paxm (_, tm) ->
let tm2 = term2nterm tm in
Hashtbl.add derivs thmname (hyp_empty, tm2);
export_ht out share_term hyp_empty tm2 thmname;
export_lemma_def out "SELECT_AX" thmname;
export_sig out thmname
| _ -> ()
) else (
Depgraph.Dep_top.iter_top (
fun thm ->
incr count_thms;
if !count_thms = 1000 then (count_thms := 0; new_file ());
(try
let p = Hashtbl.find proof_of_thm thm in
(match proof2deriv p with
| Some (h, t) ->
Hashtbl.add derivs thm (h, t);
export_ht out share_term h t thm;
(match p with
| Npdef _ -> export_def out thm
| Nptyintro _ -> export_tdef out thm
| Npaxm _ -> export_axiom out thm
| _ -> export_lemma out share_type share_term p thm);
export_sig out thm
| None -> failwith ("Erreur make_dependencies "^thm^" de "^thmname^": no derivation associated to the proof\n"))
with | Not_found -> failwith ("Erreur make_dependencies "^thm^": proof_of_thm not found\n"));
) dep_graph
);
;;
let the_proof_database = ref ([]:(string*proof*(term option)) list);;
Random.self_init;;
let rec search_proof_name n db =
match db with [] -> n | ((m, _, _)::db') -> if n=m then n^"_"^(string_of_int (Random.int 1073741823)) else search_proof_name n db'
let save_proof name p c_opt =
let name' = search_proof_name name (!the_proof_database) in
the_proof_database := (name', p, c_opt)::(!the_proof_database);;
let proof_database () = !the_proof_database;;
(* Utilities to define Coq interpretation functions *)
let ut = Hashtbl.create 17;;
let ask_ut () =
try (
let filein = Pervasives.open_in "interpretation.txt" in
let line = ref 0 in
try
while true do
incr line;
let s1 = input_line filein in
incr line;
let s2 = input_line filein in
Hashtbl.add ut s1 s2
done
with
| End_of_file -> close_in filein
| _ -> failwith ("Error line "^(string_of_int !line)^".")
) with | Sys_error _ -> ()
;;
let tc_regexp = Str.regexp "\?[0-9]*";;
let make_tc_parameter out x n =
if Str.string_match tc_regexp x 0 then (
let i = Str.match_end () in
if i <> String.length x then (
out "\nParameter "; out THEORY_NAME; out "_idT_"; out (mfc x); out " : Type.\nParameter "; out THEORY_NAME; out "_idT_inhab_"; out (mfc x);
out " : "; out THEORY_NAME; out "_idT_"; out (mfc x); out "."
)
) else (
out "\nParameter "; out THEORY_NAME; out "_idT_"; out (mfc x); out " : Type.\nParameter "; out THEORY_NAME; out "_idT_inhab_"; out (mfc x);
out " : "; out THEORY_NAME; out "_idT_"; out (mfc x); out "."
);;
let make_tc_list out x n =
if Str.string_match tc_regexp x 0 then (
let i = Str.match_end () in
if i <> String.length x then (
out "\n("; out (string_of_int n); out ", mkTT "; out THEORY_NAME; out "_idT_inhab_"; out (mfc x); out ")::"
)
) else (
out "\n("; out (string_of_int n); out ", mkTT "; out THEORY_NAME; out "_idT_inhab_"; out (mfc x); out ")::"
);;
let defT_ut = Hashtbl.create 17;;
let make_tdt_parameter out x _ =
try (
let y = Hashtbl.find ut x in
Hashtbl.add defT_ut x y
) with | Not_found -> (
out "\nParameter "; out THEORY_NAME; out "_defT_"; out (mfc x); out " : Type.";
out "\nParameter "; out THEORY_NAME; out "_defT_inhab_"; out (mfc x); out " : "; out THEORY_NAME; out "_defT_"; out (mfc x); out ".\n";
Hashtbl.add defT_ut x ("fun _ => mkTT "^THEORY_NAME^"_defT_inhab_"^(mfc x))
);;
let make_tdt_list out x n =
try (
let s = Hashtbl.find defT_ut x in
out "\n("; out (string_of_int n); out ", "; out s; out ")::";
) with | Not_found -> (
out "\n("; out (string_of_int n); out ", fun _ => mkTT tt)::"
);;
let se_regexp = Str.regexp "_[0-9]*";;
let make_se_parameter out x (_,ty) =
if Str.string_match se_regexp x 0 then (
let i = Str.match_end () in
if i <> String.length x then (
out "\nParameter "; out THEORY_NAME; out "_idV_"; out (mfc x); out " : tr_type tc tdt "; print_type out ty; out "."
)
) else (
out "\nParameter "; out THEORY_NAME; out "_idV_"; out (mfc x); out " : tr_type tc tdt "; print_type out ty; out "."
);;
let make_se_list out x (n,ty) =
if Str.string_match se_regexp x 0 then (
let i = Str.match_end () in
if i <> String.length x then (
out "\n("; print_names out n; out ", existT (fun (t: type) => tr_type tc tdt t) "; print_type out ty; out " "; out THEORY_NAME; out "_idV_"; out (mfc x); out ")::"
)
) else (
out "\n("; print_names out n; out ", existT (fun (t: type) => tr_type tc tdt t) "; print_type out ty; out " "; out THEORY_NAME; out "_idV_"; out (mfc x); out ")::"
);;
let defV_ut = Hashtbl.create 17;;
let make_sdt_parameter out x (_,ty,_) =
if ((x <> "T") && (x <> "/\\") && (x <> "==>") && (x <> "!") && (x <> "?") && (x <> "\\/") && (x <> "F") && (x <> "~") && (x <> "_FALSITY_")) then (
try (
let y = Hashtbl.find ut x in
Hashtbl.add defV_ut x y
) with | Not_found -> (
out "\nParameter "; out THEORY_NAME; out "_defV_"; out (mfc x); out " : tr_type tc tdt "; print_type out ty; out "."
)
);;
let make_sdt_list out x (n,ty,_) =
try (
let s = Hashtbl.find defV_ut x in
out "\n("; print_names out n; out ", existT (fun (t: type) => tr_type tc tdt t) "; print_type out ty; out " ("; out s; out "))::"
) with | Not_found -> (
if ((x <> "T") && (x <> "/\\") && (x <> "==>") && (x <> "!") && (x <> "?") && (x <> "\\/") && (x <> "F") && (x <> "~") && (x <> "_FALSITY_")) then (
out "\n("; print_names out n; out ", existT (fun (t: type) => tr_type tc tdt t) "; print_type out ty; out " "; out THEORY_NAME; out "_defV_"; out (mfc x); out ")::"
)
);;
(* Main function: list of proofs exportation *)
let export_list thmname_list =
total := 0;
let path = ensure_export_directory THEORY_NAME in
let rec proof_of_thm acc acc2 = function
| [] -> acc, acc2
| (s,p,c)::q ->
if List.mem s thmname_list then
proof_of_thm ((THEORY_NAME^"_"^(mfc s), reset_disk_info_of1 p, c)::acc) (acc2+1) q
else match content_of p with
| Paxm _ | Pdef _ | Ptyintro _ -> proof_of_thm ((THEORY_NAME^"_"^(mfc s), reset_disk_info_of1 p, c)::acc) (acc2+1) q
| _ -> proof_of_thm acc acc2 q in
let l, total_thms = proof_of_thm [] 0 (proof_database ()) in
let count_thms = ref 0 in
let count_files = ref 1 in
(* Main file *)
let file = ref (open_out (Filename.concat path (THEORY_NAME^"_1.v"))) in
let count_file = ref 0 in
let out s = (output_string !file s; incr count_file; if !count_file = 1000 then (count_file := 0; flush !file)) in
out "(*** This file has been automatically generated from HOL-Light source files. ***)\n\nRequire Export List NArith.\nRequire Export hol deriv proof.\n\n";
(* Temporary file *)
let (file_temp_name, file_temp_aux) = Filename.open_temp_file (THEORY_NAME^"_") ".v" in
let file_temp = ref file_temp_aux in
let count_file_temp = ref 0 in
let out_temp s = (output_string !file_temp s; incr count_file_temp; if !count_file_temp = 1000 then (count_file_temp := 0; flush !file_temp)) in
let move_temp () =
(try
close_out !file_temp
with | Sys_error s -> raise (Sys_error ("move_temp1: "^s)));
(try
let buf = Pervasives.open_in file_temp_name in
(try
while true do
out "\n";
let l = input_line buf in
out l
done
with | End_of_file -> close_in buf)
with | Sys_error s -> raise (Sys_error ("move_temp3: "^s))) in
(* New file *)
let new_file () =
move_temp ();
file_temp := open_out file_temp_name;
incr count_files;
close_out !file;
file := open_out (Filename.concat path (THEORY_NAME^"_"^(string_of_int !count_files)^".v"));
out "(*** This file has been automatically generated from HOL-Light source files. ***)\n\nRequire Export "; out THEORY_NAME; out "_"; out (string_of_int (!count_files-1)); out ".\n\n" in
(* Coq files generation *)
let date1 = Unix.time () in
List.iter (make_dependencies out_temp out out new_file count_thms path) l;
let date2 = Unix.time () in
move_temp (); close_out !file;
(* Makefile *)
let make = open_out (Filename.concat path "Makefile") in
let out = output_string make in
out "# This file has been automatically generated from HOL-Light source files.\n\nCOQ=ssrcoq\nFLAGS=-dont-load-proofs -dump-glob /dev/null -compile\n\nSRC=";
for i = 1 to !count_files do
out " "; out THEORY_NAME; out "_"; out (string_of_int i); out ".v";
done;
out "\nOBJ=$(SRC:.v=.vo)\nGLOB=$(SRC:.v=.glob)\n\n\nall: $(OBJ)\n\n\n%.vo: %.v\n\t$(COQ) $(FLAGS) $(^:.v=)\n\n\nclean:\n\trm -f $(OBJ) $(GLOB) *~";
close_out make;
(* Interpretation *)
let interp = open_out (Filename.concat path "interpretation.v") in
let out = output_string interp in
out "(*** This file has been automatically generated from HOL-Light source files. ***)\n\nRequire Import ssreflect eqtype ssrnat ssrbool.\nRequire Import List NArith ZArith.ZOdiv_def.\nRequire Import hol cast typing translation axioms.\n\nOpen Local Scope positive_scope.\n\n";
ask_ut ();
(* tc *)
Hashtbl.iter (make_tc_parameter out) idT;
out "\n\nDefinition tc_list :=";
Hashtbl.iter (make_tc_list out) idT;
out "\nnil.\n\nDefinition tc := list_tc2tc tc_list.\n\n";
(* tdt *)
Hashtbl.iter (make_tdt_parameter out) defT;
out "\n\nDefinition tdt_list : list_tdt :=";
Hashtbl.iter (make_tdt_list out) defT;
out "\nnil.\n\nDefinition tdt := list_tdt2tdt tdt_list.\n\n";
(* se *)
Hashtbl.iter (make_se_parameter out) idV;
out "\n\nDefinition se_list :=";
Hashtbl.iter (make_se_list out) idV;
out "\nnil.\n\nDefinition se := list_se2se se_list.\n\n";
(* sdt *)
Hashtbl.iter (make_sdt_parameter out) defV;
out "\n\nDefinition sdt_list :=";
Hashtbl.iter (make_sdt_list out) defV;
out "\nnil.\n\nDefinition sdt := list_sdt2sdt sdt_list.";
close_out interp;
print_string "Generated "; print_int !total; print_string " facts for "; print_int total_thms; print_string " theorems.\n";
print_string "Exportation duration: "; print_float (date2 -. date1); print_string "s.\n"
;;
(* Main function: all proofs exportation *)
let export_saved_proofs () = export_list (List.map (fun (s,_,_) -> s) (proof_database ()));;
(* Main function: one proof exportation *)
let export_one_proof name = export_list [name];;
end;;
include Proofobjects;;