123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openUtilopenNamesopenTermopsopenEConstropenInductiveopsopenHipatternopenTacmachopenTacticalsopenTacticstypeelim_kind=Caseofbool|Elim(* Find the right elimination suffix corresponding to the sort of the goal *)(* c should be of type A1->.. An->B with B an inductive definition *)letgeneral_elim_usingmk_elim(ind,u,args)id=matchmk_elimwith|Casedep->Clenv.case_pf~dep(mkVarid,mkApp(mkIndU(ind,u),args))|Elim->Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletsort=Retyping.get_sort_family_ofenvsigma(Proofview.Goal.conclgl)inletflags=Unification.elim_flags()inletgr=Indrec.lookup_eliminatorenvindsortinletsigma,elim=Evd.fresh_globalenvsigmagrinletelimt=Retyping.get_type_ofenvsigmaelimin(* applying elimination_scheme just a little modified *)letelimclause=Clenv.mk_clenv_fromenvsigma(elim,elimt)inletindmv=List.last(Clenv.clenv_argumentselimclause)inletelimclause=Clenv.clenv_instantiateindmvelimclause(mkVarid,mkApp(mkIndU(ind,u),args))inClenv.res_pf~flagselimclauseend(* computing the case/elim combinators *)letelim_on_batacnassums=Proofview.Goal.enterbeginfungl->letbranches=tryList.rev(List.firstnnassums(Proofview.Goal.hypsgl))withFailure_->CErrors.anomaly(Pp.str"make_elim_branch_assumptions.")intacbranchesendletcase_tacdepnamestac(ind,u,argsasspec)c=letopenProofview.NotationsinProofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletbranchsigns=Tacticals.compute_constructor_signaturesenv~rec_flag:false(ind,u)inletbrnames=Tacticals.compute_induction_namesfalsebranchsignsnamesinletafter_taci=letbranchnames=brnames.(i)inletn1=List.lengthbranchsigns.(i)inletn2=List.lengthbranchnamesinlet(l1,l2),l3=ifn1<n2thenList.chopn1branchnames,[]else(branchnames,[]),List.make(n1-n2)falsein(intro_patternsfalsel1)<*>(intros_clearingl3)<*>(elim_on_ba(tacl2)n1)inletbranchtacs=List.init(Array.lengthbranchsigns)after_tacingeneral_elim_using(Casedep)specc<*>(Proofview.tclEXTEND[]tclIDTACbranchtacs)end(* The following tactic Decompose repeatedly applies the
elimination(s) rule(s) of the types satisfying the predicate
``recognizer'' onto a certain hypothesis. For example :
Require Elim.
Require Le.
Goal (y:nat){x:nat | (le O x)/\(le x y)}->{x:nat | (le O x)}.
Intros y H.
Decompose [sig and] H;EAuto.
Qed.
Another example :
Goal (A,B,C:Prop)(A/\B/\C \/ B/\C \/ C/\A) -> C.
Intros A B C H; Decompose [and or] H; Assumption.
Qed.
*)letrecgeneral_decompose_auxrecognizerid=letopenDeclarationsinletopenProofview.NotationsinProofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinlet((ind,u),t)=pf_applyTacred.reduce_to_atomic_indgl(pf_get_type_ofgl(mkVarid))inlet_,args=decompose_app(Proofview.Goal.sigmagl)tinletrec_flag,mkelim=match(Environ.lookup_mind(fstind)env).mind_recordwith|NotRecord->true,Elim|FakeRecord|PrimRecord_->false,Casetrueinletbranchsigns=Tacticals.compute_constructor_signaturesenv~rec_flag(ind,u)inletnext_tacbas=letmapid=ifOnHyprecognizer(general_decompose_auxrecognizer)(fun_->tclIDTAC)idintclMAPmap(ids_of_named_contextbas)inletafter_taci=letnassums=List.lengthbranchsigns.(i)in(tclDOnassumsintro)<*>(clear[id])<*>(elim_on_banext_tacnassums)inletbranchtacs=List.init(Array.lengthbranchsigns)after_tacingeneral_elim_usingmkelim(ind,u,args)id<*>(Proofview.tclEXTEND[]tclIDTACbranchtacs)end(* We should add a COMPLETE to be sure that the created hypothesis
doesn't stay if no elimination is possible *)(* Best strategies but loss of compatibility *)lettmphyp_name=Id.of_string"_TmpHyp"letgeneral_decomposerecognizerc=Proofview.Goal.enterbeginfungl->lettypc=pf_get_type_ofglcintclTHENS(cuttypc)[intro_using_thentmphyp_name(funid->ifOnHyprecognizer(general_decompose_auxrecognizer)(funid->clear[id])id);exact_no_checkc]endlethead_inindltgl=letenv=Proofview.Goal.envglinletsigma=Tacmach.projectglintryletity,_=extract_mrectypesigmatinList.exists(funi->Environ.QInd.equalenv(fsti)(fstity))indlwithNot_found->falseletdecompose_thesecl=Proofview.Goal.enterbeginfungl->letindl=List.map(funx->x,UVars.Instance.empty)lingeneral_decompose(funenvsigma(_,t)->head_inindltgl)cendletdecompose_andc=general_decompose(funenvsigma(_,t)->is_recordenvsigmat)cletdecompose_orc=general_decompose(funenvsigma(_,t)->is_disjunctionenvsigmat)cleth_decomposelc=decompose_theseclleth_decompose_or=decompose_orleth_decompose_and=decompose_and