(* cOpyright (C) 2005, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://cs.unibo.it/helm/. *) (* $Id: inference.ml 6245 2006-04-05 12:07:51Z tassi $ *) (******* CIC substitution ***************************************************) type cic_substitution = Cic.substitution let cic_apply_subst = CicMetaSubst.apply_subst let cic_apply_subst_metasenv = CicMetaSubst.apply_subst_metasenv let cic_ppsubst = CicMetaSubst.ppsubst let cic_buildsubst n context t ty tail = (n,(context,t,ty)) :: tail let cic_flatten_subst subst = List.map (fun (i, (context, term, ty)) -> let context = (* cic_apply_subst_context subst*) context in let term = cic_apply_subst subst term in let ty = cic_apply_subst subst ty in (i, (context, term, ty))) subst let rec cic_lookup_subst meta subst = match meta with | Cic.Meta (i, _) -> ( try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst in cic_lookup_subst t subst with Not_found -> meta ) | _ -> meta ;; let cic_merge_subst_if_possible s1 s2 = let already_in = Hashtbl.create 13 in let rec aux acc = function | ((i,_,x) as s)::tl -> (try let x' = Hashtbl.find already_in i in if x = x' then aux acc tl else None with | Not_found -> Hashtbl.add already_in i x; aux (s::acc) tl) | [] -> Some acc in aux [] (s1@s2) ;; (******** NAIF substitution **************************************************) (* * naif version of apply subst; the local context of metas is ignored; * we assume the substituted term must be lifted according to the nesting * depth of the meta. * Alternatively, we could used implicit instead of metas *) type naif_substitution = (int * Cic.term) list let naif_apply_subst subst term = let rec aux k t = match t with Cic.Rel _ -> t | Cic.Var (uri,exp_named_subst) -> let exp_named_subst' = List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst in Cic.Var (uri, exp_named_subst') | Cic.Meta (i, l) -> (try aux k (CicSubstitution.lift k (List.assoc i subst)) with Not_found -> t) | Cic.Sort _ | Cic.Implicit _ -> t | Cic.Cast (te,ty) -> Cic.Cast (aux k te, aux k ty) | Cic.Prod (n,s,t) -> Cic.Prod (n, aux k s, aux (k+1) t) | Cic.Lambda (n,s,t) -> Cic.Lambda (n, aux k s, aux (k+1) t) | Cic.LetIn (n,s,t) -> Cic.LetIn (n, aux k s, aux (k+1) t) | Cic.Appl [] -> assert false | Cic.Appl l -> Cic.Appl (List.map (aux k) l) | Cic.Const (uri,exp_named_subst) -> let exp_named_subst' = List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst in if exp_named_subst' != exp_named_subst then Cic.Const (uri, exp_named_subst') else t (* TODO: provare a mantenere il piu' possibile sharing *) | Cic.MutInd (uri,typeno,exp_named_subst) -> let exp_named_subst' = List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst in Cic.MutInd (uri,typeno,exp_named_subst') | Cic.MutConstruct (uri,typeno,consno,exp_named_subst) -> let exp_named_subst' = List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst in Cic.MutConstruct (uri,typeno,consno,exp_named_subst') | Cic.MutCase (sp,i,outty,t,pl) -> let pl' = List.map (aux k) pl in Cic.MutCase (sp, i, aux k outty, aux k t, pl') | Cic.Fix (i, fl) -> let len = List.length fl in let fl' = List.map (fun (name, i, ty, bo) -> (name, i, aux k ty, aux (k+len) bo)) fl in Cic.Fix (i, fl') | Cic.CoFix (i, fl) -> let len = List.length fl in let fl' = List.map (fun (name, ty, bo) -> (name, aux k ty, aux (k+len) bo)) fl in Cic.CoFix (i, fl') in aux 0 term ;; (* naif version of apply_subst_metasenv: we do not apply the substitution to the context *) let naif_apply_subst_metasenv subst metasenv = List.map (fun (n, context, ty) -> (n, context, naif_apply_subst subst ty)) (List.filter (fun (i, _, _) -> not (List.mem_assoc i subst)) metasenv) let naif_ppsubst names subst = "{" ^ String.concat "; " (List.map (fun (idx, t) -> Printf.sprintf "%d:= %s" idx (CicPp.pp t names)) subst) ^ "}" ;; let naif_buildsubst n context t ty tail = (n,t) :: tail ;; let naif_flatten_subst subst = List.map (fun (i,t) -> i, naif_apply_subst subst t ) subst ;; let rec naif_lookup_subst meta subst = match meta with | Cic.Meta (i, _) -> (try naif_lookup_subst (List.assoc i subst) subst with Not_found -> meta) | _ -> meta ;; let naif_merge_subst_if_possible s1 s2 = let already_in = Hashtbl.create 13 in let rec aux acc = function | ((i,x) as s)::tl -> (try let x' = Hashtbl.find already_in i in if x = x' then aux acc tl else None with | Not_found -> Hashtbl.add already_in i x; aux (s::acc) tl) | [] -> Some acc in aux [] (s1@s2) ;; (********** ACTUAL SUBSTITUTION IMPLEMENTATION *******************************) type substitution = naif_substitution let apply_subst = naif_apply_subst let apply_subst_metasenv = naif_apply_subst_metasenv let ppsubst ~names l = naif_ppsubst (names:(Cic.name option)list) l let buildsubst = naif_buildsubst let flatten_subst = naif_flatten_subst let lookup_subst = naif_lookup_subst (* filter out from metasenv the variables in substs *) let filter subst metasenv = List.filter (fun (m, _, _) -> try let _ = List.find (fun (i, _) -> m = i) subst in false with Not_found -> true) metasenv ;; let is_in_subst i subst = List.mem_assoc i subst;; let merge_subst_if_possible = naif_merge_subst_if_possible;; let empty_subst = [];; (********* EQUALITY **********************************************************) type rule = SuperpositionRight | SuperpositionLeft | Demodulation type uncomparable = int -> int type equality = uncomparable * (* trick to break structural equality *) int * (* weight *) proof * (Cic.term * (* type *) Cic.term * (* left side *) Cic.term * (* right side *) Utils.comparison) * (* ordering *) Cic.metasenv * (* environment for metas *) int (* id *) and proof = new_proof * old_proof and new_proof = | Exact of Cic.term | Step of substitution * (rule * int*(Utils.pos*int)* Cic.term) (* eq1, eq2,predicate *) and old_proof = | NoProof (* term is the goal missing a proof *) | BasicProof of substitution * Cic.term | ProofBlock of substitution * UriManager.uri * (Cic.name * Cic.term) * Cic.term * (Utils.pos * equality) * old_proof | ProofGoalBlock of old_proof * old_proof | ProofSymBlock of Cic.term list * old_proof | SubProof of Cic.term * int * old_proof and goal_proof = (Utils.pos * int * substitution * Cic.term) list ;; (* globals *) let maxid = ref 0;; let id_to_eq = Hashtbl.create 1024;; let freshid () = incr maxid; !maxid ;; let reset () = maxid := 0; Hashtbl.clear id_to_eq ;; let uncomparable = fun _ -> 0 let mk_equality (weight,(newp,oldp),(ty,l,r,o),m) = let id = freshid () in let eq = (uncomparable,weight,(newp,oldp),(ty,l,r,o),m,id) in Hashtbl.add id_to_eq id eq; eq ;; let open_equality (_,weight,proof,(ty,l,r,o),m,id) = (weight,proof,(ty,l,r,o),m,id) let string_of_equality ?env eq = match env with | None -> let w, _, (ty, left, right, o), _ , id = open_equality eq in Printf.sprintf "Id: %d, Weight: %d, {%s}: %s =(%s) %s" id w (CicPp.ppterm ty) (CicPp.ppterm left) (Utils.string_of_comparison o) (CicPp.ppterm right) | Some (_, context, _) -> let names = Utils.names_of_context context in let w, _, (ty, left, right, o), _ , id = open_equality eq in Printf.sprintf "Id: %d, Weight: %d, {%s}: %s =(%s) %s" id w (CicPp.pp ty names) (CicPp.pp left names) (Utils.string_of_comparison o) (CicPp.pp right names) ;; let compare (_,_,_,s1,_,_) (_,_,_,s2,_,_) = Pervasives.compare s1 s2 ;; let rec string_of_proof_old ?(names=[]) = function | NoProof -> "NoProof " | BasicProof (s, t) -> "BasicProof(" ^ ppsubst ~names s ^ ", " ^ (CicPp.pp t names) ^ ")" | SubProof (t, i, p) -> Printf.sprintf "SubProof(%s, %s, %s)" (CicPp.pp t names) (string_of_int i) (string_of_proof_old p) | ProofSymBlock (_,p) -> Printf.sprintf "ProofSymBlock(%s)" (string_of_proof_old p) | ProofBlock (subst, _, _, _ ,(_,eq),old) -> let _,(_,p),_,_,_ = open_equality eq in "ProofBlock(" ^ (ppsubst ~names subst) ^ "," ^ (string_of_proof_old old) ^ "," ^ string_of_proof_old p ^ ")" | ProofGoalBlock (p1, p2) -> Printf.sprintf "ProofGoalBlock(%s, %s)" (string_of_proof_old p1) (string_of_proof_old p2) ;; let proof_of_id id = try let (_,(p,_),(_,l,r,_),_,_) = open_equality (Hashtbl.find id_to_eq id) in p,l,r with Not_found -> assert false let string_of_proof_new ?(names=[]) p gp = let str_of_rule = function | SuperpositionRight -> "SupR" | SuperpositionLeft -> "SupL" | Demodulation -> "Demod" in let str_of_pos = function | Utils.Left -> "left" | Utils.Right -> "right" in let fst3 (x,_,_) = x in let rec aux margin name = let prefix = String.make margin ' ' ^ name ^ ": " in function | Exact t -> Printf.sprintf "%sExact (%s)\n" prefix (CicPp.pp t names) | Step (subst,(rule,eq1,(pos,eq2),pred)) -> Printf.sprintf "%s%s(%s|%d with %d dir %s pred %s))\n" prefix (str_of_rule rule) (ppsubst ~names subst) eq1 eq2 (str_of_pos pos) (CicPp.pp pred names)^ aux (margin+1) (Printf.sprintf "%d" eq1) (fst3 (proof_of_id eq1)) ^ aux (margin+1) (Printf.sprintf "%d" eq2) (fst3 (proof_of_id eq2)) in aux 0 "" p ^ String.concat "\n" (List.map (fun (pos,i,s,t) -> (Printf.sprintf "GOAL: %s %d %s %s\n" (str_of_pos pos) i (ppsubst ~names s) (CicPp.pp t names)) ^ aux 1 (Printf.sprintf "%d " i) (fst3 (proof_of_id i))) gp) ;; let ppsubst = ppsubst ~names:[] (* returns an explicit named subst and a list of arguments for sym_eq_URI *) let build_ens uri termlist = let obj, _ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in match obj with | Cic.Constant (_, _, _, uris, _) -> assert (List.length uris <= List.length termlist); let rec aux = function | [], tl -> [], tl | (uri::uris), (term::tl) -> let ens, args = aux (uris, tl) in (uri, term)::ens, args | _, _ -> assert false in aux (uris, termlist) | _ -> assert false ;; let build_proof_term_old ?(noproof=Cic.Implicit None) proof = let rec do_build_proof proof = match proof with | NoProof -> Printf.fprintf stderr "WARNING: no proof!\n"; noproof | BasicProof (s,term) -> apply_subst s term | ProofGoalBlock (proofbit, proof) -> print_endline "found ProofGoalBlock, going up..."; do_build_goal_proof proofbit proof | ProofSymBlock (termlist, proof) -> let proof = do_build_proof proof in let ens, args = build_ens (Utils.sym_eq_URI ()) termlist in Cic.Appl ([Cic.Const (Utils.sym_eq_URI (), ens)] @ args @ [proof]) | ProofBlock (subst, eq_URI, (name, ty), bo, (pos, eq), eqproof) -> let t' = Cic.Lambda (name, ty, bo) in let _, (_,proof), (ty, what, other, _), menv',_ = open_equality eq in let proof' = do_build_proof proof in let eqproof = do_build_proof eqproof in let what, other = if pos = Utils.Left then what, other else other, what in apply_subst subst (Cic.Appl [Cic.Const (eq_URI, []); ty; what; t'; eqproof; other; proof']) | SubProof (term, meta_index, proof) -> let proof = do_build_proof proof in let eq i = function | Cic.Meta (j, _) -> i = j | _ -> false in ProofEngineReduction.replace ~equality:eq ~what:[meta_index] ~with_what:[proof] ~where:term and do_build_goal_proof proofbit proof = match proof with | ProofGoalBlock (pb, p) -> do_build_proof (ProofGoalBlock (replace_proof proofbit pb, p)) | _ -> do_build_proof (replace_proof proofbit proof) and replace_proof newproof = function | ProofBlock (subst, eq_URI, namety, bo, poseq, eqproof) -> let eqproof' = replace_proof newproof eqproof in ProofBlock (subst, eq_URI, namety, bo, poseq, eqproof') | ProofGoalBlock (pb, p) -> let pb' = replace_proof newproof pb in ProofGoalBlock (pb', p) | BasicProof _ -> newproof | SubProof (term, meta_index, p) -> SubProof (term, meta_index, replace_proof newproof p) | p -> p in do_build_proof proof ;; let mk_sym uri ty t1 t2 p = let ens, args = build_ens uri [ty;t1;t2;p] in Cic.Appl (Cic.Const(uri, ens) :: args) ;; let mk_trans uri ty t1 t2 t3 p12 p23 = let ens, args = build_ens uri [ty;t1;t2;t3;p12;p23] in Cic.Appl (Cic.Const (uri, ens) :: args) ;; let mk_eq_ind uri ty what pred p1 other p2 = Cic.Appl [Cic.Const (uri, []); ty; what; pred; p1; other; p2] ;; let p_of_sym ens tl = let args = List.map snd ens @ tl in match args with | [_;_;_;p] -> p | _ -> assert false ;; let open_trans ens tl = let args = List.map snd ens @ tl in match args with | [ty;l;m;r;p1;p2] -> ty,l,m,r,p1,p2 | _ -> assert false ;; let canonical t = let rec remove_refl t = match t with | Cic.Appl (((Cic.Const(uri_trans,ens))::tl) as args) when LibraryObjects.is_trans_eq_URI uri_trans -> let ty,l,m,r,p1,p2 = open_trans ens tl in (match p1,p2 with | Cic.Appl [Cic.MutConstruct (uri, 0, 1,_);_;_],p2 -> remove_refl p2 | p1,Cic.Appl [Cic.MutConstruct (uri, 0, 1,_);_;_] -> remove_refl p1 | _ -> Cic.Appl (List.map remove_refl args)) | Cic.Appl l -> Cic.Appl (List.map remove_refl l) | _ -> t in let rec canonical t = match t with | Cic.Appl (((Cic.Const(uri_sym,ens))::tl) as args) when LibraryObjects.is_sym_eq_URI uri_sym -> (match p_of_sym ens tl with | Cic.Appl ((Cic.Const(uri,ens))::tl) when LibraryObjects.is_sym_eq_URI uri -> canonical (p_of_sym ens tl) | Cic.Appl ((Cic.Const(uri_trans,ens))::tl) when LibraryObjects.is_trans_eq_URI uri_trans -> let ty,l,m,r,p1,p2 = open_trans ens tl in mk_trans uri_trans ty r m l (canonical (mk_sym uri_sym ty m r p2)) (canonical (mk_sym uri_sym ty l m p1)) | Cic.Appl (((Cic.Const(uri_ind,ens)) as he)::tl) when LibraryObjects.is_eq_ind_URI uri_ind || LibraryObjects.is_eq_ind_r_URI uri_ind -> let ty, what, pred, p1, other, p2 = match tl with | [ty;what;pred;p1;other;p2] -> ty, what, pred, p1, other, p2 | _ -> assert false in let pred,l,r = match pred with | Cic.Lambda (name,s,Cic.Appl [Cic.MutInd(uri,0,ens);ty;l;r]) when LibraryObjects.is_eq_URI uri -> Cic.Lambda (name,s,Cic.Appl [Cic.MutInd(uri,0,ens);ty;r;l]),l,r | _ -> prerr_endline (CicPp.ppterm pred); assert false in let l = CicSubstitution.subst what l in let r = CicSubstitution.subst what r in Cic.Appl [he;ty;what;pred; canonical (mk_sym uri_sym ty l r p1);other;canonical p2] | Cic.Appl [Cic.MutConstruct (uri, 0, 1,_);_;_] as t when LibraryObjects.is_eq_URI uri -> t | _ -> Cic.Appl (List.map canonical args)) | Cic.Appl l -> Cic.Appl (List.map canonical l) | _ -> t in remove_refl (canonical t) ;; let build_proof_step subst p1 p2 pos l r pred = let p1 = apply_subst subst p1 in let p2 = apply_subst subst p2 in let l = apply_subst subst l in let r = apply_subst subst r in let pred = apply_subst subst pred in let ty,body = (* Cic.Implicit None *) match pred with | Cic.Lambda (_,ty,body) -> ty,body | _ -> assert false in let what, other = (* Cic.Implicit None, Cic.Implicit None *) if pos = Utils.Left then l,r else r,l in let is_not_fixed t = CicSubstitution.subst (Cic.Implicit None) t <> CicSubstitution.subst (Cic.Rel 1) t in match body,pos with |Cic.Appl [Cic.MutInd(eq,_,_);_;Cic.Rel 1;third],Utils.Left -> let third = CicSubstitution.subst (Cic.Implicit None) third in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in mk_trans uri_trans ty other what third (mk_sym uri_sym ty what other p2) p1 |Cic.Appl [Cic.MutInd(eq,_,_);_;Cic.Rel 1;third],Utils.Right -> let third = CicSubstitution.subst (Cic.Implicit None) third in let uri_trans = LibraryObjects.trans_eq_URI ~eq in mk_trans uri_trans ty other what third p2 p1 |Cic.Appl [Cic.MutInd(eq,_,_);_;third;Cic.Rel 1],Utils.Left -> let third = CicSubstitution.subst (Cic.Implicit None) third in let uri_trans = LibraryObjects.trans_eq_URI ~eq in mk_trans uri_trans ty third what other p1 p2 |Cic.Appl [Cic.MutInd(eq,_,_);_;third;Cic.Rel 1],Utils.Right -> let third = CicSubstitution.subst (Cic.Implicit None) third in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in mk_trans uri_trans ty third what other p1 (mk_sym uri_sym ty other what p2) | Cic.Appl [Cic.MutInd(eq,_,_);_;lhs;rhs],Utils.Left when is_not_fixed lhs -> let rhs = CicSubstitution.subst (Cic.Implicit None) rhs in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in let pred_of t = CicSubstitution.subst t lhs in let pred_of_what = pred_of what in let pred_of_other = pred_of other in (* p2 : what = other * ==================================== * inject p2: P(what) = P(other) *) let inject ty lhs what other p2 = let liftedty = CicSubstitution.lift 1 ty in let lifted_pred_of_other = CicSubstitution.lift 1 (pred_of other) in let refl_eq_part = Cic.Appl [Cic.MutConstruct(eq,0,1,[]);ty;pred_of other] in mk_eq_ind (Utils.eq_ind_r_URI ()) ty other (Cic.Lambda (Cic.Name "foo",ty, (Cic.Appl [Cic.MutInd(eq,0,[]);liftedty;lhs;lifted_pred_of_other]))) refl_eq_part what p2 in mk_trans uri_trans ty pred_of_other pred_of_what rhs (mk_sym uri_sym ty pred_of_what pred_of_other (inject ty lhs what other p2) ) p1 | Cic.Appl[Cic.MutInd(eq,_,_);_;lhs;rhs],Utils.Right when is_not_fixed lhs -> let rhs = CicSubstitution.subst (Cic.Implicit None) rhs in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in let pred_of t = CicSubstitution.subst t lhs in let pred_of_what = pred_of what in let pred_of_other = pred_of other in (* p2 : what = other * ==================================== * inject p2: P(what) = P(other) *) let inject ty lhs what other p2 = let liftedty = CicSubstitution.lift 1 ty in let lifted_pred_of_other = CicSubstitution.lift 1 (pred_of other) in let refl_eq_part = Cic.Appl [Cic.MutConstruct(eq,0,1,[]);ty;pred_of other] in mk_eq_ind (Utils.eq_ind_URI ()) ty other (Cic.Lambda (Cic.Name "foo",ty, (Cic.Appl [Cic.MutInd(eq,0,[]);liftedty;lhs;lifted_pred_of_other]))) refl_eq_part what p2 in mk_trans uri_trans ty pred_of_other pred_of_what rhs (mk_sym uri_sym ty pred_of_other pred_of_what (inject ty lhs what other p2) ) p1 | Cic.Appl[Cic.MutInd(eq,_,_);_;lhs;rhs],Utils.Right when is_not_fixed rhs -> let lhs = CicSubstitution.subst (Cic.Implicit None) lhs in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in let pred_of t = CicSubstitution.subst t rhs in let pred_of_what = pred_of what in let pred_of_other = pred_of other in (* p2 : what = other * ==================================== * inject p2: P(what) = P(other) *) let inject ty lhs what other p2 = let liftedty = CicSubstitution.lift 1 ty in let lifted_pred_of_other = CicSubstitution.lift 1 (pred_of other) in let refl_eq_part = Cic.Appl [Cic.MutConstruct(eq,0,1,[]);ty;pred_of other] in mk_eq_ind (Utils.eq_ind_r_URI ()) ty other (Cic.Lambda (Cic.Name "foo",ty, (Cic.Appl [Cic.MutInd(eq,0,[]);liftedty;lhs;lifted_pred_of_other]))) refl_eq_part what p2 in mk_trans uri_trans ty lhs pred_of_what pred_of_other p1 (mk_sym uri_sym ty pred_of_what pred_of_other (inject ty rhs other what p2)) | Cic.Appl[Cic.MutInd(eq,_,_);_;lhs;rhs],Utils.Left when is_not_fixed rhs -> let lhs = CicSubstitution.subst (Cic.Implicit None) lhs in let uri_trans = LibraryObjects.trans_eq_URI ~eq in let uri_sym = LibraryObjects.sym_eq_URI ~eq in let pred_of t = CicSubstitution.subst t rhs in let pred_of_what = pred_of what in let pred_of_other = pred_of other in (* p2 : what = other * ==================================== * inject p2: P(what) = P(other) *) let inject ty lhs what other p2 = let liftedty = CicSubstitution.lift 1 ty in let lifted_pred_of_other = CicSubstitution.lift 1 (pred_of other) in let refl_eq_part = Cic.Appl [Cic.MutConstruct(eq,0,1,[]);ty;pred_of other] in mk_eq_ind (Utils.eq_ind_URI ()) ty other (Cic.Lambda (Cic.Name "foo",ty, (Cic.Appl [Cic.MutInd(eq,0,[]);liftedty;lhs;lifted_pred_of_other]))) refl_eq_part what p2 in mk_trans uri_trans ty lhs pred_of_what pred_of_other p1 (mk_sym uri_sym ty pred_of_other pred_of_what (inject ty rhs other what p2)) | _, Utils.Left -> mk_eq_ind (Utils.eq_ind_URI ()) ty what pred p1 other p2 | _, Utils.Right -> mk_eq_ind (Utils.eq_ind_r_URI ()) ty what pred p1 other p2 ;; let build_proof_term_new proof = let rec aux = function | Exact term -> term | Step (subst,(_, id1, (pos,id2), pred)) -> let p,_,_ = proof_of_id id1 in let p1 = aux p in let p,l,r = proof_of_id id2 in let p2 = aux p in build_proof_step subst p1 p2 pos l r pred in aux proof let build_goal_proof l initial = let proof = List.fold_left (fun current_proof (pos,id,subst,pred) -> let p,l,r = proof_of_id id in let p = build_proof_term_new p in let pos = if pos = Utils.Left then Utils.Right else Utils.Left in build_proof_step subst current_proof p pos l r pred) initial l in canonical proof ;; let refl_proof ty term = Cic.Appl [Cic.MutConstruct (LibraryObjects.eq_URI (), 0, 1, []); ty; term] ;; let metas_of_proof p = Utils.metas_of_term (build_proof_term_old (snd p)) ;; let relocate newmeta menv = let subst, metasenv, newmeta = List.fold_right (fun (i, context, ty) (subst, menv, maxmeta) -> let irl = [] (* CicMkImplicit.identity_relocation_list_for_metavariable context *) in let newsubst = buildsubst i context (Cic.Meta(maxmeta,irl)) ty subst in let newmeta = maxmeta, context, ty in newsubst, newmeta::menv, maxmeta+1) menv ([], [], newmeta+1) in let metasenv = apply_subst_metasenv subst metasenv in let subst = flatten_subst subst in subst, metasenv, newmeta let fix_metas newmeta eq = let w, (p1,p2), (ty, left, right, o), menv,_ = open_equality eq in (* debug let _ , eq = fix_metas_old newmeta (w, p, (ty, left, right, o), menv, args) in prerr_endline (string_of_equality eq); *) let subst, metasenv, newmeta = relocate newmeta menv in let ty = apply_subst subst ty in let left = apply_subst subst left in let right = apply_subst subst right in let fix_proof = function | NoProof -> NoProof | BasicProof (subst',term) -> BasicProof (subst@subst',term) | ProofBlock (subst', eq_URI, namety, bo, (pos, eq), p) -> (* let newsubst = List.map (fun (i, (context, term, ty)) -> let context = apply_subst_context subst context in let term = apply_subst subst term in let ty = apply_subst subst ty in (i, (context, term, ty))) subst' in *) ProofBlock (subst@subst', eq_URI, namety, bo, (pos, eq), p) | p -> assert false in let fix_new_proof = function | Exact p -> Exact (apply_subst subst p) | Step (s,(r,id1,(pos,id2),pred)) -> Step (s@subst,(r,id1,(pos,id2),(*apply_subst subst*) pred)) in let new_p = fix_new_proof p1 in let old_p = fix_proof p2 in let eq = mk_equality (w, (new_p,old_p), (ty, left, right, o), metasenv) in (* debug prerr_endline (string_of_equality eq); *) newmeta+1, eq exception NotMetaConvertible;; let meta_convertibility_aux table t1 t2 = let module C = Cic in let rec aux ((table_l, table_r) as table) t1 t2 = match t1, t2 with | C.Meta (m1, tl1), C.Meta (m2, tl2) -> let m1_binding, table_l = try List.assoc m1 table_l, table_l with Not_found -> m2, (m1, m2)::table_l and m2_binding, table_r = try List.assoc m2 table_r, table_r with Not_found -> m1, (m2, m1)::table_r in if (m1_binding <> m2) || (m2_binding <> m1) then raise NotMetaConvertible else ( try List.fold_left2 (fun res t1 t2 -> match t1, t2 with | None, Some _ | Some _, None -> raise NotMetaConvertible | None, None -> res | Some t1, Some t2 -> (aux res t1 t2)) (table_l, table_r) tl1 tl2 with Invalid_argument _ -> raise NotMetaConvertible ) | C.Var (u1, ens1), C.Var (u2, ens2) | C.Const (u1, ens1), C.Const (u2, ens2) when (UriManager.eq u1 u2) -> aux_ens table ens1 ens2 | C.Cast (s1, t1), C.Cast (s2, t2) | C.Prod (_, s1, t1), C.Prod (_, s2, t2) | C.Lambda (_, s1, t1), C.Lambda (_, s2, t2) | C.LetIn (_, s1, t1), C.LetIn (_, s2, t2) -> let table = aux table s1 s2 in aux table t1 t2 | C.Appl l1, C.Appl l2 -> ( try List.fold_left2 (fun res t1 t2 -> (aux res t1 t2)) table l1 l2 with Invalid_argument _ -> raise NotMetaConvertible ) | C.MutInd (u1, i1, ens1), C.MutInd (u2, i2, ens2) when (UriManager.eq u1 u2) && i1 = i2 -> aux_ens table ens1 ens2 | C.MutConstruct (u1, i1, j1, ens1), C.MutConstruct (u2, i2, j2, ens2) when (UriManager.eq u1 u2) && i1 = i2 && j1 = j2 -> aux_ens table ens1 ens2 | C.MutCase (u1, i1, s1, t1, l1), C.MutCase (u2, i2, s2, t2, l2) when (UriManager.eq u1 u2) && i1 = i2 -> let table = aux table s1 s2 in let table = aux table t1 t2 in ( try List.fold_left2 (fun res t1 t2 -> (aux res t1 t2)) table l1 l2 with Invalid_argument _ -> raise NotMetaConvertible ) | C.Fix (i1, il1), C.Fix (i2, il2) when i1 = i2 -> ( try List.fold_left2 (fun res (n1, i1, s1, t1) (n2, i2, s2, t2) -> if i1 <> i2 then raise NotMetaConvertible else let res = (aux res s1 s2) in aux res t1 t2) table il1 il2 with Invalid_argument _ -> raise NotMetaConvertible ) | C.CoFix (i1, il1), C.CoFix (i2, il2) when i1 = i2 -> ( try List.fold_left2 (fun res (n1, s1, t1) (n2, s2, t2) -> let res = aux res s1 s2 in aux res t1 t2) table il1 il2 with Invalid_argument _ -> raise NotMetaConvertible ) | t1, t2 when t1 = t2 -> table | _, _ -> raise NotMetaConvertible and aux_ens table ens1 ens2 = let cmp (u1, t1) (u2, t2) = Pervasives.compare (UriManager.string_of_uri u1) (UriManager.string_of_uri u2) in let ens1 = List.sort cmp ens1 and ens2 = List.sort cmp ens2 in try List.fold_left2 (fun res (u1, t1) (u2, t2) -> if not (UriManager.eq u1 u2) then raise NotMetaConvertible else aux res t1 t2) table ens1 ens2 with Invalid_argument _ -> raise NotMetaConvertible in aux table t1 t2 ;; let meta_convertibility_eq eq1 eq2 = let _, _, (ty, left, right, _), _,_ = open_equality eq1 in let _, _, (ty', left', right', _), _,_ = open_equality eq2 in if ty <> ty' then false else if (left = left') && (right = right') then true else if (left = right') && (right = left') then true else try let table = meta_convertibility_aux ([], []) left left' in let _ = meta_convertibility_aux table right right' in true with NotMetaConvertible -> try let table = meta_convertibility_aux ([], []) left right' in let _ = meta_convertibility_aux table right left' in true with NotMetaConvertible -> false ;; let meta_convertibility t1 t2 = if t1 = t2 then true else try ignore(meta_convertibility_aux ([], []) t1 t2); true with NotMetaConvertible -> false ;; exception TermIsNotAnEquality;; let term_is_equality term = let iseq uri = UriManager.eq uri (LibraryObjects.eq_URI ()) in match term with | Cic.Appl [Cic.MutInd (uri, _, _); _; _; _] when iseq uri -> true | _ -> false ;; let equality_of_term proof term = let eq_uri = LibraryObjects.eq_URI () in let iseq uri = UriManager.eq uri eq_uri in match term with | Cic.Appl [Cic.MutInd (uri, _, _); ty; t1; t2] when iseq uri -> let o = !Utils.compare_terms t1 t2 in let stat = (ty,t1,t2,o) in let w = Utils.compute_equality_weight stat in let e = mk_equality (w, (Exact proof, BasicProof ([],proof)),stat,[]) in e | _ -> raise TermIsNotAnEquality ;; let is_weak_identity eq = let _,_,(_,left, right,_),_,_ = open_equality eq in left = right || meta_convertibility left right ;; let is_identity (_, context, ugraph) eq = let _,_,(ty,left,right,_),menv,_ = open_equality eq in left = right || (* (meta_convertibility left right)) *) fst (CicReduction.are_convertible ~metasenv:menv context left right ugraph) ;; let term_of_equality equality = let _, _, (ty, left, right, _), menv, _= open_equality equality in let eq i = function Cic.Meta (j, _) -> i = j | _ -> false in let argsno = List.length menv in let t = CicSubstitution.lift argsno (Cic.Appl [Cic.MutInd (LibraryObjects.eq_URI (), 0, []); ty; left; right]) in snd ( List.fold_right (fun (i,_,ty) (n, t) -> let name = Cic.Name ("X" ^ (string_of_int n)) in let ty = CicSubstitution.lift (n-1) ty in let t = ProofEngineReduction.replace ~equality:eq ~what:[i] ~with_what:[Cic.Rel (argsno - (n - 1))] ~where:t in (n-1, Cic.Prod (name, ty, t))) menv (argsno, t)) ;;