+ let arg,gty = find_hyp 1 context in
+ let last_hyp_name_of_status (proof,goal) =
+ let curi, metasenv, pbo, pty = proof in
+ let metano,context,gty = CicUtil.lookup_meta goal metasenv in
+ match context with
+ (Some (Cic.Name s,_))::_ -> s
+ | _ -> assert false
+ in
+ let dummy = "dummy" in
+ Some arg,false,
+ (fun ~term typ ->
+ Tacticals.seq
+ ~tactics:
+ [ProofEngineStructuralRules.rename name dummy;
+ PT.letin_tac
+ ~mk_fresh_name_callback:(fun _ _ _ ~typ -> Cic.Name name) term;
+ ProofEngineStructuralRules.clearbody name;
+ ReductionTactics.change_tac
+ ~pattern:
+ (None,[name,Cic.Implicit (Some `Hole)], None)
+ (ProofEngineTypes.const_lazy_term typ);
+ ProofEngineStructuralRules.clear dummy
+ ]),
+ Some pat,gty
+ | _::_ -> assert false
+ in
+ let if_right_to_left do_not_change a b =
+ match direction with
+ | `RightToLeft -> if do_not_change then a else b
+ | `LeftToRight -> if do_not_change then b else a
+ in
+ let ty_eq,ugraph =
+ CicTypeChecker.type_of_aux' metasenv context equality
+ CicUniv.empty_ugraph in
+ let (ty_eq,metasenv',arguments,fresh_meta) =
+ ProofEngineHelpers.saturate_term
+ (ProofEngineHelpers.new_meta_of_proof proof) metasenv context ty_eq 0 in
+ let equality =
+ if List.length arguments = 0 then
+ equality
+ else
+ C.Appl (equality :: arguments) in
+ (* t1x is t2 if we are rewriting in an hypothesis *)
+ let eq_ind, ty, t1, t2, t1x =
+ match ty_eq with
+ | C.Appl [C.MutInd (uri, 0, []); ty; t1; t2]
+ when LibraryObjects.is_eq_URI uri ->
+ let ind_uri =
+ if_right_to_left dir2
+ LibraryObjects.eq_ind_URI LibraryObjects.eq_ind_r_URI
+ in
+ let eq_ind = C.Const (ind_uri uri,[]) in
+ if dir2 then
+ if_right_to_left true (eq_ind,ty,t2,t1,t2) (eq_ind,ty,t1,t2,t1)
+ else
+ if_right_to_left true (eq_ind,ty,t1,t2,t2) (eq_ind,ty,t2,t1,t1)
+ | _ -> raise (PET.Fail (lazy "Rewrite: argument is not a proof of an equality")) in
+ (* now we always do as if direction was `LeftToRight *)
+ let fresh_name =
+ FreshNamesGenerator.mk_fresh_name
+ ~subst:[] metasenv' context C.Anonymous ~typ:ty in
+ let lifted_t1 = CicSubstitution.lift 1 t1x in
+ let lifted_gty = CicSubstitution.lift 1 gty in
+ let lifted_conjecture =
+ metano,(Some (fresh_name,Cic.Decl ty))::context,lifted_gty in
+ let lifted_pattern =
+ let lifted_concl_pat =
+ match concl_pat with
+ | None -> None
+ | Some term -> Some (CicSubstitution.lift 1 term) in
+ Some (fun _ m u -> lifted_t1, m, u),[],lifted_concl_pat
+ in
+ let subst,metasenv',ugraph,_,selected_terms_with_context =
+ ProofEngineHelpers.select
+ ~metasenv:metasenv' ~ugraph ~conjecture:lifted_conjecture
+ ~pattern:lifted_pattern in
+ let metasenv' = CicMetaSubst.apply_subst_metasenv subst metasenv' in
+ let what,with_what =
+ (* Note: Rel 1 does not live in the context context_of_t *)
+ (* The replace_lifting_csc 0 function will take care of lifting it *)
+ (* to context_of_t *)
+ List.fold_right
+ (fun (context_of_t,t) (l1,l2) -> t::l1, Cic.Rel 1::l2)
+ selected_terms_with_context ([],[]) in
+ let t1 = CicMetaSubst.apply_subst subst t1 in
+ let t2 = CicMetaSubst.apply_subst subst t2 in
+ let equality = CicMetaSubst.apply_subst subst equality in
+ let abstr_gty =
+ ProofEngineReduction.replace_lifting_csc 0
+ ~equality:(==) ~what ~with_what:with_what ~where:lifted_gty in
+ let abstr_gty = CicMetaSubst.apply_subst subst abstr_gty in
+ let pred = C.Lambda (fresh_name, ty, abstr_gty) in
+ (* The argument is either a meta if we are rewriting in the conclusion
+ or the hypothesis if we are rewriting in an hypothesis *)
+ let metasenv',arg,newtyp =
+ match arg with
+ None ->
+ let gty' = CicSubstitution.subst t2 abstr_gty in
+ let irl =
+ CicMkImplicit.identity_relocation_list_for_metavariable context in
+ let metasenv' = (fresh_meta,context,gty')::metasenv' in
+ metasenv', C.Meta (fresh_meta,irl), Cic.Rel (-1) (* dummy term, never used *)
+ | Some arg ->
+ let gty' = CicSubstitution.subst t1 abstr_gty in
+ metasenv,arg,gty'
+ in
+ let exact_proof =
+ C.Appl [eq_ind ; ty ; t2 ; pred ; arg ; t1 ;equality]
+ in
+ let (proof',goals) =
+ PET.apply_tactic
+ (tac ~term:exact_proof newtyp) ((curi,metasenv',pbo,pty),goal)
+ in
+ let goals =
+ goals@(ProofEngineHelpers.compare_metasenvs ~oldmetasenv:metasenv
+ ~newmetasenv:metasenv')
+ in
+ (proof',goals)