123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785(************************************************************************)(* * 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. *)openLtac_pluginopenUtilopenNamesopenConstropenContextopenLocusopenPrinteropenTermopsopenTacinterpopenSsrmatching_pluginopenSsrmatchingopenSsrastopenSsrprintersopenSsrcommonopenProofview.NotationsmoduleERelevance=EConstr.ERelevanceletssroldreworder=Summary.ref~name:"SSR:oldreworder"falselet()=Goptions.(declare_bool_option{optstage=Summary.Stage.Interp;optkey=["SsrOldRewriteGoalsOrder"];optread=(fun_->!ssroldreworder);optdepr=None;optwrite=(funb->ssroldreworder:=b)})(** The "simpl" tactic *)(* We must avoid zeta-converting any "let"s created by the "in" tactical. *)lettacred_simplenv=letsimpl_expr=Genredexpr.(Simpl(Redops.make_red_flag[FBeta;FMatch;FZeta;FDeltaBut[]],None))inletesimpl,_=Redexpr.reduction_of_red_exprenvsimpl_exprinletesimplesigmac=let(_,t)=esimplesigmacintinletsimplenvsigmac=(esimplenvsigmac)insimplletsafe_simpltacn=ifn=~-1thenProofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletconcl=Proofview.Goal.conclglinletcl=red_safe(tacred_simplenv)envsigmaconclinconvert_concl_no_checkclendelsessr_n_tac"simpl"nletsimpltac=function|Simpln->safe_simpltacn|Cutn->Tacticals.tclTRY(donetacn)|SimplCut(n,m)->Tacticals.tclTHEN(safe_simpltacm)(Tacticals.tclTRY(donetacn))|Nop->Tacticals.tclIDTACletsimpltacs=Proofview.Goal.enter(fun_->simpltacs)(** The "congr" tactic *)letinterp_congrarg_atenvsigmaist~conclnrftym=debug_ssr(fun()->Pp.(str"===interp_congrarg_at==="));letcongrn,_=mkSsrRRef"nary_congruence"inletargs1=mkRnatn::mkRHolesn@[ty]inletargs2=mkRHoles(3*n)inletrecloopi=ifi+n>mthenNoneelsetryletrt=mkRAppcongrn(args1@mkRApprf(mkRHolesi)::args2)indebug_ssr(fun()->Pp.(str"rt="++Printer.pr_glob_constr_envenvsigmart));Some(interp_refineenvsigmaist~conclrt)withewhenCErrors.noncriticale->loop(i+1)inloop0letpattern_id=mk_internal_id"pattern value"letcongrtac((n,t),ty)ist=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletconcl=Proofview.Goal.conclglindebug_ssr(fun()->(Pp.str"===congr==="));debug_ssr(fun()->Pp.(str"concl="++Printer.pr_econstr_envenvsigmaconcl));letnsigma,_asit=interp_termenvsigmaisttinletsigma=Evd.merge_universe_contextsigma(Evd.evar_universe_contextnsigma)inletf,_,_ucst=abs_evarsenvsigmaitinletist'={istwithlfun=Id.Map.addpattern_id(Tacinterp.Value.of_constrf)Id.Map.empty}inletrf=mkRltacVarpattern_idinletm=pf_nbargsenvsigmafinletcf=ifn>0thenmatchinterp_congrarg_atenvsigmaist'~conclnrftymwith|Somecf->cf|None->errorstrmPp.(str"No "++intn++str"-congruence with "++pr_termt)elseletrecloopi=ifi>mthenerrorstrmPp.(str"No congruence with "++pr_termt)elsematchinterp_congrarg_atenvsigmaist'~conclirftymwith|Somecf->cf|None->loop(i+1)inloop1inTacticals.(tclTHEN(refine_withcf)(tclTRYTactics.reflexivity))endletpf_typecheckt=Proofview.Goal.enterbeginfungl->letsigma,_=Typing.type_of(Proofview.Goal.envgl)(Proofview.Goal.sigmagl)tinProofview.Unsafe.tclEVARSsigmaendlettclMATCH_GOALenvsigmact_okt_fail=Proofview.Goal.enterbeginfungl->matchunify_HOenvsigma(Proofview.Goal.conclgl)cwith|sigma->Proofview.Unsafe.tclEVARSsigma<*>convert_concl~check:true(Reductionops.nf_evarsigmac)<*>t_oksigma|exceptionexnwhenCErrors.noncriticalexn->t_fail()endletmk_evarenvsigmaty=letsigma=Evd.create_evar_defssigmainlet(sigma,x)=Evarutil.new_evarenvsigmatyinsigma,xletnewssrcongrtacargist=letopenProofview.NotationsinProofview.Goal.enter_one~__LOC__beginfun_g->(Ssrcommon.tacMK_SSR_CONST"ssr_congr_arrow")end>>=funarr->Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletconcl=Proofview.Goal.conclglindebug_ssr(fun()->Pp.(str"===newcongr==="));debug_ssr(fun()->Pp.(str"concl="++Printer.pr_econstr_envenvsigmaconcl));(* utils *)letfssigmat=Reductionops.nf_evarsigmatinletssr_congrlr=EConstr.mkApp(arr,lr)inletsigma,eq=Evd.fresh_globalenvsigmaCoqlib.(lib_ref"core.eq.type")in(* here the two cases: simple equality or arrow *)letequality,_,eq_args,sigma'=saturateenvsigmaeq3inProofview.Unsafe.tclEVARSsigma<*>tclMATCH_GOALenvsigma'equality(funsigma'->letx=List.find_map_exn(fun(n,x,_)->ifn=0thenSomexelseNone)eq_argsinletty=fssigma'xincongrtac(arg,Detyping.detypeDetyping.NowId.Set.emptyenvsigmaty)ist)(fun()->tryletsigma,t_lhs=Evarutil.new_Typesigmainletsigma,t_rhs=Evarutil.new_Typesigmainletsigma,lhs=mk_evarenvsigmat_lhsinletsigma,rhs=mk_evarenvsigmat_rhsinletarrow=EConstr.mkArrowlhsERelevance.relevant(EConstr.Vars.lift1rhs)intclMATCH_GOALenvsigmaarrow(funsigma->letlr=[|fssigmalhs;fssigmarhs|]inleta=ssr_congrlrinTacticals.tclTHENLIST[pf_typechecka;Tactics.applya;congrtac(arg,mkRType)ist])(fun_->Tacticals.tclZEROMSGPp.(str"Conclusion is not an equality nor an arrow"))withewhenCErrors.noncriticale->Proofview.tclZEROe)end(** 7. Rewriting tactics (rewrite, unlock) *)(** Rewrite rules *)typessrwkind=RWredofssrsimpl|RWdef|RWeqtypessrrule=ssrwkind*ssrterm(** Rewrite arguments *)typessrrwarg=(ssrdir*ssrmult)*((ssrdocc*rpatternoption)*ssrrule)letnotimes=0letnomult=1,Onceletmkoccocc=None,occletnoclr=mkoccNoneletmkclrclr=Someclr,Noneletnodocc=mkclr[]letis_rw_cut=functionRWred(Cut_)->true|_->falseletmk_rwarg(d,(n,_asm))((clr,occasdocc),rx)(rt,_asr):ssrrwarg=ifrt<>RWeqthenbeginifrt=RWredNop&¬(m=nomult&&occ=None&&rx=None)&&(clr=None||clr=Some[])thenanomaly"Improper rewrite clear switch";ifd=R2L&&rt<>RWdefthenCErrors.user_err(Pp.str"Right-to-left switch on simplification");ifn<>1&&is_rw_cutrtthenCErrors.user_err(Pp.str"Bad or useless multiplier");ifocc<>None&&rx=None&&rt<>RWdefthenCErrors.user_err(Pp.str"Missing redex for simplification occurrence")end;(d,m),((docc,rx),r)letnorwmult=L2R,nomultletnorwocc=noclr,Noneletsimplintacoccrdxsim=letsimptacm=Proofview.Goal.enterbeginfungl->ifm<>~-1thenbeginifrdx<>NonethenCErrors.user_err(Pp.str"Custom simpl tactic does not support patterns");ifocc<>NonethenCErrors.user_err(Pp.str"Custom simpl tactic does not support occurrence numbers");simpltac(Simplm)endelseletsigma0,concl0,env0=Proofview.Goal.(sigmagl,conclgl,envgl)inletsimpenvc__=red_safeTacred.simplenvsigma0cinconvert_concl_no_check(eval_patternenv0sigma0(Reductionops.nf_evarsigma0concl0)rdxoccsimp)endinletopenTacticalsinProofview.Goal.enterbeginfun_->matchsimwith|Simplm->simptacm|SimplCut(n,m)->tclTHEN(simptacm)(tclTRY(donetacn))|_->simpltacsimendletrecget_evalrefenvsigmac=matchEConstr.kindsigmacwith|Varid->Evaluable.EvalVarRefid|Const(k,_)->Evaluable.EvalConstRefk|App(c',_)->get_evalrefenvsigmac'|Cast(c',_,_)->get_evalrefenvsigmac'|Proj(p,_,_)->Evaluable.EvalProjectionRef(Names.Projection.reprp)|_->errorstrmPp.(str"The term "++pr_econstr_pat(Global.env())sigmac++str" is not unfoldable")(* Strip a pattern generated by a prenex implicit to its constant. *)letstrip_unfold_term_((sigma,t)asp)kt=matchEConstr.kindsigmatwith|App(f,a)whenkt=NoFlag&&Array.for_all(EConstr.isEvarsigma)a&&EConstr.isConstsigmaf->(sigma,f),true|Const_|Var_->p,true|Proj_->p,true|_->p,falseletsame_projenvsigmat1t2=matchEConstr.kindsigmat1,EConstr.kindsigmat2with|Proj(c1,_,_),Proj(c2,_,_)->Environ.QProjection.equalenvc1c2|_->falseletclassify_patternp=matchpwith|None->None|Somep->redex_of_patternpletunfoldintacoccrdxt(kt,_)=Proofview.Goal.enterbeginfungl->letfssigmax=Reductionops.nf_evarsigmaxinletsigma0=Proofview.Goal.sigmaglinletenv0=Proofview.Goal.envglinletconcl0=Proofview.Goal.conclglinlet(sigma,t),const=strip_unfold_termenv0tktinletbodyenvtc=Tacred.unfoldn[AllOccurrences,get_evalrefenvsigmat]envsigma0cinleteasy=occ=None&&rdx=Noneinletred_flags=ifeasythenRedFlags.betaiotazetaelseRedFlags.betaiotainletbetaenv=Reductionops.clos_norm_flagsred_flagsenvsigma0inletunfold,conclude=matchclassify_patternrdxwith|None->letrigidev=Evd.memsigma0evinletu=mk_tpatternenv0~rigidtL2Rt(empty_tpatterns(Evd.create_evar_defssigma))inletfind_T,end_T=mk_tpattern_matcher~raise_NoMatch:truesigma0occuin(funenvc_h->tryfind_Tenvch~k:(funenvc__->bodyenvtc)withNoMatchwheneasy->c|NoMatch|NoProgress->errorstrmPp.(str"No occurrence of "++pr_econstr_patenvsigma0t++spc()++str"in "++Printer.pr_econstr_envenvsigmac)),(fun()->tryignore@@end_T()with|NoMatchwheneasy->()|NoMatch->anomaly"unfoldintac")|Some_->(funenv(casorig_c)_h->ifconstthenletrecauxc=matchEConstr.kindsigma0cwith|Const_whenEConstr.eq_constrsigma0ct->bodyenvtt|App(f,a)whenEConstr.eq_constrsigma0ft->EConstr.mkApp(bodyenvff,a)|Proj_whensame_projenvsigma0ct->bodyenvtc|_->letc=Reductionops.whd_betaiotazetaenvsigma0cinmatchEConstr.kindsigma0cwith|Const_whenEConstr.eq_constrsigma0ct->bodyenvtt|App(f,a)whenEConstr.eq_constrsigma0ft->EConstr.mkApp(bodyenvff,a)|Proj_whensame_projenvsigma0ct->bodyenvtc|Constf->aux(bodyenvcc)|App(f,a)->aux(EConstr.mkApp(bodyenvff,a))|_->errorstrmPp.(str"The term "++pr_econstr_envenvsigmaorig_c++str" contains no "++pr_econstr_envenvsigmat++str" even after unfolding")inauxcelsetrybodyenvt(fs(unify_HOenvsigmact)t)withewhenCErrors.noncriticale->errorstrmPp.(str"The term "++pr_econstr_envenvsigmac++spc()++str"does not unify with "++pr_econstr_patenvsigmat)),ignoreinletconcl=trybetaenv0(eval_patternenv0sigma0concl0rdxoccunfold)withOption.IsNone->errorstrmPp.(str"Failed to unfold "++pr_econstr_patenv0sigmat)inlet()=conclude()inconvert_concl~check:trueconclendletfoldtacoccrdxft=Proofview.Goal.enterbeginfungl->letsigma0=Proofview.Goal.sigmaglinletenv0=Proofview.Goal.envglinletconcl0=Proofview.Goal.conclglinletsigma,t=ftinlett=Reductionops.nf_evarsigmatinletfold,conclude=matchclassify_patternrdxwith|None->letut=red_product_skip_idenv0sigmatinletrigidev=Evd.memsigma0evinletut=mk_tpattern~rigidenv0tL2Rut(empty_tpatterns(Evd.create_evar_defssigma))inletfind_T,end_T=mk_tpattern_matcher~raise_NoMatch:truesigma0occutin(funenvc_h->tryfind_Tenvch~k:(funenvt__->t)withNoMatch->c),(fun()->tryignore@@end_T()withNoMatch->())|Some_->(funenvc_h->tryletsigma=unify_HOenvsigmactinReductionops.nf_evarsigmatwithewhenCErrors.noncriticale->errorstrmPp.(str"fold pattern "++pr_econstr_patenvsigmat++spc()++str"does not match redex "++pr_econstr_patenvsigmac)),ignoreinletconcl=eval_patternenv0sigma0concl0rdxoccfoldinlet()=conclude()inconvert_concl~check:trueconclendletconverse_dir=functionL2R->R2L|R2L->L2Rletrw_progressrhslhsise=not(EConstr.eq_constriselhs(Evarutil.nf_evariserhs))(* Coq has a more general form of "equation" (any type with a single *)(* constructor with no arguments with_rect_r elimination lemmas). *)(* However there is no clear way of determining the LHS and RHS of *)(* such a generic Leibniz equation -- short of inspecting the type *)(* of the elimination lemmas. *)letrecstrip_prod_expand_letsigmac=matchEConstr.kindsigmacwith|Prod(_,_,c')->strip_prod_expand_letsigmac'|LetIn(_,v,_,c')->strip_prod_expand_letsigma(EConstr.Vars.subst1vc)|Cast(c',_,_)->strip_prod_expand_letsigmac'|_->cletrule_id=mk_internal_id"rewrite rule"exceptionPRtype_errorof(Environ.env*Evd.evar_map*Pretype_errors.pretype_error)optionletid_map_redex_sigma~before:_~after=sigma,after(* Invariants expected from the arguments:
⊢ rdx : rdx_ty
pattern_id : rdx_ty ⊢ pred : Type@{s}
⊢ new_rdx : rdx_ty
⊢ c : c_ty
⊢ c_ty ≡ EQN rdx_ty rdx new_rdx
*)letpirrel_rewrite?(under=false)?(map_redex=id_map_redex)predrdxrdx_tynew_rdxdir(sigma,c)c_ty=letopenTacmachinletopenTacticalsinProofview.Goal.enterbeginfungl->(* ppdebug(lazy(str"sigma@pirrel_rewrite=" ++ pr_evar_map None sigma)); *)letenv=pf_envglinletbeta=Reductionops.clos_norm_flagsRedFlags.betaenvsigmainletsigma,new_rdx=map_redexenvsigma~before:rdx~after:new_rdxinletsigma,p=(* The resulting goal *)Evarutil.new_evarenvsigma(beta(EConstr.Vars.subst1new_rdxpred))inletpred=EConstr.mkNamedLambdasigma(make_annotpattern_idERelevance.relevant)rdx_typredinletsigma,elim=letsort=Tacticals.elimination_sort_of_goalglinmatchEquality.eq_elimination_ref(dir=L2R)sortwith|Somer->Evd.fresh_globalenvsigmar|None->let((kn,i)asind,_)=Tacred.eval_to_quantified_indenvsigmac_tyinletsort=Tacticals.elimination_sort_of_goalglinletsigma,elim=Evd.fresh_globalenvsigma(Indrec.lookup_eliminatorenvindsort)inifdir=R2Lthensigma,elimelseletelim,_=EConstr.destConstsigmaeliminletmp,l=KerName.repr(Constant.canonicalelim)inletl'=Label.of_id(Nameops.add_suffix(Label.to_idl)"_r")inletc1'=Global.constant_of_delta_kn(Constant.canonical(Constant.make2mpl'))inEvd.fresh_globalenvsigma(ConstRefc1')in(* We check the proof is well typed. We assume that the type of [elim] is of
the form [forall (A : Type) (x : A) (P : A -> Type@{s}), T] s.t. the only
universes to unify are by checking the [A] and [P] arguments. *)letsigma=tryletopenEConstrinletelimT=Retyping.get_type_ofenvsigmaeliminlet(idA,tA,elimT)=destProdsigmaelimTinlet(_,_,elimT)=destProdsigmaelimTinlet(idP,tP,_)=destProdsigmaelimTinletsigma=Typing.checkenvsigmardx_tytAinlettP=mkLetIn(idA,rdx_ty,tA,mkLetIn(anonR,mkProp,mkTypeUniv.Universe.type1,tP))inletsigma=Typing.checkenvsigmapredtPinsigmawith|Pretype_errors.PretypeError(env,sigma,te)->raise(PRtype_error(Some(env,sigma,te)))|ewhenCErrors.noncriticale->raise(PRtype_errorNone)inletproof=EConstr.mkApp(elim,[|rdx_ty;new_rdx;pred;p;rdx;c|])indebug_ssr(fun()->Pp.(str"pirrel_rewrite: proof term: "++pr_econstr_envenvsigmaproof));Proofview.tclORELSE(refine_with~first_goes_last:(not!ssroldreworder||under)~with_evars:under(sigma,proof))(fun(e,i)->(* we generate a msg like: "Unable to find an instance for the variable" *)matchEConstr.kindsigmacwith|App(hd,args)->lethd_ty=Retyping.get_type_ofenvsigmahdinletnames=letrecauxenvt=function0->[]|n->lett=Reductionops.whd_allenvsigmatinletopenEConstrinmatchkind_of_typesigmatwith|ProdType(name,ty,t)->name.binder_name::aux(EConstr.push_rel(Context.Rel.Declaration.LocalAssum(name,ty))env)t(n-1)|_->(* In the case the head is an HO constant it may accept more arguments *)CList.initn(fun_->Names.Name.Anonymous)inauxenvhd_ty(Array.lengthargs)inletmiss=Util.List.map_filter(fun(t,name)->letevs=Evar.Set.elements(Evarutil.undefined_evars_of_termsigmat)inletopen_evs=List.filter(funk->Sorts.InProp<>Retyping.get_sort_family_ofenvsigma(Evd.evar_concl(Evd.find_undefinedsigmak)))evsinifopen_evs<>[]thenSomenameelseNone)(List.combine(Array.to_listargs)names)intclZEROMSGPp.(Himsg.explain_refiner_errorenvsigma(Logic.UnresolvedBindingsmiss)++(Pp.fnl()++str"Rule's type:"++spc()++pr_econstr_envenvsigmahd_ty))|_->Proofview.tclZERO~info:ie)endletpf_merge_uc_ofssigma=Evd.merge_universe_contextsigma(Evd.evar_universe_contexts)letrwcltac?under?map_redexclrdxdir(sigma,r)=letopenProofview.NotationsinProofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma0=Proofview.Goal.sigmaglinletsigma=resolve_typeclasses~where:r~fail:falseenvsigmainletr_n,evs,ucst=abs_evarsenvsigma0(sigma,r)inletn=List.lengthevsinletr_n'=abs_ctermenvsigma0nr_ninletr'=EConstr.Vars.subst_varsigmapattern_idr_n'inletsigma0=Evd.set_universe_contextsigma0ucstinletsigma,rdxt=Typing.type_ofenvsigmardxinlet()=debug_ssr(fun()->Pp.(str"r@rwcltac="++pr_econstr_envenvsigmar))inletcvtac,rwtac,sigma0=ifEConstr.Vars.closed0sigma0r'thenletc_eq=Coqlib.(lib_ref"core.eq.type")inletsigma,c_ty=Typing.type_ofenvsigmarinlet()=debug_ssr(fun()->Pp.(str"c_ty@rwcltac="++pr_econstr_envenvsigmac_ty))inletopenEConstrinmatchkind_of_typesigma(Reductionops.whd_allenvsigmac_ty)with|AtomicType(e,a)whenSsrcommon.is_ind_refenvsigmaec_eq->letnew_rdx=ifdir=L2Rthena.(2)elsea.(1)inpirrel_rewrite?under?map_redexclrdxa.(0)new_rdxdir(sigma,r)c_ty,Tacticals.tclIDTAC,sigma0|_->letcl'=EConstr.mkApp(EConstr.mkNamedLambdasigma(make_annotpattern_idERelevance.relevant)rdxtcl,[|rdx|])inletsigma,_=Typing.type_ofenvsigmacl'inletsigma0=pf_merge_uc_ofsigmasigma0inconvert_concl~check:truecl',rewritetac?underdirr',sigma0elseletdc,r2=EConstr.decompose_lambda_n_assumsigma0nr'inletr3,_,r3t=tryEConstr.destCastsigma0r2withewhenCErrors.noncriticale->errorstrmPp.(str"no cast from "++pr_econstr_patenvsigma0r++str" to "++pr_econstr_envenvsigma0r2)inletcl'=EConstr.mkNamedProdsigma(make_annotrule_idERelevance.relevant)(EConstr.it_mkProd_or_LetInr3tdc)(EConstr.Vars.lift1cl)inletcl''=EConstr.mkNamedProdsigma(make_annotpattern_idERelevance.relevant)rdxtcl'inletitacs=[introidpattern_id;introidrule_id]inletcltac=Tactics.clear[pattern_id;rule_id]inletrwtacs=[Tacticals.tclTHENLIST[rewritetac?underdir(EConstr.mkVarrule_id);if!ssroldreworder||Option.defaultfalseunderthenProofview.tclUNIT()elseProofview.cycle1];cltac]inTactics.apply_type~typecheck:truecl''[rdx;EConstr.it_mkLambda_or_LetInr3dc],Tacticals.tclTHENLIST(itacs@rwtacs),sigma0inletcvtac'=Proofview.tclORELSEcvtacbeginfunction|(PRtype_errore,_)->leterror=Option.cata(fun(env,sigma,te)->Pp.(fnl()++str"Type error was: "++Himsg.explain_pretype_errorenvsigmate))(Pp.mt())einifoccur_existentialsigma0(Tacmach.pf_conclgl)thenTacticals.tclZEROMSGPp.(str"Rewriting impacts evars"++error)elseTacticals.tclZEROMSGPp.(str"Dependent type error in rewrite of "++pr_econstr_envenvsigma0(EConstr.mkNamedLambdasigma(make_annotpattern_idERelevance.relevant)rdxtcl)++error)|(e,info)->Proofview.tclZERO~infoeendinProofview.Unsafe.tclEVARSsigma0<*>Tacticals.tclTHENcvtac'rwtacendletlz_setoid_relation=letsdir=["Classes";"RelationClasses"]inletlast_srel=refNoneinfunenv->match!last_srelwith|Some(env',srel)whenenv'==env->srel|_->letsrel=trySome(UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.find_reference"Class_setoid"("Coq"::sdir)"RewriteRelation"[@ocaml.warning"-3"])withewhenCErrors.noncriticale->Noneinlast_srel:=Some(env,srel);srelletssr_is_setoidenv=matchlz_setoid_relationenvwith|None->fun___->false|Somesrel->funsigmarargs->Rewrite.is_applied_rewrite_relationenvsigma[](EConstr.mkApp(r,args))<>Noneletclosed0_checkenvsigmaclp=ifEConstr.Vars.closed0sigmaclthenerrorstrmPp.(str"No occurrence of redex "++pr_econstr_envenvsigmap)letdir_org=functionL2R->1|R2L->2letrwprocess_ruleenvdirrule=letis_setoid=ssr_is_setoidenvinletprod_type=Coqlib.lib_ref"core.prod.type"inletprod_intro=Coqlib.lib_ref"core.prod.intro"inletprod_proj1=Coqlib.lib_ref"core.prod.proj1"inletprod_proj2=Coqlib.lib_ref"core.prod.proj2"inletr_sigma,rules=letrecloopdsigmart0rsred=lett=ifred=1thenTacred.hnf_constrenvsigmat0elseReductionops.clos_whd_flagsRedFlags.betaiotazetaenvsigmat0indebug_ssr(fun()->Pp.(str"rewrule="++pr_econstr_patenvsigmat));matchEConstr.kindsigmatwith|Prod(_,xt,at)->letsigma=Evd.create_evar_defssigmainlet(sigma,x)=Evarutil.new_evarenvsigmaxtinloopdsigmaEConstr.(mkApp(r,[|x|]))(EConstr.Vars.subst1xat)rs0|App(pr,a)whenis_ind_refenvsigmaprprod_type->letr0=Reductionops.clos_whd_flagsRedFlags.allenvsigmarinletsigma,pL,pR=matchEConstr.kindsigmar0with|App(c,ra)whenis_construct_refenvsigmacprod_intro->(sigma,ra.(2),ra.(3))|_->letra=Array.appenda[|r|]inletsigma,pi1=Evd.fresh_globalenvsigmaprod_proj1inletsigma,pi2=Evd.fresh_globalenvsigmaprod_proj2inletpL=EConstr.mkApp(pi1,ra)inletpR=EConstr.mkApp(pi2,ra)in(sigma,pL,pR)inifEConstr.is_lib_refenvsigma"core.True.type"a.(0)thenloop(converse_dird)sigmapRa.(1)rs0elseletsigma,rs2=loopdsigmapRa.(1)rs0inloopdsigmapLa.(0)rs20|App(r_eq,a)whenHipattern.match_with_equality_typeenvsigmat!=None->let(ind,u)=EConstr.destIndsigmar_eqandrhs=Array.lastainletnp=Inductiveops.inductive_nparamdeclsenvindinletindu=(ind,u)inletind_ct=Inductiveops.type_of_constructorsenvinduinletlhs0=last_argsigma(strip_prod_expand_letsigmaind_ct.(0))inletrdesc=matchEConstr.kindsigmalhs0with|Reli->letlhs=a.(np-i)inletlhs,rhs=ifd=L2Rthenlhs,rhselserhs,lhsin(* msgnl (str "RW: " ++ pr_rwdir d ++ str " " ++ pr_constr_pat r ++ str " : "
++ pr_constr_pat lhs ++ str " ~> " ++ pr_constr_pat rhs); *)d,r,lhs,rhs(*
let l_i, r_i = if d = L2R then i, 1 - ndep else 1 - ndep, i in
let lhs = a.(np - l_i) and rhs = a.(np - r_i) in
let a' = Array.copy a in let _ = a'.(np - l_i) <- mkVar pattern_id in
let r' = mkCast (r, DEFAULTcast, mkApp (r_eq, a')) in
(d, r', lhs, rhs)
*)|_->letlhs=EConstr.Vars.substl(array_list_of_tl(Array.suba0np))lhs0inletlhs,rhs=ifd=R2Lthenlhs,rhselserhs,lhsinletd'=ifArray.lengtha=1thendelseconverse_dirdind',r,lhs,rhsinsigma,rdesc::rs|App(s_eq,a)whenis_setoidsigmas_eqa->letnp=Array.lengthaandi=3-dir_orgdinletlhs=a.(np-i)andrhs=a.(np+i-3)inleta'=Array.copyainlet_=a'.(np-i)<-EConstr.mkVarpattern_idinletr'=EConstr.mkCast(r,DEFAULTcast,EConstr.mkApp(s_eq,a'))insigma,(d,r',lhs,rhs)::rs|_->ifred=0thenloopdsigmartrs1elseerrorstrmPp.(str"not a rewritable relation: "++pr_econstr_patenvsigmat++spc()++str"in rule "++pr_econstr_patenvsigma(sndrule))inletsigma,r=ruleinlett=Retyping.get_type_ofenvsigmarinloopdirsigmart[]0inr_sigma,rulesletrwrxtac?under?map_redexoccrdx_patdirrule=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma0=Proofview.Goal.sigmaglinletr_sigma,rules=rwprocess_ruleenvdirruleinletfind_rulerdx=letrecrwtac=function|[]->errorstrmPp.(str"pattern "++pr_econstr_patenvsigma0rdx++str" does not match "++pr_dir_sidedir++str" of "++pr_econstr_patenvsigma0(sndrule))|(d,r,lhs,rhs)::rs->tryletise=unify_HOenv(Evd.create_evar_defsr_sigma)lhsrdxinifnot(rw_progressrhsrdxise)thenraiseNoMatchelsed,(ise,Evd.evar_universe_contextise,Reductionops.nf_evariser)withewhenCErrors.noncriticale->rwtacrsinrwtacrulesinletenv0=envinletconcl0=Proofview.Goal.conclglinletrigidev=Evd.memsigma0evinletfind_R,conclude=matchclassify_patternrdx_patwith|None->letupats_origin=dir,(sndrule)inletrpatpats(d,r,lhs,rhs)=letr=Reductionops.nf_evarr_sigmarinletlhs=Reductionops.nf_evarr_sigmalhsinmk_tpattern~ok:(rw_progressrhs)~rigidenv0rdlhspatsinletrpats=List.fold_leftrpat(empty_tpatternsr_sigma)rulesinletfind_R,end_R=mk_tpattern_matchersigma0occ~upats_originrpatsin(funec_i->find_R~k:(fun___h->EConstr.mkRelh)eci),funcl->letrdx,d,r=end_R()inclosed0_checkenv0sigma0clrdx;(d,r),rdx|Some(_,e)->letr=refNonein(funenvc_h->do_oncer(fun()->find_rulec,c);EConstr.mkRelh),(funconcl->closed0_checkenv0sigma0concle;let(d,(ev,ctx,c)),x=assert_donerin(d,(true,ev,ctx,Reductionops.nf_evarevc)),x)inletconcl0=Reductionops.nf_evarsigma0concl0inletconcl=eval_patternenv0sigma0concl0rdx_patoccfind_Rinlet(d,(_,sigma,uc,t)),rdx=concludeconclinletr=Evd.merge_universe_contextsigmauc,tinrwcltac?under?map_redexconclrdxdrendletssrinstancesofruleistdirarg=Proofview.Goal.enterbeginfungl->letenv0=Proofview.Goal.envglinletsigma0=Proofview.Goal.sigmaglinletconcl0=Proofview.Goal.conclglinletrigidev=Evd.memsigma0evinletrule=interp_termenv0sigma0istarginletr_sigma,rules=rwprocess_ruleenv0dirruleinletfind,conclude=letupats_origin=dir,(sndrule)inletrpatpats(d,r,lhs,rhs)=letr=Reductionops.nf_evarr_sigmarinletlhs=Reductionops.nf_evarr_sigmalhsinmk_tpattern~ok:(rw_progressrhs)~rigidenv0rdlhspatsinletrpats=List.fold_leftrpat(empty_tpatternsr_sigma)rulesinmk_tpattern_matcher~all_instances:true~raise_NoMatch:truesigma0None~upats_originrpatsinletprintenvpc_=Feedback.msg_infoPp.(hov1(str"instance:"++spc()++pr_econstr_envenvr_sigmap++spc()++str"matches:"++spc()++pr_econstr_envenvr_sigmac));cinFeedback.msg_infoPp.(str"BEGIN INSTANCES");trywhiletruedoignore(findenv0(Reductionops.nf_evarsigma0concl0)1~k:print)done;raiseNoMatchwithNoMatch->Feedback.msg_infoPp.(str"END INSTANCES");Tacticals.tclIDTACendletipat_rewriteoccdirc=Proofview.Goal.enterbeginfungl->rwrxtacoccNonedir(Proofview.Goal.sigmagl,c)endletrwargtac?under?map_redexist((dir,mult),(((oclr,occ),grx),(kind,gt)))=letopenProofview.NotationsinProofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletfail=reffalseinletinterp_rpatternenvsigmagc=tryinterp_rpatternenvsigmagcwithewhenCErrors.noncriticale&&sndmult=May->fail:=true;{pat_sigma=sigma;pat_pat=TEConstr.mkProp}inletinterpenvsigmagc=tryinterp_termenvsigmaistgcwithewhenCErrors.noncriticale&&sndmult=May->fail:=true;(sigma,EConstr.mkProp)inletrwtac=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletrx=Option.map(interp_rpatternenvsigma)grxin(* Evarmaps below are extensions of sigma, so setting the universe context is correct *)letsigma=matchrxwith|None->sigma|Some{pat_sigma=s}->Evd.set_universe_contextsigma(Evd.evar_universe_contexts)inlett=interpenvsigmagtinletsigma=Evd.set_universe_contextsigma(Evd.evar_universe_context(fstt))inProofview.Unsafe.tclEVARSsigma<*>(matchkindwith|RWredsim->simplintacoccrxsim|RWdef->ifdir=R2Lthenfoldtacoccrxtelseunfoldintacoccrxtgt|RWeq->rwrxtac?under?map_redexoccrxdirt)endinletctac=cleartac(interp_clrsigma(oclr,(fstgt,snd(interpenvsigmagt))))inif!failthenctacelseTacticals.tclTHEN(tclMULTmultrwtac)ctacend(** Rewrite argument sequence *)(* type ssrrwargs = ssrrwarg list *)(** The "rewrite" tactic *)letssrrewritetac?under?map_redexistrwargs=Proofview.Goal.enterbeginfun_->Tacticals.tclTHENLIST(List.map(rwargtac?under?map_redexist)rwargs)end(** The "unlock" tactic *)letunfoldtacocckotkt=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletconcl=Proofview.Goal.conclglinletconcl=Evarutil.nf_evarsigmaconclinletcl,c=fill_occ_termenvsigmaconclocc(fst(strip_unfold_termenvtkt))inletcl'=EConstr.Vars.subst1(Tacred.unfoldn[OnlyOccurrences[1],get_evalrefenvsigmac]envsigmac)clinletf=ifko=NonethenRedFlags.betaiotazetaelseRedFlags.betaiotainconvert_concl~check:true(Reductionops.clos_norm_flagsfenvsigmacl')endletunlocktacistargs=letopenProofview.Notationsinletutac(occ,gt)=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinunfoldtacoccocc(interp_termenvsigmaistgt)(fstgt)endinSsrcommon.tacMK_SSR_CONST"locked">>=funlocked->Ssrcommon.tacMK_SSR_CONST"master_key">>=funkey->letktacs=[(Proofview.tclEVARMAP>>=funsigma->unfoldtacNoneNone(sigma,locked)InParens);Ssrelim.casetackey(fun?seed:_k->k)]inTacticals.tclTHENLIST(List.maputacargs@ktacs)