123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176(************************************************************************)(* * 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) *)(************************************************************************)(* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *)openNamesopenConstropenContextopenTermopsopenProofview.NotationsopenSsrastopenSsrcommonmoduleRelDecl=Context.Rel.DeclarationmoduleNamedDecl=Context.Named.Declaration(** Tacticals (+, -, *, done, by, do, =>, first, and last). *)letget_index=functionLocus.ArgArgi->i|_->anomaly"Uninterpreted index"(* Toplevel constr must be globalized twice ! *)(** The "first" and "last" tacticals. *)lettclPERMpermtac=Proofview.Goal.enterbeginfungls->tac<*>(Proofview.Unsafe.tclGETGOALS>>=fungls->Proofview.Unsafe.tclSETGOALS(permgls))endletrot_hypsdirihyps=letn=List.lengthhypsinifi=0thenList.revhypselseifi>nthenCErrors.user_err(Pp.str"Not enough goals")elseletrecrotil_hyps=function|hyp::hyps'wheni>0->rot(i-1)(hyp::l_hyps)hyps'|hyps'->hyps'@(List.revl_hyps)inrot(matchdirwithL2R->i|R2L->n-i)[]hypslettclSEQATistatac1dir(ivar,((_,atacs2),atac3))=leti=get_indexivarinletevtact=ssrevaltacisttinlettac1=evtacatac1inifatacs2=[]&&atac3<>NonethentclPERM(rot_hypsdiri)tac1elseletevotac=functionSomeatac->evtacatac|_->Tacticals.tclIDTACinlettac3=evotacatac3inletrecmk_padn=ifn>0thentac3::mk_pad(n-1)else[]inmatchdir,mk_pad(i-1),List.mapevotacatacs2with|L2R,[],[tac2]whenatac3=None->Tacticals.tclTHENFIRSTtac1tac2|L2R,[],[tac2]whenatac3=None->Tacticals.tclTHENLASTtac1tac2|L2R,pad,tacs2->Tacticals.tclTHENSFIRSTntac1(Array.of_list(pad@tacs2))tac3|R2L,pad,tacs2->Tacticals.tclTHENSLASTntac1tac3(Array.of_list(tacs2@pad))(** The "in" pseudo-tactical *)(* {{{ **********************************************)lethidden_goal_tag="the_hidden_goal"letcheck_wgen_uniqgens=letclears=List.flatten(List.mapfstgens)incheck_hyps_uniq[]clears;letids=CList.map_filter(function(_,Some((id,_),_))->Some(hoi_idid)|_->None)gensinletreccheckids=function|id::_whenList.memidids->errorstrmPp.(str"Duplicate generalization "++Id.printid)|id::hyps->check(id::ids)hyps|[]->()incheck[]idsletpf_clauseidsgensclseq=letkeep_clears=List.map(fun(x,_)->x,None)inifgens<>[]then(check_wgen_uniqgens;gens)elseifclseq<>InAll&&clseq<>InAllHypsthenkeep_clearsgenselseCErrors.user_err(Pp.str"assumptions should be named explicitly")lethidden_clseq=functionInHyps|InHypsSeq|InAllHyps->true|_->falseletposetacidcl=Tactics.pose_tac(Nameid)cllethidetacsclseqidhidecl0=ifnot(hidden_clseqclseq)then[]else[posetacidhidecl0;convert_concl_no_check(EConstr.mkVaridhide)]letendclausestacid_mapclseqgl_idcl0=letopenTacmachinProofview.Goal.enterbeginfungl->letnot_hyp'id=not(List.mem_associdid_map)inletorig_idid=tryList.associdid_mapwithNot_found->idinletdc,c=EConstr.decompose_prod_decls(projectgl)(pf_conclgl)inlethide_goal=hidden_clseqclseqinletc_hidden=hide_goal&&EConstr.eq_constr(projectgl)c(EConstr.mkVargl_id)inletrecfitsforced=function|(id,_)::ids,decl::dc'whenRelDecl.get_namedecl=Nameid->fitstrue(ids,dc')|ids,dc'->forced&&ids=[]&&(nothide_goal||dc'=[]&&c_hidden)inletrecunmarkc=matchEConstr.kind(projectgl)cwith|Varidwhenhidden_clseqclseq&&id=gl_id->cl0|Prod({binder_name=Nameid}asna,t,c')whenList.mem_associdid_map->EConstr.mkProd({nawithbinder_name=Name(orig_idid)},unmarkt,unmarkc')|LetIn({binder_name=Nameid}asna,v,t,c')whenList.mem_associdid_map->EConstr.mkLetIn({nawithbinder_name=Name(orig_idid)},unmarkv,unmarkt,unmarkc')|_->EConstr.map(projectgl)unmarkcinletutachyp=Tactics.convert_hyp~check:false~reorder:false(NamedDecl.map_construnmarkhyp)inletutacs=List.maputac(Proofview.Goal.hypsgl)inletugtac=Proofview.Goal.enterbeginfungl->convert_concl_no_check(unmark(pf_conclgl))endinletctacs=ifhide_goalthen[Tactics.clear[gl_id]]else[]inletmktacitacs=Tacticals.tclTHENLIST(itacs@utacs@ugtac::ctacs)inletitac(_,id)=Tactics.introductionidiniffitsfalse(id_map,List.revdc)thenmktac(List.mapitacid_map)elseletall_ids=ids_of_rel_contextdc@pf_ids_of_hypsglinifList.for_allnot_hyp'all_ids&¬c_hiddenthenmktac[]elseerrorstrmPp.(str"tampering with discharged assumptions of \"in\" tactical")endlettclCLAUSEStac(gens,clseq)=letopenProofview.NotationsinProofview.Goal.enterbeginfungl->ifclseq=InGoal||clseq=InSeqGoalthentacelseletclr_gens=pf_clauseidsgensclseqinletclear=Tacticals.tclTHENLIST(List.rev(List.fold_rightclr_of_wgenclr_gens[]))inletgl_id=mk_anon_idhidden_goal_tag(Tacmach.pf_ids_of_hypsgl)inletcl0=Proofview.Goal.conclglinletdtac=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletc=Proofview.Goal.conclglinletfoldgen(sigma,args,c)=abs_wgenenvsigmatruemk_discharged_idgen(args,c)inletsigma,args,c=List.fold_rightfoldgens(sigma,[],c)inProofview.Unsafe.tclEVARSsigma<*>Tactics.apply_type~typecheck:truecargsendinletendtac=letid_map=CList.map_filter(function|_,Some((x,_),_)->letid=hoi_idxinSome(mk_discharged_idid,id)|_,None->None)gensinendclausestacid_mapclseqgl_idcl0inTacticals.tclTHENLIST(hidetacsclseqgl_idcl0@[dtac;clear;tac;endtac])end(** The "do" tactical. ********************************************************)lethinttacistis_by(is_or,atacs)=Proofview.Goal.enterbeginfun_->letdtac=ifis_bythendonetac~-1elseTacticals.tclIDTACinletmktac=function|Someatac->Tacticals.tclTHEN(ssrevaltacistatac)dtac|_->dtacinmatchList.mapmktacatacswith|[]->ifis_orthendtacelseTacticals.tclIDTAC|[tac]->tac|tacs->Tacticals.tclFIRSTtacsendletssrdotacist(((n,m),tac),clauses)=letmul=get_indexn,mintclCLAUSES(tclMULTmul(hinttacistfalsetac))clauses