123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463(************************************************************************)(* * The Rocq Prover / The Rocq 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) *)(************************************************************************)openPpopenUtilopenNamesopenTac2typesopenTac2extffiopenGenredexpropenProofview.Notationsletreturn=Proofview.tclUNITletthawrf=Tac2ffi.app_fun1fTac2ffi.unitr()lettactic_infer_flagswith_evar=Pretyping.{use_coercions=true;use_typeclasses=UseTC;solve_unification_constraints=true;fail_evar=notwith_evar;expand_evars=true;program_mode=false;polymorphic=false;undeclared_evars_patvars=false;patvars_abstract=false;unconstrained_sorts=false;}(** FIXME: export a better interface in Tactics *)letdelayed_of_tactictacenvsigma=let_,pv=Proofview.initsigma[]inletname,poly=Id.of_string"ltac2_delayed",falseinletc,pv,_,_=Proofview.apply~name~polyenvtacpvinlet_,sigma=Proofview.proofviewpvin(sigma,c)letdelayed_of_thunkrtacenvsigma=delayed_of_tactic(thawrtac)envsigmaletmk_bindings=function|ImplicitBindingsl->Tactypes.ImplicitBindingsl|ExplicitBindingsl->letl=List.mapCAst.makelinTactypes.ExplicitBindingsl|NoBindings->Tactypes.NoBindingsletmk_with_bindings(x,b)=(x,mk_bindingsb)letrecmk_intro_pattern=function|IntroForthcomingb->CAst.make@@Tactypes.IntroForthcomingb|IntroNamingipat->CAst.make@@Tactypes.IntroNaming(mk_intro_pattern_namingipat)|IntroActionipat->CAst.make@@Tactypes.IntroAction(mk_intro_pattern_actionipat)andmk_intro_pattern_naming=function|IntroIdentifierid->Namegen.IntroIdentifierid|IntroFreshid->Namegen.IntroFreshid|IntroAnonymous->Namegen.IntroAnonymousandmk_intro_pattern_action=function|IntroWildcard->Tactypes.IntroWildcard|IntroOrAndPatternipat->Tactypes.IntroOrAndPattern(mk_or_and_intro_patternipat)|IntroInjectionipats->Tactypes.IntroInjection(List.mapmk_intro_patternipats)|IntroApplyOn(c,ipat)->letc=CAst.make@@delayed_of_thunkTac2ffi.constrcinTactypes.IntroApplyOn(c,mk_intro_patternipat)|IntroRewriteb->Tactypes.IntroRewritebandmk_or_and_intro_pattern=function|IntroOrPatternipatss->Tactypes.IntroOrPattern(List.map(funipat->List.mapmk_intro_patternipat)ipatss)|IntroAndPatternipats->Tactypes.IntroAndPattern(List.mapmk_intro_patternipats)letmk_intro_patternsipat=List.mapmk_intro_patternipatletmk_occurrences=function|AllOccurrences->Locus.AllOccurrences|AllOccurrencesButl->Locus.AllOccurrencesButl|NoOccurrences->Locus.NoOccurrences|OnlyOccurrencesl->Locus.OnlyOccurrenceslletmk_occurrences_exproccs=letoccs=mk_occurrencesoccsinLocusops.occurrences_map(List.map(funi->Locus.ArgArgi))occsletmk_hyp_location(id,occs,h)=((mk_occurrences_exproccs,id),h)letmk_clausecl={Locus.onhyps=Option.map(funl->List.mapmk_hyp_locationl)cl.onhyps;Locus.concl_occs=mk_occurrences_exprcl.concl_occs;}letintros_patternsevipat=letipat=mk_intro_patternsipatinTactics.intros_patternsevipatletapplyadvevcbcl=letmapc=letc=thawconstr_with_bindingsc>>=funp->return(mk_with_bindingsp)inNone,CAst.makecinletcb=List.mapmapcbinmatchclwith|None->Tactics.apply_with_delayed_bindings_genadvevcb|Some(id,cl)->letcl=Option.mapmk_intro_patternclinTactics.apply_delayed_inadvevidcbclTacticals.tclIDTACletmk_destruction_arg=function|ElimOnConstrc->letc=c>>=func->return(mk_with_bindingsc)inTactics.ElimOnConstr(delayed_of_tacticc)|ElimOnIdentid->Tactics.ElimOnIdentCAst.(makeid)|ElimOnAnonHypn->Tactics.ElimOnAnonHypnletmk_induction_clause(arg,eqn,as_,occ)=leteqn=Option.map(funipat->CAst.make@@mk_intro_pattern_namingipat)eqninletas_=Option.map(funipat->CAst.make@@mk_or_and_intro_patternipat)as_inletocc=Option.mapmk_clauseoccin((None,mk_destruction_argarg),(eqn,as_),occ)letinduction_destructisrecev(ic:induction_clauselist)using=letic=List.mapmk_induction_clauseicinletusing=Option.mapmk_with_bindingsusinginInduction.induction_destructisrecev(ic,using)letelimevccopt=letc=mk_with_bindingscinletcopt=Option.mapmk_with_bindingscoptinTactics.elimevNoneccoptletgeneralizepl=letmk_occoccs=mk_occurrencesoccsinletpl=List.map(fun(c,occs,na)->(mk_occoccs,c),na)plinGeneralize.new_generalize_genplletgeneral_case_analysisevc=letc=mk_with_bindingscinTactics.general_case_analysisevNonecletconstructor_tacevnibnd=letbnd=mk_bindingsbndinTactics.constructor_tacevnibndletleft_with_bindingsevbnd=letbnd=mk_bindingsbndinTactics.left_with_bindingsevbndletright_with_bindingsevbnd=letbnd=mk_bindingsbndinTactics.right_with_bindingsevbndletsplit_with_bindingsevbnd=letbnd=mk_bindingsbndinTactics.split_with_bindingsev[bnd]letspecializecpat=letc=mk_with_bindingscinletpat=Option.mapmk_intro_patternpatinTactics.specializecpatletchangepatccl=letopenTac2ffiinProofview.Goal.enterbeginfungl->letcsubstenvsigma=letsubst=Array.map_of_listsnd(Id.Map.bindingssubst)indelayed_of_tactic(Tac2ffi.app_fun1c(arrayconstr)constrsubst)envsigmainletcl=mk_clauseclinTactics.change~check:truepatcclendletrewriteevrwclby=letmap_rw(orient,repeat,c)=letc=c>>=func->return(mk_with_bindingsc)in(Option.defaulttrueorient,repeat,None,delayed_of_tacticc)inletrw=List.mapmap_rwrwinletcl=mk_clauseclinletby=Option.map(funtac->Tacticals.tclCOMPLETE(thawTac2ffi.unittac),Equality.Naive)byinEquality.general_multi_rewriteevrwclbyletsetoid_rewriteorientcoccsid=letc=c>>=func->return(mk_with_bindingsc)inletoccs=mk_occurrencesoccsinRewrite.cl_rewrite_clause(delayed_of_tacticc)orientoccsidletsymmetrycl=letcl=mk_clauseclinTactics.intros_symmetryclletforwardfsttacipatc=letipat=Option.mapmk_intro_patternipatinTactics.forwardfsttacipatcletassert_=function|AssertValue(id,c)->letipat=CAst.make@@Tactypes.IntroNaming(Namegen.IntroIdentifierid)inTactics.forwardtrueNone(Someipat)c|AssertType(ipat,c,tac)->letipat=Option.mapmk_intro_patternipatinlettac=Option.map(funtac->thawTac2ffi.unittac)tacinTactics.forwardtrue(Sometac)ipatcletletin_pat_tacevipatnaccl=letipat=Option.map(fun(b,ipat)->(b,CAst.make@@mk_intro_pattern_namingipat))ipatinletcl=mk_clauseclinTactics.letin_pat_tacevipatnaccl(** Ltac interface treats differently global references than other term
arguments in reduction expressions. In Ltac1, this is done at parsing time.
Instead, we parse indifferently any pattern and dispatch when the tactic is
called. *)letmap_pattern_with_occs(pat,occ)=matchpatwith|Pattern.PRef(GlobRef.ConstRefcst)->(mk_occurrencesocc,Inl(Evaluable.EvalConstRefcst))|Pattern.PRef(GlobRef.VarRefid)->(mk_occurrencesocc,Inl(Evaluable.EvalVarRefid))|_->(mk_occurrencesocc,Inrpat)letget_evaluable_reference=function|GlobRef.VarRefid->Proofview.tclUNIT(Evaluable.EvalVarRefid)|GlobRef.ConstRefcst->Proofview.tclUNIT(Evaluable.EvalConstRefcst)|r->Proofview.tclZERO(Tacred.NotEvaluableRefr)letreducercl=letcl=mk_clauseclinTactics.reducerclletsimplflagswherecl=letwhere=Option.mapmap_pattern_with_occswhereinletcl=mk_clauseclinProofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}inTactics.reduce(Simpl(flags,where))clletcbvflagscl=letcl=mk_clauseclinProofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}inTactics.reduce(Cbvflags)clletcbnflagscl=letcl=mk_clauseclinProofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}inTactics.reduce(Cbnflags)clletlazy_flagscl=letcl=mk_clauseclinProofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}inTactics.reduce(Lazyflags)clletunfoldoccscl=letcl=mk_clauseclinletmap(gr,occ)=letocc=mk_occurrencesoccinget_evaluable_referencegr>>=fungr->Proofview.tclUNIT(occ,gr)inProofview.Monad.List.mapmapoccs>>=funoccs->Tactics.reduce(Unfoldoccs)clletpatternwherecl=letwhere=List.map(fun(c,occ)->(mk_occurrencesocc,c))whereinletcl=mk_clauseclinTactics.reduce(Patternwhere)clletvmwherecl=letwhere=Option.mapmap_pattern_with_occswhereinletcl=mk_clauseclinTactics.reduce(CbvVmwhere)clletnativewherecl=letwhere=Option.mapmap_pattern_with_occswhereinletcl=mk_clauseclinTactics.reduce(CbvNativewhere)clleteval_funredc=Tac2core.pf_applybeginfunenvsigma->let(redfun,_)=Redexpr.reduction_of_red_exprenvredinlet(sigma,ans)=redfunenvsigmacinProofview.Unsafe.tclEVARSsigma>>=fun()->Proofview.tclUNITansendleteval_redc=eval_funRedcleteval_hnfc=eval_funHnfcleteval_simplflagswherec=letwhere=Option.mapmap_pattern_with_occswhereinProofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}ineval_fun(Simpl(flags,where))cleteval_cbvflagsc=Proofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}ineval_fun(Cbvflags)cleteval_cbnflagsc=Proofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}ineval_fun(Cbnflags)cleteval_lazyflagsc=Proofview.Monad.List.mapget_evaluable_referenceflags.rConst>>=funrConst->letflags={flagswithrConst}ineval_fun(Lazyflags)cleteval_unfoldoccsc=letmap(gr,occ)=letocc=mk_occurrencesoccinget_evaluable_referencegr>>=fungr->Proofview.tclUNIT(occ,gr)inProofview.Monad.List.mapmapoccs>>=funoccs->eval_fun(Unfoldoccs)cleteval_foldclc=eval_fun(Foldcl)cleteval_patternwherec=letwhere=List.map(fun(pat,occ)->(mk_occurrencesocc,pat))whereineval_fun(Patternwhere)cleteval_vmwherec=letwhere=Option.mapmap_pattern_with_occswhereineval_fun(CbvVmwhere)cleteval_nativewherec=letwhere=Option.mapmap_pattern_with_occswhereineval_fun(CbvNativewhere)cleton_destruction_argtacevarg=Proofview.Goal.enterbeginfungl->matchargwith|None->tacevNone|Some(clear,arg)->letarg=matchargwith|ElimOnConstrc->letenv=Proofview.Goal.envglinProofview.tclEVARMAP>>=funsigma->c>>=fun(c,lbind)->letlbind=mk_bindingslbindinProofview.tclEVARMAP>>=funsigma'->letflags=tactic_infer_flagsevinlet(sigma',c)=Tactics.finish_evar_resolution~flagsenvsigma'(Somesigma,c)inProofview.tclUNIT(Somesigma',Tactics.ElimOnConstr(c,lbind))|ElimOnIdentid->Proofview.tclUNIT(None,Tactics.ElimOnIdentCAst.(makeid))|ElimOnAnonHypn->Proofview.tclUNIT(None,Tactics.ElimOnAnonHypn)inarg>>=fun(sigma',arg)->letarg=Some(clear,arg)inmatchsigma'with|None->tacevarg|Somesigma'->Tacticals.tclWITHHOLESev(tacevarg)sigma'endletdiscriminateevarg=letarg=Option.map(funarg->None,arg)arginon_destruction_argEquality.discr_tacevargletinjectionevipatarg=letarg=Option.map(funarg->None,arg)arginletipat=Option.mapmk_intro_patternsipatinlettacevarg=Equality.injClauseNoneipatevarginon_destruction_argtacevargletautorewrite~allbyidscl=letconds=ifallthenSomeEquality.AllMatcheselseNoneinletids=List.mapId.to_stringidsinletcl=mk_clauseclinmatchbywith|None->Autorewrite.auto_multi_rewrite?condsidscl|Someby->letby=thawTac2ffi.unitbyinAutorewrite.auto_multi_rewrite_with?condsbyidscl(** Auto *)letdelayed_of_globrefgr=();funenvsigma->Evd.fresh_globalenvsigmagrlettrivialdebuglemsdbs=letlems=List.mapdelayed_of_globreflemsinletdbs=Option.map(funl->List.mapId.to_stringl)dbsinAuto.gen_trivial~debuglemsdbsletautodebugnlemsdbs=letlems=List.mapdelayed_of_globreflemsinletdbs=Option.map(funl->List.mapId.to_stringl)dbsinAuto.gen_auto~debugnlemsdbsleteautodebugnlemsdbs=letlems=List.mapdelayed_of_globreflemsinletdbs=Option.map(funl->List.mapId.to_stringl)dbsinEauto.gen_eauto~debug?depth:nlemsdbslettypeclasses_eautostrategydepthdbs=letonly_classes,dbs=matchdbswith|None->true,[Class_tactics.typeclasses_db]|Somedbs->letdbs=List.mapId.to_stringdbsinfalse,dbsinClass_tactics.typeclasses_eauto~only_classes?strategy~depthdbsletunifyxy=Tactics.unifyxyletcurrent_transparent_state()=Proofview.tclENV>>=funenv->letstate=Conv_oracle.get_transp_state(Environ.oracleenv)inProofview.tclUNITstateletevarconv_unifystatexy=Tactics.evarconv_unify~statexy(** Inversion *)letinversionkndargpatids=letids=matchidswith|None->[]|Somel->linbeginmatchpatwith|None->Proofview.tclUNITNone|Some(IntroAction(IntroOrAndPatternp))->Proofview.tclUNIT(Some(CAst.make@@mk_or_and_intro_patternp))|Some_->Tacticals.tclZEROMSG(str"Inversion only accept disjunctive patterns")end>>=funpat->letinversion_arg=beginmatchargwith|None->assertfalse|Some(_,Tactics.ElimOnAnonHypn)->Inv.inv_clausekndpatids(AnonHypn)|Some(_,Tactics.ElimOnIdentid)->Inv.inv_clausekndpatids(NamedHypid)|Some(_,Tactics.ElimOnConstrc)->letopenTactypesinletanon=CAst.make@@IntroNamingNamegen.IntroAnonymousinTactics.specializec(Someanon)>>=fun()->Tacticals.onLastHypId(funid->Inv.inv_clausekndpatids(NamedHyp(CAst.makeid)))endinon_destruction_arginversiontrue(Some(None,arg))letcontradictionc=letc=Option.mapmk_with_bindingscinContradiction.contradictioncletcongruencenl=Cc_core_plugin.Cctac.congruence_tacn(Option.default[]l)letsimple_congruencenl=Cc_core_plugin.Cctac.simple_congruence_tacn(Option.default[]l)