123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629(************************************************************************)(* * 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) *)(************************************************************************)(* This file is (C) Copyright 2006-2015 Microsoft Corporation and Inria. *)openLtac_pluginopenNamesopenPpopenGenargopenContextmoduleCoqConstr=ConstropenCoqConstropenLibnamesopenTacticsopenTermopsopenGlob_termopenUtilopenEvdopenTacexpropenTacinterpopenPretypingopenPpconstropenPrinteropenEvar_kindsopenConstrexpropenConstrexpr_opstypessrtermkind=|InParens|WithAt|NoFlag|Cpatternleterrorstrm=CErrors.user_errletloc_errorlocmsg=CErrors.user_err?loc(strmsg)letppnl=Feedback.msg_infoletpp=CDebug.create~name:"ssrmatching"()letpps=pp(fun()->Lazy.forces)let{Goptions.get=option_LegacyFoUnif}=Goptions.declare_bool_option_and_ref~key:["SsrMatching";"LegacyFoUnif"]~depr:{Deprecation.since=Some"9.2";note=Some"Use this flag only to port scripts from 9.1 to 9.2, do not leave it in final scripts."}~value:false()(** Utils *)(* {{{ *****************************************************************)letenv_sizeenv=List.length(Environ.named_contextenv)letsafeDestAppsigmac=matchEConstr.kindsigmacwithApp(f,a)->f,a|_->c,[||](* Toplevel constr must be globalized twice ! *)letglob_constristgenvsigmat=matcht,istwith|(_,Somece),Someist->letvars=Id.Map.fold(funx_accu->Id.Set.addxaccu)ist.lfunId.Set.emptyinletltacvars={Constrintern.empty_ltac_signwithConstrintern.ltac_vars=vars}inConstrintern.intern_genWithoutTypeConstraint~ltacvars:ltacvarsgenvsigmace|(rc,None),_->rc|(_,Some_),None->CErrors.anomalyPp.(str"glob_constr: term with no ist")(* Term printing utilities functions for deciding bracketing. *)letpr_parenprxx=hov1(str"("++prxx++str")")(* String lexing utilities *)letskip_wscharss=letrecloopi=matchs.[i]with'\n'..' '->loop(i+1)|_->iinloop(* We also guard characters that might interfere with the ssreflect *)(* tactic syntax. *)letguard_termkindsi=matchs.[i]with|'('->false|'{'|'/'|'='->true|_->kind=InParens(* The call 'guard s i' should return true if the contents of s *)(* starting at i need bracketing to avoid ambiguities. *)letpr_guardedguardprcc=lets=Pp.string_of_ppcmds(prcc)^"$"inifguards(skip_wscharss0)thenpr_parenprccelseprcc(* More sensible names for constr printers *)letwith_global_env_evmfx=letenv=Global.env()inletsigma=Evd.from_envenvinf?flags:Noneenvsigmaxletprl_glob_constr=with_global_env_evmpr_lglob_constr_envletpr_glob_constr=with_global_env_evmpr_glob_constr_envletprl_constr_expr=pr_lconstr_exprletpr_constr_expr=pr_constr_exprletprl_glob_constr_and_exprenvsigma=function|_,Somec->prl_constr_expr~flags:(current_flags())envsigmac|c,None->prl_glob_constrcletpr_glob_constr_and_exprenvsigma=function|_,Somec->pr_constr_expr~flags:(current_flags())envsigmac|c,None->pr_glob_constrc(** Adding a new uninterpreted generic argument type *)letadd_genargtagpr=letwit=Genarg.make0taginlettag=Geninterp.Val.createtaginletglobistx=(ist,x)inletsubst_x=xinletinterpistx=Ftactic.returnxinletgen_prenvsigma___=prenvsigmainlet()=Genintern.register_intern0witglobinlet()=Gensubst.register_subst0witsubstinlet()=Tacinterp.Register.register_interp0witinterpinlet()=Geninterp.register_val0wit(Some(Geninterp.Val.Basetag))inPptactic.declare_extra_genarg_pprulewitgen_prgen_prgen_pr;wit(** Constructors for constr_expr *)letisCVar=function{CAst.v=CRef(qid,_)}->qualid_is_identqid|_->falseletdestCVar=function|{CAst.v=CRef(qid,_)}whenqualid_is_identqid->qualid_basenameqid|_->CErrors.anomaly(str"not a CRef.")letisGLambdac=matchDAst.getcwithGLambda(Name_,_,_,_,_)->true|_->falseletdestGLambdac=matchDAst.getcwithGLambda(Nameid,_,_,_,c)->(id,c)|_->CErrors.anomaly(str"not a GLambda")letisGHolec=matchDAst.getcwithGHole_->true|_->falseletmkCHole~loc=CAst.make?loc@@CHole(None)letmkCLambda?locnametyt=CAst.make?loc@@CLambdaN([CLocalAssum([CAst.make?locname],None,DefaultExplicit,ty)],t)letmkCCast?loctty=CAst.make?loc@@CCast(t,SomeDEFAULTcast,ty)(** Constructors for rawconstr *)letmkRHole=DAst.make@@GHole(GInternalHole)letmkRAppfargs=ifargs=[]thenfelseDAst.make@@GApp(f,args)letmkRCastrcrt=DAst.make@@GCast(rc,SomeDEFAULTcast,rt)letmkRLambdanst=DAst.make@@GLambda(n,None,Explicit,s,t)(* }}} *)exceptionNoProgress(** Unification procedures. *)(* To enforce the rigidity of the rooted match we always split *)(* top applications, so the unification procedures operate on *)(* arrays of patterns and terms. *)(* We perform three kinds of unification: *)(* EQ: exact conversion check *)(* FO: first-order unification of evars, without conversion *)(* HO: higher-order unification with conversion *)(* The subterm unification strategy is to find the first FO *)(* match, if possible, and the first HO match otherwise, then *)(* compute all the occurrences that are EQ matches for the *)(* relevant subterm. *)(* Additional twists: *)(* - If FO/HO fails then we attempt to fill evars using *)(* typeclasses before raising an outright error. We also *)(* fill typeclasses even after a successful match, since *)(* beta-reduction and canonical instances may leave *)(* undefined evars. *)(* - We do postchecks to rule out matches that are not *)(* closed or that assign to a global evar; these can be *)(* disabled for rewrite or dependent family matches. *)(* - We do a full FO scan before turning to HO, as the FO *)(* comparison can be much faster than the HO one. *)letunif_EQenvsigmapc=letenv=Environ.set_universes(Evd.universessigma)envinReductionops.infer_convenvsigmapcletunif_EQ_refenvisepc=matchunif_EQenv!isepcwith|None->false|Someise'->ise:=ise';trueletunif_EQ_argsenvsigmapaa=letn=Array.lengthpainletise=refsigmainletrecloopi=(i=n)||unif_EQ_refenvisepa.(i)a.(i)&&loop(i+1)inifloop0thenSome!iseelseNoneletunif_HOenvisepc=tryEvarconv.unify_delayenvisepcwithEvarconv.UnableToUnify(ise,err)->raisePretype_errors.(PretypeError(env,ise,CannotUnify(p,c,Someerr)))letunif_HO_argsenvise0paica=letn=Array.lengthpainletrecloopisej=ifj=ntheniseelseloop(unif_HOenvisepa.(j)(ca.(i+j)))(j+1)inloopise00(* FO unification should boil down to calling w_unify with no_delta, but *)(* alas things are not so simple: w_unify does partial type-checking, *)(* which breaks down when the no-delta flag is on (as the Rocq type system *)(* requires full convertibility. The workaround here is to convert all *)(* evars into metas, since 8.2 does not TC metas. This means some lossage *)(* for HO evars, though hopefully Miller patterns can pick up some of *)(* those cases, and HO matching will mop up the rest. *)letflags_FOenv=letoracle=Environ.oracleenvinletts=Conv_oracle.get_transp_stateoracleinletflags={(Unification.default_no_delta_unify_flagsts).Unification.core_unify_flagswithUnification.modulo_conv_on_closed_terms=None;Unification.modulo_eta=true;Unification.modulo_betaiota=true;Unification.modulo_delta_types=ts}in{Unification.core_unify_flags=flags;Unification.merge_unify_flags=flags;Unification.subterm_unify_flags=flags;Unification.allow_K_in_toplevel_higher_order_unification=false;Unification.resolve_evars=(Unification.default_no_delta_unify_flagsts).Unification.resolve_evars}letlegacy_unif_FOenvisemetaspc=let_:_*Evd.evar_map=Unification.w_unify~metasenviseConversion.CONV~flags:(flags_FOenv)pcin()typehd_comparison=|CompareArgsofevar_map*Unification.Meta.t*Impargs.implicit_statuslist|CanonicalInfRequired|CanonicalRedRequiredofEvd.evar_map*EConstr.t*int|Differentletimplicits_for_rewrite_ofgr=Impargs.implicits_of_globalgr|>List.last|>sndletfailure_FO()=raise(CErrors.user_errPp.(mt()))letrecsame_hdenvisemetaspc=matchEConstr.kindisep,EConstr.kindisecwith|Const(c1,_),Const(c2,_)whenEnviron.QConstant.equalenvc1c2->CompareArgs(ise,metas,implicits_for_rewrite_of(GlobRef.ConstRefc1))|Ind(c1,_),Ind(c2,_)whenEnviron.QInd.equalenvc1c2->CompareArgs(ise,metas,implicits_for_rewrite_of(GlobRef.IndRefc1))|Construct(c1,_),Construct(c2,_)whenEnviron.QConstruct.equalenvc1c2->CompareArgs(ise,metas,implicits_for_rewrite_of(GlobRef.ConstructRefc1))|Const(c1,_),_whenStructures.Structure.is_projectionc1->CanonicalInfRequired|_,Const(c2,i)whenStructures.Structure.is_projectionc2->letb=Environ.constant_value_inenv(c2,EConstr.EInstance.kindisei)inCanonicalRedRequired(ise,EConstr.of_constrb,Structures.Structure.projection_nparamsenvc2)|Relc1,Relc2whenc1==c2->CompareArgs(ise,metas,[])|Varc1,Varc2whenId.equalc1c2->CompareArgs(ise,metas,implicits_for_rewrite_of(GlobRef.VarRefc1))|Proj(p1,_,x),Proj(p2,_,y)whenEnviron.QProjection.equalenvp1p2->letmetas,ise=unif_FO_skip_implenvisemetasxyinCompareArgs(ise,metas,[])|_->Differentandunif_FO_skip_implenvisemetaspc=matchEConstr.kindisep,EConstr.kindisecwith|Metai,_whenUnification.Meta.meta_opt_fvaluemetasi=None->letise,metas=Unification.Meta.meta_assigni(c,TypeNotProcessed)metasiseinmetas,ise|Metai,_->beginmatchUnification.Meta.meta_opt_fvaluemetasiwith|None->assertfalse|Some{Unification.rebus=p}->unif_FO_skip_implenvisemetaspcend(* | App(hd,args1), _ when EConstr.isMeta ise hd -> metas, ise *)(* | App(hd,args1), App(f,args2) when EConstr.isMeta ise hd ->
if Array.length args1 > Array.length args2 then failure_FO ();
let args2, rest = CArray.chop (Array.length args2 - Array.length args1) args2 in
let rhs = EConstr.mkApp (f,args2) in
pp(lazy(str "HO-FO" ++ pr_econstr_env env ise hd ++ str " = " ++ pr_econstr_env env ise rhs));
let metas, ise = unif_FO_skip_impl env ise metas hd rhs in
unif_FO_skip_impl3 env ise metas (Array.to_list args1) (Array.to_list rest) [] *)|Proj(p1,_,x),Proj(p2,_,y)whenEnviron.QProjection.equalenvp1p2->unif_FO_skip_impl3envisemetas[x][y][]|App(hd1,args1),App(hd2,args2)whennot@@EConstr.isMetaisehd1->beginmatchsame_hdenvisemetashd1hd2with|CanonicalRedRequired(ise,proj,narg)whenArray.lengthargs2>narg->pp(lazy(str"Red in "++pr_econstr_envenvisec));letc'=letopenReductionopsinletmetas={meta_value=(funi->Option.map(funx->x.Unification.rebus)(Unification.Meta.meta_opt_fvaluemetasi))}inStack.zipise@@whd_betaiota_deltazeta_for_iota_stateTransparentState.fullenvise~metas(EConstr.mkApp(proj,args2),Stack.empty)inpp(lazy(str"Red out "++pr_econstr_envenvisec'));ifEConstr.eq_constrisecc'thenfailure_FO()elseunif_FO_skip_implenvisemetaspc'|CanonicalInfRequired->pp(lazy(str"Skip"));metas,ise|CompareArgs(ise,metas,imp)->pp(lazy(str"Rec"));unif_FO_skip_impl3envisemetas(Array.to_listargs1)(Array.to_listargs2)imp|_->pp(lazy(str"Fail"));failure_FO()end|_->letkludgev=EConstr.mkLambda(make_annotAnonymousEConstr.ERelevance.relevant,EConstr.mkProp,v)inUnification.w_unify~metasenviseConversion.CONV~flags:(flags_FOenv)(kludgep)(kludgec)andunif_FO_skip_impl3envisemetasargs1args2imp=matchargs1,args2,impwith|a1::args1,a2::args2,Some_::imp->pp(lazy(str"skip impl "++pr_econstr_envenvisea1++str" = "++pr_econstr_envenvisea2));unif_FO_skip_impl3envisemetasargs1args2imp|a1::args1,a2::args2,None::imp->pp(lazy(str"do "++pr_econstr_envenvisea1++str" = "++pr_econstr_envenvisea2));letmetas,ise=unif_FO_skip_implenvisemetasa1a2inunif_FO_skip_impl3envisemetasargs1args2imp|a1::args1,a2::args2,[]->pp(lazy(str"do "++pr_econstr_envenvisea1++str" = "++pr_econstr_envenvisea2));letmetas,ise=unif_FO_skip_implenvisemetasa1a2inunif_FO_skip_impl3envisemetasargs1args2[]|[],[],_->pp(lazy(str"good"));metas,ise|_->pp(lazy(str"bad"));failure_FO()letnew_unif_FOenvisemetaspc=pp(lazy(str"NEW FO "++pr_econstr_envenvisep++str" = "++pr_econstr_envenvisec));let_:_*Evd.evar_map=unif_FO_skip_implenvisemetaspcin()letunif_FOenvisemetaspc=ifoption_LegacyFoUnif()thenlegacy_unif_FOenvisemetaspcelsenew_unif_FOenvisemetaspc(* Perform evar substitution in main term and prune substitution. *)letnf_open_termsigma0isec=letopenEConstrinlets'=refsigma0inletrecnfc'=matchEConstr.kindisec'with|Evarex->letk,a=exinleta'=SList.Skip.mapnfainifnot(Evd.mem!s'k)thens':=Evd.add!s'k(Evarutil.nf_evar_infoise(Evd.find_undefinedisek));mkEvar(k,a')|_->mapisenfc'inletcopy_defk_()=letEvarInfoevi=Evd.findisekinmatchEvd.evar_bodyeviwith|Evar_definedc'->letc'=nfc'ins':=Evd.definekc'!s'|_->()inletc'=nfcinlet_=Evd.fold_undefinedcopy_defsigma0()inletchanged=sigma0!=!s'inchanged,!s',Evd.ustateise,c'letunif_end?(solve_TC=true)envsigma0ise0ptok=letise=Evarconv.solve_unif_constraints_with_heuristicsenvise0inlettcs=Evd.get_typeclass_evarsiseinletc,s,uc,t=nf_open_termsigma0iseptinletise1=create_evar_defssinletise1=Evd.set_typeclass_evarsise1(Evar.Set.filter(funev->Evd.is_undefinedise1ev)tcs)inletise1=Evd.set_ustateise1ucinletise2=ifsolve_TCthenTypeclasses.resolve_typeclasses~fail:trueenvise1elseise1inifnot(okise)thenraiseNoProgresselseifise2==ise1then(c,s,uc,t)elseletc,s,uc',t=nf_open_termsigma0ise2tinc,s,UState.unionucuc',tletunify_HOenvsigma0t1t2=letsigma=unif_HOenvsigma0t1t2inlet_,sigma,uc,_=unif_end~solve_TC:falseenvsigma0sigmat2(fun_->true)inEvd.set_ustatesigmauc(* This is what the definition of iter_constr should be... *)letiter_constr_LRsigmafc=matchEConstr.kindsigmacwith|Evar(k,a)->SList.Skip.iterfa|Cast(cc,_,t)->fcc;ft|Prod(_,t,b)|Lambda(_,t,b)->ft;fb|LetIn(_,v,t,b)->fv;ft;fb|App(cf,a)->fcf;Array.iterfa|Case(_,_,pms,((_,p),_),iv,v,b)->fv;Array.iterfpms;fp;iter_invertfiv;Array.iter(fun(_,c)->fc)b|Fix(_,(_,t,b))|CoFix(_,(_,t,b))->fori=0toArray.lengtht-1doft.(i);fb.(i)done|Proj(_,_,a)->fa|Array(_u,t,def,ty)->Array.iterft;fdef;fty|(Rel_|Meta_|Var_|Sort_|Const_|Ind_|Construct_|Int_|Float_|String_)->()(* The comparison used to determine which subterms matches is KEYED *)(* CONVERSION. This looks for convertible terms that either have the same *)(* same head constant as pat if pat is an application (after beta-iota), *)(* or start with the same constr constructor (esp. for LetIn); this is *)(* disregarded if the head term is let x := ... in x, and casts are always *)(* ignored and removed). *)(* Record projections get special treatment: in addition to the projection *)(* constant itself, ssreflect also recognizes head constants of canonical *)(* projections. *)exceptionNoMatchtypessrdir=L2R|R2Lletpr_dir_side=functionL2R->str"LHS"|R2L->str"RHS"letinv_dir=functionL2R->R2L|R2L->L2Rtypepattern_class=|KpatFixed|KpatConst|KpatEvarofEvar.t|KpatLet|KpatLam|KpatRigid|KpatFlex|KpatProjofConstant.ttypetpattern={up_k:pattern_class;up_FO:Unification.Meta.t*EConstr.t;up_f:EConstr.t;up_a:EConstr.tarray;up_t:EConstr.t;(* equation proof term or matched term *)up_dir:ssrdir;(* direction of the rule *)up_ok:EConstr.t->evar_map->bool;(* progress test for rewrite *)}typetpatterns={tpat_sigma:Evd.evar_map;tpat_pats:tpatternlist;}letempty_tpatternssigma={tpat_sigma=sigma;tpat_pats=[]}(* Technically we only care about the metas of [sigma] in the [tpatterns] type.
Should we [create_evar_defs] here? *)letall_ok__=trueletproj_nparamsenvc=try1+Structures.Structure.projection_nparamsenvcwithNot_found->0letisRigidsigmac=matchEConstr.kindsigmacwith|(Prod_|Sort_|Lambda_|Case_|Fix_|CoFix_|Int_|Float_|String_|Array_)->true|(Rel_|Var_|Meta_|Evar(_,_)|Cast(_,_,_)|LetIn(_,_,_,_)|App(_,_)|Const(_,_)|Ind((_,_),_)|Construct(((_,_),_),_)|Proj_)->falselethole_var=mkVar(Id.of_string"_")letpr_constr_patenvsigmac0=letrecwipe_evarc=ifisEvarcthenhole_varelsemapwipe_evarcinpr_constr_envenvsigma(wipe_evarc0)letehole_var=EConstr.mkVar(Id.of_string"_")letpr_econstr_patenvsigmac0=letrecwipe_evarc=letopenEConstrinifisEvarsigmacthenehole_varelsemapsigmawipe_evarcinletdummy_decl=letdummy_prod=mkProd(make_annotAnonymousSorts.Relevant,mkProp,mkProp)inletna=make_annot(EConstr.destVarsigmaehole_var)Sorts.RelevantinContext.Named.Declaration.(LocalAssum(na,dummy_prod))inletenv=Environ.push_namedProofVardummy_declenvinpr_econstr_envenvsigma(wipe_evarc0)(* Turn (new) evars into metas *)letevars_for_FO~hack~rigidenv(ise0:evar_map)c0=letopenEConstrinletmetas=refUnification.Meta.emptyinletsigma=refise0inletnenv=env_sizeenv+ifhackthen1else0inletrecputc=matchEConstr.kind!sigmacwith|Evar(k,a)->ifrigidkthenmap!sigmaputcelseletevi=Evd.find_undefined!sigmakinletdc=List.firstn(max0(SList.lengtha-nenv))(evar_filtered_contextevi)inletabs_dc(d,c)=function|Context.Named.Declaration.LocalDef(x,b,t)->d,mkNamedLetIn!sigmax(putb)(putt)c|Context.Named.Declaration.LocalAssum(x,t)->mkVarx.binder_name::d,mkNamedProd!sigmax(putt)cinleta,t=Context.Named.fold_insideabs_dc~init:([],put(Evd.evar_conclevi))dcinletm=Evarutil.new_meta()inlet()=metas:=Unification.Meta.meta_declaremt!metasinsigma:=Evd.definek(applistc(mkMetam)a)!sigma;putc|_->map!sigmaputcinletc1=putc0in!metas,c1(* Compile a match pattern from a term; t is the term to fill. *)(* p_origin can be passed to obtain a better error message *)letmk_tpattern?p_origin?(hack=false)?(ok=all_ok)~rigidenvtdirp{tpat_sigma=ise;tpat_pats=pats}=letopenEConstrinletk,f,a=letf,a=Reductionops.whd_betaiota_stackenvisepinmatchEConstr.kindisefwith|Const(p,_)->letnp=proj_nparamsenvpinifnp=0||np>List.lengthathenKpatConst,f,aelseleta1,a2=List.chopnpainKpatProjp,(applistcfa1),a2|Proj(p,_,arg)->KpatProj((Environ.projection_repr_constantenv(Projection.reprp))),f,a|Var_|Ind_|Construct_->KpatFixed,f,a|Evar(k,_)->ifrigidkthenKpatEvark,f,aelseifa<>[]thenKpatFlex,f,aelse(matchp_originwithNone->CErrors.user_errPp.(str"indeterminate pattern")|Some(dir,rule)->errorstrm(str"indeterminate "++pr_dir_sidedir++str" in "++pr_econstr_patenviserule))|LetIn(_,v,_,b)->ifb<>mkRel1thenKpatLet,f,aelseKpatFlex,v,a|Lambda_->KpatLam,f,a|_->KpatRigid,f,ainletaa=Array.of_listainletp'=evars_for_FO~hack~rigidenvise(mkApp(f,aa))inletpat={up_k=k;up_FO=p';up_f=f;up_a=aa;up_ok=ok;up_dir=dir;up_t=t}in{tpat_sigma=ise;tpat_pats=pats@[pat]}(* Specialize a pattern after a successful match: assign a precise head *)(* kind and arity for Proj and Flex patterns. *)letungen_upatlhs(c,sigma,uc,t)u=letf,a=safeDestAppsigmalhsinletk=matchkind(EConstr.Unsafe.to_constrf)with|Var_|Ind_|Construct_->KpatFixed|Const_->KpatConst|Evar(k,_)->ifis_definedsigmakthenraiseNoMatchelseKpatEvark(* FIXME: why do we observe defined evars here? *)|LetIn_->KpatLet|Lambda_->KpatLam|_->KpatRigidinc,sigma,uc,{uwithup_k=k;up_FO=(Unification.Meta.empty,lhs);up_f=f;up_a=a;up_t=t}letnb_cs_proj_argsenvisepcfu=letopenEConstrinletopenStructuresinletopenValuePatterninletnak=letopenCanonicalSolutioninlet_,{cvalue_arguments}=findenvise(GlobRef.ConstRefpc,k)inList.lengthcvalue_argumentsinletnargs_of_projt=matchEConstr.kindisetwith|App(_,args)->Array.lengthargs|Proj_->0(* if splay_app calls expand_projection, this has to be
the number of arguments including the projected *)|_->assertfalseintrymatchEConstr.kindisefwith|Prod_->naProd_cs|Sorts->na(Sort_cs(ESorts.quality_or_setises))|Const(c',_)whenEnviron.QConstant.equalenvc'pc->nargs_of_proju.up_f|Proj(c',_,_)whenEnviron.QConstant.equalenv((Environ.projection_repr_constantenv(Projection.reprc')))pc->nargs_of_proju.up_f|Proj(c',_,_)->let_=na(Proj_cs(Names.Projection.reprc'))in0|Var_|Ind_|Construct_|Const_->na(Const_cs(fst@@destRefisef))|_->-1withNot_found->-1letisEvar_kisekf=matchEConstr.kindisefwithEvar(k',_)->k=k'|_->falseletnb_argssigmac=matchEConstr.kindsigmacwithApp(_,a)->Array.lengtha|_->0letmkSubArgia=ifi=Array.lengthathenaelseArray.suba0iletmkSubAppfia=letopenEConstrinifi=0thenfelsemkApp(f,mkSubArgia)letsplay_appise=letrecloopca=matchEConstr.kindisecwith|App(f,a')->loopf(Array.appenda'a)|Cast(c',_,_)->loopc'a|_->c,ainfunc->matchEConstr.kindisecwith|App(f,a)->loopfa|Cast_|Evar_->loopc[||]|_->c,[||]letfilter_upatenvsigmai0fnufpats=letopenEConstrinletna=Array.lengthu.up_ainifn<nathenfpatselseletnp=matchu.up_kwith|KpatConstwheneq_constr_nounivssigmau.up_ff->na|KpatFixedwheneq_constr_nounivssigmau.up_ff->na|KpatEvarkwhenisEvar_ksigmakf->na|KpatLetwhenisLetInsigmaf->na|KpatLamwhenisLambdasigmaf->na|KpatRigidwhenisRigidsigmaf->na|KpatFlex->na|KpatProjpc->letnp=na+nb_cs_proj_argsenvsigmapcfuinifn<npthen-1elsenp|_->-1inifnp<nathenfpatselselet()=if!i0<nptheni0:=nin(u,np)::fpatsleteq_prim_projenvsigmact=matchEConstr.kindsigmatwith|Proj(p,_,_)->Environ.QConstant.equalenv((Environ.projection_repr_constantenv(Projection.reprp)))c|_->falseletfilter_upat_FOenvsigmai0fnufpats=letopenEConstrinletnp=nb_argssigma(sndu.up_FO)inifn<npthenfpatselseletok=matchu.up_kwith|KpatConst->eq_constr_nounivssigmau.up_ff|KpatFixed->eq_constr_nounivssigmau.up_ff|KpatEvark->isEvar_ksigmakf|KpatLet->isLetInsigmaf|KpatLam->isLambdasigmaf|KpatRigid->isRigidsigmaf|KpatProjpc->isRefXenvsigma(ConstRefpc)f||eq_prim_projenvsigmapcf|KpatFlex->i0:=n;trueinifokthenbeginif!i0<nptheni0:=np;(u,np)::fpatsendelsefpatsexceptionFoundUnifof(bool*evar_map*UState.t*tpattern)(* Note: we don't update env as we descend into the term, as the primitive *)(* unification procedure always rejects subterms with bound variables. *)letdont_impact_evars_insigma0cl=letevs_in_cl=Evd.evars_of_termsigma0clinfunsigma->Evar.Set.for_all(funk->trylet_=Evd.find_undefinedsigmakintruewithNot_found->false)evs_in_cl(* We are forced to duplicate code between the FO/HO matching because we *)(* have to work around several kludges in unify.ml: *)(* - w_unify drops into second-order unification when the pattern is an *)(* application whose head is a meta. *)(* - w_unify tries to unify types without subsumption when the pattern *)(* head is an evar or meta (e.g., it fails on ?1 = nat when ?1 : Type). *)(* - w_unify expands let-in (zeta conversion) eagerly, whereas we want to *)(* match a head let rigidly. *)letmatch_upats_FOupatsenvsigma0iseorig_c=letdont_impact_evars=dont_impact_evars_insigma0orig_cinletrecloopc=letf,a=splay_appisecinleti0=ref(-1)inletfpats=List.fold_right(filter_upat_FOenvisei0f(Array.lengtha))upats[]inwhile!i0>=0doleti=!i0ini0:=-1;letc'=mkSubAppfiainletone_match(u,np)=letopenEConstrinletskip=ifi<=nptheni<npelseifu.up_k==KpatFlexthenbegini0:=i-1;falseendelsebeginif!i0<nptheni0:=np;trueendinifskip||not(EConstr.Vars.closed0isec')then()elsetrylet()=matchu.up_kwith|KpatFlex->letkludgev=mkLambda(make_annotAnonymousERelevance.relevant,mkProp,v)inlet(metas,p_FO)=u.up_FOinunif_FOenvisemetas(kludgep_FO)(kludgec')|KpatLet->letkludgevla=letvl,a=safeDestAppisevlainletx,v,t,b=destLetInisevlinmkApp(mkLambda(x,t,b),Array.consva)inlet(metas,p_FO)=u.up_FOinunif_FOenvisemetas(kludgep_FO)(kludgec')|_->let(metas,p_FO)=u.up_FOinunif_FOenvisemetasp_FOc'inletise'=(* Unify again using HO to assign evars *)ifu.up_k=KpatConstthentryletise=unif_HOenviseu.up_ffinunif_HO_argsenviseu.up_a(i-Array.lengthu.up_a)awithewhenCErrors.noncriticale->raiseNoMatchelseletp=mkApp(u.up_f,u.up_a)intryunif_HOenvisepc'withewhenCErrors.noncriticale->raiseNoMatchinletlhs=mkSubAppfiainletpt'=unif_endenvsigma0ise'u.up_t(u.up_oklhs)inifoption_LegacyFoUnif()||Evar.Set.equal(Evd.evars_of_termise'(mkApp(u.up_f,u.up_a)))(Evd.evars_of_termise'lhs)thenraise(FoundUnif(ungen_upatlhspt'u))else(pp(lazy(str"not ground"++pr_econstr_patenvise'(mkApp(u.up_f,u.up_a))));raiseNoMatch)withFoundUnif(_,s,_,_)assig_uwhendont_impact_evarss->raisesig_u|Not_found->CErrors.anomaly(str"incomplete ise in match_upats_FO.")|ewhenCErrors.noncriticale->pp(lazy(str"FO fail: "++CErrors.print_no_reporte));()inList.iterone_matchfpatsdone;iter_constr_LRiseloopf;Array.iterloopaintrylooporig_cwithInvalid_argument_->CErrors.anomaly(str"IN FO.")letmatch_upats_HO~on_instanceupatsenvsigma0isec=letdont_impact_evars=dont_impact_evars_insigma0cinletit_did_match=reffalseinletfailed_because_of_TC=reffalseinletrecauxupatsenvsigma0isec=letf,a=splay_appisecinleti0=ref(-1)inletfpats=List.fold_right(filter_upatenvisei0f(Array.lengtha))upats[]inwhile!i0>=0doleti=!i0ini0:=-1;letone_match(u,np)=letskip=ifi<=nptheni<npelseifu.up_k==KpatFlexthenbegini0:=i-1;falseendelsebeginif!i0<nptheni0:=np;trueendinifskipthen()elsetryletise'=matchu.up_kwith|KpatFixed->ise|KpatConst->(* Ensure universe instances are unified *)unif_HOenviseu.up_ff|KpatEvar_->letopenEConstrinletpka=Evd.expand_existentialise@@destEvariseu.up_finletka=Evd.expand_existentialise@@destEvarisefinletfoldisepkk=unif_HOenvisepkkinList.fold_left2foldisepkaka|KpatLet->letopenEConstrinletx,v,t,b=destLetInisefinlet_,pv,_,pb=destLetIniseu.up_finletise'=unif_HOenvisepvvinunif_HO(EConstr.push_rel(Context.Rel.Declaration.LocalAssum(x,t))env)ise'pbb|KpatFlex|KpatProj_->letfa=mkSubAppf(i-Array.lengthu.up_a)ainletise=matchEConstr.kindisef,EConstr.kindiseu.up_fwith|Proj_,_|_,Proj_->(* with primitive projections we "lose" parameters so we unify
* the type of the arguments to retrieve that information *)lettuf=Retyping.get_type_of~lax:trueenviseu.up_finlettfa=Retyping.get_type_of~lax:trueenvisefainunif_HOenvisetuftfa|_->iseinpp(lazy(str"FLEX "++pr_econstr_envenviseu.up_f++str" = "++pr_econstr_envenvisefa));unif_HOenviseu.up_ffa|_->unif_HOenviseu.up_ffinletise''=unif_HO_argsenvise'u.up_a(i-Array.lengthu.up_a)ainletlhs=mkSubAppfiainletpt'=unif_endenvsigma0ise''u.up_t(u.up_oklhs)inon_instance(ungen_upatlhspt'u)withFoundUnif(_,s,_,_)assig_uwhendont_impact_evarss->raisesig_u|NoProgress->it_did_match:=true|Pretype_errors.PretypeError(_,_,Pretype_errors.UnsatisfiableConstraints_)->failed_because_of_TC:=true|ewhenCErrors.noncriticale->()inList.iterone_matchfpatsdone;iter_constr_LRise(auxupatsenvsigma0ise)f;Array.iter(auxupatsenvsigma0ise)ainauxupatsenvsigma0isec;if!it_did_matchthenraiseNoProgress;!failed_because_of_TCletfixed_upatevd=function|{up_k=KpatFlex|KpatEvar_|KpatProj_}->false|{up_t=t}->not(occur_existentialevdt)letdo_oncerf=match!rwithSome_->()|None->r:=Some(f())letassert_doner=match!rwithSomex->x|None->CErrors.anomaly(str"do_once never called.")typesubst=Environ.env->EConstr.t->EConstr.t->int->EConstr.ttype'afind_P=Environ.env->EConstr.t->int->k:subst->'atypeconclude=unit->EConstr.t*ssrdir*(bool*Evd.evar_map*UState.t*EConstr.t)letrecuniquize=function|[]->[]|(_,sigma,_,{up_f=f;up_a=a;up_t=t}asx)::xs->letnf_evarsigmac=EConstr.Unsafe.to_constr(Evarutil.nf_evarsigmac)inletequalsigma1sigma2c1c2=Constr.equal(nf_evarsigma1c1)(nf_evarsigma2c2)inletneq(_,sigma1,_,{up_f=f1;up_a=a1;up_t=t1})=not(equalsigmasigma1tt1&&equalsigmasigma1ff1&&CArray.for_all2(equalsigmasigma1)aa1)inx::uniquize(List.filterneqxs)typeocc_state={max_occ:int;nocc:int;occ_set:boolarray;(* immutable after creation *)use_occ:bool;skip_occ:bool;}letcreate_occ_stateocc=letuse_occ,occ_list=matchoccwith|Some(true,ol)->ol=[],ol|Some(false,ol)->ol<>[],ol|None->false,[]inletmax_occ=List.fold_rightmaxocc_list0inletocc_set=Array.makemax_occ(notuse_occ)inlet_=List.iter(funi->occ_set.(i-1)<-use_occ)occ_listinletskip_occ=ifmax_occ=0thenuse_occelsefalsein{max_occ;nocc=0;occ_set;skip_occ;use_occ}letsubst_occocc_ref=letocc=!occ_refinlet{nocc;max_occ;occ_set;use_occ}=occinletnocc=nocc+1inlet()=occ_ref:={!occ_refwithnocc}inlet()=ifInt.equalnoccmax_occthenocc_ref:={!occ_refwithskip_occ=use_occ}inifnocc<=max_occthenocc_set.(nocc-1)elsenotuse_occletmatch_constr_universesenvsigmaxy=matchEConstr.eq_constr_universesenvsigmaxywith|None->None|Somepbs->trySome(Evd.add_constraintssigmapbs)withUGraph.UniverseInconsistency_|Evd.UniversesDiffer|QGraph.EliminationError_->Noneletmatch_EQenvsigma(ise,u)=letopenEConstrinmatchu.up_kwith|KpatLet->letx,pv,t,pb=destLetInsigmau.up_finletenv'=EConstr.push_rel(Context.Rel.Declaration.LocalAssum(x,t))envinletmatch_letf=matchEConstr.kindisefwith|LetIn(_,v,_,b)->beginmatchunif_EQenvsigmapvvwith|Somesigma'->unif_EQenv'sigma'pbb|None->Noneend|_->Noneinmatch_let|KpatFixed->func->match_constr_universesenvsigmau.up_fc|KpatConst->func->match_constr_universesenvsigmau.up_fc|KpatLam->func->(matchEConstr.kindsigmacwith|Lambda_->unif_EQenvsigmau.up_fc|_->None)|_->unif_EQenvsigmau.up_fletp2tp=EConstr.mkApp(p.up_f,p.up_a)letsourceenviseupats_originupats=matchupats_origin,upatswith|None,[p]->(iffixed_upatisepthenstr"term "elsestr"partial term ")++pr_econstr_patenvise(p2tp)++spc()|Some(dir,rule),[p]->str"The "++pr_dir_sidedir++str" of "++pr_econstr_patenviserule++fnl()++ws4++pr_econstr_patenvise(p2tp)++fnl()|Some(dir,rule),_->str"The "++pr_dir_sidedir++str" of "++pr_econstr_patenviserule++spc()|_,[]|None,_::_::_->CErrors.anomaly(str"mk_tpattern_matcher with no upats_origin.")typessrmatching_failure=|SsrTCFail|SsrMatchFail|SsrProgressFail|SsrOccMissingofint*int*EConstr.tletpr_ssrmatching_failureenvsigmaupats_originupats=function|SsrTCFail->sourceenvsigmaupats_originupats++strbrk"matches but type classes inference fails"|SsrMatchFail->sourceenvsigmaupats_originupats++str"does not match any subterm of the goal"|SsrProgressFail->letdir=matchupats_originwithSome(d,_)->d|_->CErrors.anomaly(str"mk_tpattern_matcher with no upats_origin.")instr"all matches of "++sourceenvsigmaupats_originupats++str"are equal to the "++pr_dir_side(inv_dirdir)|SsrOccMissing(nocc,max_occ,p')->str"Only "++intnocc++str" < "++intmax_occ++str(String.pluralnocc" occurrence")++matchupats_originwith|None->str" of"++spc()++pr_econstr_patenvsigmap'|Some(dir,rule)->str" of the "++pr_dir_sidedir++fnl()++ws4++pr_econstr_patenvsigmap'++fnl()++str"of "++pr_econstr_patenvsigmaruleexceptionSsrMatchingFailureofEnviron.env*Evd.evar_map*(ssrdir*EConstr.t)option*tpatternlist*ssrmatching_failurelet_=CErrors.register_handlerbeginfunction|SsrMatchingFailure(env,sigma,upats_origin,upats,e)->Some(pr_ssrmatching_failureenvsigmaupats_originupatse)|_->Noneendletssrfailenvsigmaupats_originupatse=raise(SsrMatchingFailure(env,sigma,upats_origin,upats,e))exceptionNoMatchTCletsubst_tpatternenvsigmaiseucuocc_statechk=let{up_f=pf;up_a=pa}=uinletevd=ref(Evd.set_ustatesigmauc)inletmatch_EQf=match_EQenv!evd(ise,u)finletpn=Array.lengthpainletrecsubst_loop(env,hasacc)c'=if!occ_state.skip_occthenc'elseletf,a=splay_appsigmac'inlettest()=matchmatch_EQfwith|Somesigma->(matchunif_EQ_argsenvsigmapaawith|Somesigma->evd:=sigma;true|None->false)|None->falseinifArray.lengtha>=pn&&test()thenletopenEConstrinleta1,a2=Array.chop(Array.lengthpa)ainletfa1=mkApp(f,a1)inletf'=ifsubst_occocc_statethenkenvu.up_tfa1helsefa1inmkApp(f',Array.map_left(subst_loopacc)a2)elseletopenEConstrin(* TASSI: clear letin values to avoid unfolding *)letinc_hrd(env,h')=letctx_item=matchrdwith|Context.Rel.Declaration.LocalAssum_asx->x|Context.Rel.Declaration.LocalDef(x,_,y)->Context.Rel.Declaration.LocalAssum(x,y)inEConstr.push_relctx_itemenv,h'+1inletselfaccc=subst_loopacccinletf'=map_constr_with_binders_left_to_rightenvsigmainc_hselfaccfinmkApp(f',Array.map_left(subst_loopacc)a)inletc=subst_loop(env,h)cinEvd.ustate!evd,cletfind_all_instancessigma0{tpat_sigma=ise;tpat_pats=upats}:unitfind_P=letocc_state=ref(create_occ_stateNone)infunenvch~k->letinstances=ref[]inleton_instancex=instances:=!instances@[x]inlet()=matchmatch_upats_HO~on_instanceupatsenvsigma0isecwith|(_:bool)->()|exception(NoMatch|NoProgress)->()inletans=uniquize!instancesinletiter(expl,sigma,uc,u)=let_,_=subst_tpatternenvsigmaiseucuocc_statechkin()inList.iteriteransletfind_tpattern~disable_FO~raise_NoMatch~upat_that_matched~upats_origin~upatssigma0iseocc_state:EConstr.tfind_P=funenvch~k->letupat_that_matched_ref=upat_that_matchedinletupat_that_matched=match!upat_that_matched_refwith|None->leton_instancex=raise(FoundUnifx)inletans=trylet()=ifnotdisable_FOthenmatch_upats_FOupatsenvsigma0isecinifmatch_upats_HO~on_instanceupatsenvsigma0isecthenraiseNoMatchTCelseraiseNoMatchwith|FoundUnifsigma_u->sigma_u|NoMatch->ifraise_NoMatchthenraiseNoMatchelsessrfailenviseupats_originupatsSsrMatchFail|NoMatchTC->ifraise_NoMatchthenraiseNoMatchelsessrfailenviseupats_originupatsSsrTCFail|NoProgress->ifraise_NoMatchthenraiseNoMatchelsessrfailenviseupats_originupatsSsrProgressFailinenv,ans|Somer->rinletexpl,sigma,uc,u=sndupat_that_matchedin(* pp(lazy(str"sigma@tmatch=" ++ pr_evar_map None sigma)); *)if!occ_state.skip_occthen((*ignore(k env u.up_t 0);*)c)elseletuc,c=subst_tpatternenvsigmaiseucuocc_statechkin(* Fixup upat_that_matched to record universe unifications for followup EQ matches in later occurrences of a pattern *)let()=let(env,xs)=upat_that_matchedinupat_that_matched_ref:=Some(env,(expl,sigma,uc,u))incletconclude_tpattern~raise_NoMatch~upat_that_matched~upats_origin~upatsocc:conclude=fun()->let{max_occ;nocc}=!occinletenv,(c,sigma,uc,({up_f=pf;up_a=pa}asu))=match!upat_that_matchedwith|Some(env,x)->env,x|Nonewhenraise_NoMatch->raiseNoMatch|None->CErrors.anomaly(str"companion function never called.")inletp'=EConstr.mkApp(pf,pa)inifmax_occ<=noccthenp',u.up_dir,(c,sigma,uc,u.up_t)elsessrfailenvsigmaupats_originupats(SsrOccMissing(nocc,max_occ,p'))(* upats_origin makes a better error message only *)letmk_tpattern_matcher?(raise_NoMatch=false)?upats_originsigma0occ{tpat_sigma=ise;tpat_pats=upats}=letocc_state=ref(create_occ_stateocc)inletupat_that_matched=refNoneinletdisable_FO=occ=Some(true,[1])infind_tpattern~disable_FO~raise_NoMatch~upat_that_matched~upats_origin~upatssigma0iseocc_state,conclude_tpattern~raise_NoMatch~upat_that_matched~upats_origin~upatsocc_statetype('inpat,'term)ssrpattern=|Tof'term|In_Tof'term|X_In_Tof'inpat|In_X_In_Tof'inpat|E_In_X_In_Tof'term*'inpat|E_As_X_In_Tof'term*'inpatletpr_in_patternpr_identpr_term(x,t)=pr_identx++str" in "++pr_termtletpr_patternpr_identpr_term=function|Tt->pr_termt|In_Tt->str"in "++pr_termt|X_In_Tp->pr_in_patternpr_identpr_termp|In_X_In_Tp->str"in "++pr_in_patternpr_identpr_termp|E_In_X_In_T(e,p)->pr_terme++str" in "++pr_in_patternpr_identpr_termp|E_As_X_In_T(e,p)->pr_terme++str" as "++pr_in_patternpr_identpr_termpletpr_holepr_constre=pr_constr(EConstr.mkEvare)typein_pattern={in_hole:EConstr.existential;in_func:EConstr.t;in_patt:EConstr.t;(* in_patt := in_func{#1 := in_hole} *)}letpr_in_pattern_auxpr_constr{in_hole=x;in_patt=t}=pr_holepr_constrx++str" in "++pr_constrtletpr_pattern_auxpr_constr=function|Tt->pr_constrt|In_Tt->str"in "++pr_constrt|X_In_Tp->pr_in_pattern_auxpr_constrp|In_X_In_Tp->str"in "++pr_in_pattern_auxpr_constrp|E_In_X_In_T(e,p)->pr_constre++str" in "++pr_in_pattern_auxpr_constrp|E_As_X_In_T(e,p)->pr_constre++str" as "++pr_in_pattern_auxpr_constrptypepattern={pat_sigma:Evd.evar_map;pat_pat:(in_pattern,EConstr.t)ssrpattern;}letpp_patternenv{pat_sigma=sigma;pat_pat=p}=pr_pattern_aux(funt->pr_econstr_patenvsigmat)ptypecpattern={kind:ssrtermkind;pattern:Genintern.glob_constr_and_expr;interpretation:Tacinterp.interp_signoption}letpr_term{kind;pattern;_}=letenv=Global.env()inletsigma=Evd.from_envenvinpr_guarded(guard_termkind)(pr_glob_constr_and_exprenvsigma)patternletprl_term{kind;pattern;_}=letenv=Global.env()inletsigma=Evd.from_envenvinpr_guarded(guard_termkind)(prl_glob_constr_and_exprenvsigma)patternletpr_cpattern=pr_termletpr_pattern_w_ids=pr_patternpr_idprl_termletmk_termkcist={kind=k;pattern=(mkRHole,Somec);interpretation=ist}letmk_lterm=mk_termNoFlagletglob_ssrtermgs=function|{kind;pattern=(_,Somec);interpretation=None}->letx=Tacintern.intern_constrgscin{kind;pattern=(fstx,Somec);interpretation=None}|ct->ct(* ssrterm conbinators *)letcombineCGt1t2fg=letmk_isti1i2=matchi1,i2with|None,Somei->Somei|Somei,None->Somei|None,None->None|Somei,Somejwheni==j->Somei|_->CErrors.anomaly(Pp.str"combineCG: different ist")inmatcht1,t2with|{kind=x;pattern=(t1,None);interpretation=i1},{pattern=(t2,None);interpretation=i2}->{kind=x;pattern=(gt1t2,None);interpretation=mk_isti1i2}|{kind=x;pattern=(_,Somet1);interpretation=i1},{pattern=(_,Somet2);interpretation=i2}->{kind=x;pattern=(mkRHole,Some(ft1t2));interpretation=mk_isti1i2}|_,{pattern=(_,None);_}->CErrors.anomaly(str"have: mixed C-G constr.")|_->CErrors.anomaly(str"have: mixed G-C constr.")letloc_ofCG=function|{pattern=(s,None);_}->Glob_ops.loc_of_glob_constrs|{pattern=(_,Somes);_}->Constrexpr_ops.constr_locs(* This piece of code asserts the following notations are reserved *)(* Reserved Notation "( a 'in' b )" (at level 0). *)(* Reserved Notation "( a 'as' b )" (at level 0). *)(* Reserved Notation "( a 'in' b 'in' c )" (at level 0). *)(* Reserved Notation "( a 'as' b 'in' c )" (at level 0). *)letglob_cpatterngsp=pp(lazy(str"globbing pattern: "++pr_termp));letglobx=(glob_ssrtermgs(mk_ltermxNone)).patterninletencodeksl=letname=Name(Id.of_string("_ssrpat_"^s))in{kind=k;pattern=(mkRCastmkRHole(mkRLambdanamemkRHole(mkRAppmkRHolel)),None);interpretation=None}inletbind_int1t2=letmkCHole=mkCHole~loc:Noneinletn=Name(destCVart1)infst(glob(mkCCastmkCHole(mkCLambdanmkCHolet2)))inletcheck_vart2=ifnot(isCVart2)thenloc_error(constr_loct2)"Only identifiers are allowed here"inmatchpwith|{pattern=(_,None);_}asx->x|{kind=k;pattern=(v,Somet);_}asorig->ifk=Cpatternthenglob_ssrtermgs{kind=InParens;pattern=(v,Somet);interpretation=None}elsematcht.CAst.vwith|CNotation(_,(InConstrEntry,"( _ in _ )"),([t1;t2],[],[],[]))->(trymatchglobt1,globt2with|(r1,None),(r2,None)->encodek"In"[r1;r2]|(r1,Some_),(r2,Some_)whenisCVart1->encodek"In"[r1;r2;bind_int1t2]|(r1,Some_),(r2,Some_)->encodek"In"[r1;r2]|_->CErrors.anomaly(str"where are we?.")withewhenCErrors.noncriticale&&isCVart1->encodek"In"[bind_int1t2])|CNotation(_,(InConstrEntry,"( _ in _ in _ )"),([t1;t2;t3],[],[],[]))->check_vart2;encodek"In"[fst(globt1);bind_int2t3]|CNotation(_,(InConstrEntry,"( _ as _ )"),([t1;t2],[],[],[]))->encodek"As"[fst(globt1);fst(globt2)]|CNotation(_,(InConstrEntry,"( _ as _ in _ )"),([t1;t2;t3],[],[],[]))->check_vart2;encodek"As"[fst(globt1);bind_int2t3]|_->glob_ssrtermgsorigletglob_in_patterns(x,t)=(x,glob_ssrtermst)letglob_rpatternsp=matchpwith|Tt->T(glob_cpatternst)|In_Tt->In_T(glob_ssrtermst)|X_In_Tp->X_In_T(glob_in_patternsp)|In_X_In_Tp->In_X_In_T(glob_in_patternsp)|E_In_X_In_T(e,p)->E_In_X_In_T(glob_ssrtermse,glob_in_patternsp)|E_As_X_In_T(e,p)->E_As_X_In_T(glob_ssrtermse,glob_in_patternsp)letsubst_ssrterms{kind;pattern;interpretation}={kind;pattern=Tacsubst.subst_glob_constr_and_exprspattern;interpretation}letsubst_in_patterns(x,t)=(x,subst_ssrtermst)letsubst_rpatterns=function|Tt->T(subst_ssrtermst)|In_Tt->In_T(subst_ssrtermst)|X_In_Tp->X_In_T(subst_in_patternsp)|In_X_In_Tp->In_X_In_T(subst_in_patternsp)|E_In_X_In_T(e,p)->E_In_X_In_T(subst_ssrtermse,subst_in_patternsp)|E_As_X_In_T(e,p)->E_As_X_In_T(subst_ssrtermse,subst_in_patternsp)letinterp_ssrtermist{kind;pattern;_}={kind;pattern;interpretation=Someist}letinterp_inpatterns(x,t)=(interp_ssrtermsx,interp_ssrtermst)letinterp_rpatterns=function|Tt->T(interp_ssrtermst)|In_Tt->In_T(interp_ssrtermst)|X_In_Tp->X_In_T(interp_inpatternsp)|In_X_In_Tp->In_X_In_T(interp_inpatternsp)|E_In_X_In_T(e,p)->E_In_X_In_T(interp_ssrtermse,interp_inpatternsp)|E_As_X_In_T(e,p)->E_As_X_In_T(interp_ssrtermse,interp_inpatternsp)letinterp_rpattern0ist__t=interp_rpatternisttlettag_of_cpatternp=p.kindletloc_of_cpattern=loc_ofCGtypeocc=(bool*intlist)optiontyperpattern=(cpattern*cpattern,cpattern)ssrpatternletpr_rpattern=pr_patternpr_cpatternpr_cpatternletwit_rpatternty=add_genarg"rpatternty"(funenvsigma->pr_patternpr_cpatternpr_cpattern)letid_of_cpattern{pattern=(c1,c2);_}=letopenCAstinmatchDAst.getc1,c2with|_,Some{v=CRef(qid,_)}whenqualid_is_identqid->Some(qualid_basenameqid)|_,Some{v=CAppExpl((qid,_),[])}whenqualid_is_identqid->Some(qualid_basenameqid)|GRef(GlobRef.VarRefx,_),None->Somex|_->Noneletid_of_Ctermt=matchid_of_cpatterntwith|Somex->x|None->loc_error(loc_of_cpatternt)"Only identifiers are allowed here"letinterp_open_constristenvsigmagc=Tacinterp.interp_open_constristenvsigmagcletpf_intern_termenvsigma{pattern=c;interpretation=ist;_}=glob_constristenvsigmacletinterp_ssrtermistenvsigmat=interp_ssrtermisttletinterp_termenvsigma=function|{pattern=c;interpretation=Someist;_}->interp_open_constristenvsigmac|_->errorstrm(str"interpreting a term with no ist")letthinidsigmagoal=letids=Id.Set.singletonidinletevi=Evd.find_undefinedsigmagoalinletenv=Evd.evar_filtered_env(Global.env())eviinletcl=Evd.evar_concleviinletrelevance=Evd.evar_relevanceeviinletans=(* Why can this get called with an unknown id? *)ifnot@@Environ.mem_namedidenvthenSome(sigma,Environ.named_context_valenv,cl)elsetrySome(Evarutil.clear_hyps_in_evienvsigma(Environ.named_context_valenv)clids)withEvarutil.ClearDependencyError_->Noneinmatchanswith|None->sigma|Some(sigma,hyps,concl)->let(sigma,evk)=Evarutil.new_pure_evar~src:(Loc.tagEvar_kinds.GoalEvar)~typeclass_candidate:falsehypssigma~relevanceconclinletsigma=Evd.remove_future_goalsigmaevkinletsigma=Evd.transfer_namegoalevksigmainletproof=EConstr.mkEvar(evk,Evd.evar_identity_subst@@Evd.find_undefinedsigmaevk)inEvd.definegoalproofsigma(*
let pr_ist { lfun= lfun } =
prlist_with_sep spc
(fun (id, Geninterp.Val.Dyn(ty,_)) ->
pr_id id ++ str":" ++ Geninterp.Val.pr ty) (Id.Map.bindings lfun)
*)letdecode_pattern?wit_ssrpatternargenvsigma0red=pp(lazy(str"interpreting: "++pr_rpatternred));letxInTxy=X_In_T(x,y)andinXInTxy=In_X_In_T(x,y)inletinTx=In_TxandeInXInText=E_In_X_In_T(e,(x,t))inleteAsXInText=E_As_X_In_T(e,(x,t))inletmkG?(k=NoFlag)xist={kind=k;pattern=(x,None);interpretation=ist}inletdecode({interpretation=ist;_}ast)?reccallfg=trymatchDAst.get(pf_intern_termenvsigma0t)with|GCast(t,SomeDEFAULTcast,c)whenisGHolet&&isGLambdac->let(x,c)=destGLambdacinfx{kind=NoFlag;pattern=(c,None);interpretation=ist}|GVaridwhenOption.has_someist&&letist=Option.getistinId.Map.memidist.lfun&¬(Option.is_emptyreccall)&¬(Option.is_emptywit_ssrpatternarg)->letv=Id.Map.findid(Option.getist).lfuninOption.getreccall(Value.cast(topwit(Option.getwit_ssrpatternarg))v)|it->gtwithewhenCErrors.noncriticale->gtinletdecodeGisttfg=decode(mkGtist)fginletbad_encid_=CErrors.anomaly(str"bad encoding for pattern "++strid++str".")inletred=letrecdecode_red=function|T{kind=k;pattern=(t,None);interpretation=ist}->beginmatchDAst.gettwith|GCast(c,SomeDEFAULTcast,t)whenisGHolec&&let(id,t)=destGLambdatinletid=Id.to_stringidinletlen=String.lengthidin(len>8&&String.subid08="_ssrpat_")->let(id,t)=destGLambdatinletid=Id.to_stringidinletlen=String.lengthidin(matchString.subid8(len-8),DAst.gettwith|"In",GApp(_,[t])->decodeGisttxInT(funx->Tx)|"In",GApp(_,[e;t])->decodeGistt(eInXInT(mkGeist))(bad_encid)|"In",GApp(_,[e;t;e_in_t])->decodeGistt(eInXInT(mkGeist))(fun_->decodeGiste_in_txInT(fun_->assertfalse))|"As",GApp(_,[e;t])->decodeGistt(eAsXInT(mkGeist))(bad_encid)|_->bad_encid())|_->decode~reccall:decode_red(mkG~ktist)xInT(funx->Tx)end|Tt->decode~reccall:decode_redtxInT(funx->Tx)|In_Tt->decodetinXInTinT|X_In_T(e,t)->decodet(eInXInTe)(funx->xInT(id_of_Cterme)x)|In_X_In_T(e,t)->inXInT(id_of_Cterme)t|E_In_X_In_T(e,(x,rp))->eInXInTe(id_of_Ctermx)rp|E_As_X_In_T(e,(x,rp))->eAsXInTe(id_of_Ctermx)rpindecode_redredinpp(lazy(str"decoded as: "++pr_pattern_w_idsred));redletadd_pattern_typeenvsigma0red(ty,ist)=letist_ofx=x.interpretationinletmkG?(k=NoFlag)xist={kind=k;pattern=(x,None);interpretation=ist}inletty={kind=NoFlag;pattern=ty;interpretation=Someist}inletred=matchredwith|Tt->T(combineCGtty(mkCCast?loc:(loc_ofCGt))mkRCast)|X_In_T(x,t)->letgty=pf_intern_termenvsigma0tyinE_As_X_In_T(mkG(mkRCastmkRHolegty)(ist_ofty),(x,t))|E_In_X_In_T(e,(x,t))->letty=mkG(pf_intern_termenvsigma0ty)(ist_ofty)inE_In_X_In_T(combineCGety(mkCCast?loc:(loc_ofCGt))mkRCast,(x,t))|E_As_X_In_T(e,(x,t))->letty=mkG(pf_intern_termenvsigma0ty)(ist_ofty)inE_As_X_In_T(combineCGety(mkCCast?loc:(loc_ofCGt))mkRCast,(x,t))|red->redinpp(lazy(str"typed as: "++pr_pattern_w_idsred));redletcleanup_XinEenvsigma0(h_k,_)xrpsigma=letto_clean,update=(* handle rename if x is already used *)letctx=Environ.named_contextenvinletlen=Context.Named.lengthctxinletname=refNoneintryignore(Context.Named.lookupxctx);(name,funk->if!name=NonethenletEvarInfoevi=Evd.findsigmakinletnctx=Evd.evar_contexteviinletnlen=Context.Named.lengthnctxinifnlen>lenthenbeginname:=Some(Context.Named.Declaration.get_id(List.nthnctx(nlen-len-1)))end)withNot_found->ref(Somex),fun_->()inletnew_evars=letrecauxacct=matchEConstr.kindsigmatwith|Evar(k,_)->ifk=h_k||List.memkacc||Evd.memsigma0kthenaccelse(updatek;k::acc)|_->EConstr.foldsigmaauxacctinaux[]rpinletsigma=List.fold_left(funsigmae->ifEvd.is_definedsigmaethensigmaelse(* clear may be recursive *)ifOption.is_empty!to_cleanthensigmaelseletname=Option.get!to_cleaninpp(lazy(pr_idname));thinnamesigmae)sigmanew_evarsinsigmaletmk_in_patternenvsigma0(x,rp)=letsigma=sigma0inletist=matchrp.interpretationwith|None->CErrors.user_err(Pp.str"interpreting a term with no ist")|Someist->istinletsrc=Loc.tag(BinderType(Namex))inletsigma,(ty,s)=Evarutil.new_type_evarenvsigmaEvd.univ_flexible_alginletna=Context.make_annot(Namex)(Retyping.relevance_of_sorts)inletnenv=EConstr.push_rel(Context.Rel.Declaration.LocalAssum(na,ty))envinletsigma,rp0=Tacinterp.interp_open_constristnenvsigmarp.patterninletsigma,h=Evarutil.new_evarenvsigma~srctyinleth=EConstr.destEvarsigmahinletsigma=cleanup_XinEenvsigma0hxrp0sigmainletrp=EConstr.Vars.subst1(EConstr.mkEvarh)(Evarutil.nf_evarsigmarp0)inletin_pat={in_hole=h;in_patt=rp;in_func=rp0}insigma,in_patletinterp_pattern?wit_ssrpatternargenvsigma0redredty=pp(lazy(str"interpreting: "++pr_rpatternred));letred=decode_pattern?wit_ssrpatternargenvsigma0redinletred=matchredtywith|None->red|Somety->add_pattern_typeenvsigma0redtyinmatchredwith|Tt->letsigma,t=interp_termenvsigma0tin{pat_sigma=sigma;pat_pat=Tt}|In_Tt->letsigma,t=interp_termenvsigma0tin{pat_sigma=sigma;pat_pat=In_Tt}|X_In_Tp|In_X_In_Tp|E_In_X_In_T(_,p)|E_As_X_In_T(_,p)->letsigma,in_pat=mk_in_patternenvsigma0pinletsigma,p=matchredwith|X_In_T_->sigma,X_In_Tin_pat|In_X_In_T_->sigma,In_X_In_Tin_pat|E_In_X_In_T(e,_)->letsigma,e=interp_termenvsigmaeinsigma,E_In_X_In_T(e,in_pat)|E_As_X_In_T(e,_)->letsigma,e=interp_termenvsigmaeinsigma,E_As_X_In_T(e,in_pat)|T_|In_T_->assertfalsein{pat_sigma=sigma;pat_pat=p}letinterp_cpatternenvsigmaredredty=interp_patternenvsigma(Tred)redty;;letinterp_rpattern~wit_ssrpatternargenvsigmared=interp_pattern~wit_ssrpatternargenvsigmaredNone;;letid_of_patternsigmap=matchp.pat_patwith|Tt->(matchEConstr.kindsigmatwithVarid->Someid|_->None)|_->None(* The full occurrence set *)letnoindex=Some(false,[])(* calls do_subst on every sub-term identified by (pattern,occ) *)leteval_pattern?raise_NoMatchenv0sigma0concl0patternocc(do_subst:subst)=letrigidev=Evd.memsigma0evinletfssigmax=Reductionops.nf_evarsigmaxinletpop_evarsigma{in_hole=(e,args);in_patt=p;in_func=fp}=letEvarInfoe_def=Evd.findsigmaeinlete_body=matchEvd.evar_bodye_defwithEvar_definedc->c|_->errorstrm(str"Matching the pattern "++pr_econstr_envenv0sigma0p++str" did not instantiate ?"++int(Evar.repre)++spc()++str"Does the variable bound by the \"in\" construct occur "++str"in the pattern?")in(* This code is very suspect because the returned value is the same as p up to
evar expansion *)letfp=Reductionops.nf_evarsigmafpinletfp=EConstr.Vars.subst1(EConstr.mkEvar(e,args))fpinfp,e_bodyinletmk_upat_for?hack~rigid(sigma,t)=mk_tpattern?hack~rigidenv0tL2R(fssigmat)(empty_tpatternssigma)inmatchpatternwith|None->do_substenv0concl0concl01,UState.empty|Some{pat_sigma=sigma;pat_pat=(Trp|In_Trp)}->letrp=fssigmarpinletise=create_evar_defssigmainletocc=matchpatternwithSome{pat_pat=T_}->occ|_->noindexinletrp=mk_upat_for~rigid(ise,rp)inletfind_T,end_T=mk_tpattern_matcher?raise_NoMatchsigma0occrpinletconcl=find_Tenv0concl01~k:do_substinlet_,_,(_,_,us,_)=end_T()inconcl,us|Some{pat_sigma=sigma;pat_pat=(X_In_Tp|In_X_In_Tp)}->let{in_hole=hole;in_patt=p}asp0=pinletp=fssigmapinletocc=matchpatternwithSome{pat_pat=X_In_T_}->occ|_->noindexinlethole=EConstr.mkEvarholeinletrp=mk_upat_for~hack:true~rigid(sigma,p)inletfind_T,end_T=mk_tpattern_matchersigma0noindexrpin(* we start from sigma, so hole is considered a rigid head *)letholep=mk_upat_for~rigid:(funev->Evd.memsigmaev)(sigma,hole)inletfind_X,end_X=mk_tpattern_matcher?raise_NoMatchsigmaoccholepinletconcl=find_Tenv0concl01~k:(funenvc_h->letp_sigma=unify_HOenv(create_evar_defssigma)cpinletp,e_body=pop_evarp_sigmap0infsp_sigma(find_Xenvph~k:(funenv_->do_substenve_body)))inlet_=end_X()inlet_,_,(_,_,us,_)=end_T()inconcl,us|Some{pat_sigma=sigma;pat_pat=E_In_X_In_T(e,p)}->let{in_hole=hole;in_patt=p}asp0=pinletp,e=fssigmap,fssigmaeinlethole=EConstr.mkEvarholeinletrp=mk_upat_for~hack:true~rigid(sigma,p)inletfind_T,end_T=mk_tpattern_matchersigma0noindexrpinletholep=mk_upat_for~rigid:(funev->Evd.memsigmaev)(sigma,hole)inletfind_X,end_X=mk_tpattern_matchersigmanoindexholepinletre=mk_upat_for~rigid(sigma,e)inletfind_E,end_E=mk_tpattern_matcher?raise_NoMatchsigma0occreinletconcl=find_Tenv0concl01~k:(funenvc_h->letp_sigma=unify_HOenv(create_evar_defssigma)cpinletp,e_body=pop_evarp_sigmap0infsp_sigma(find_Xenvph~k:(funenvc_h->find_Eenve_bodyh~k:do_subst)))inlet_,_,(_,_,us,_)=end_E()inlet_=end_X()inlet_=end_T()inconcl,us|Some{pat_sigma=sigma;pat_pat=E_As_X_In_T(e,p)}->let{in_hole=hole;in_patt=p}asp0=pinletp,e=fssigmap,fssigmaeinlethole=EConstr.mkEvarholeinletrp=lete_sigma=unify_HOenv0sigmaholeeine_sigma,fse_sigmapinletrp=mk_upat_for~hack:true~rigidrpinletfind_TE,end_TE=mk_tpattern_matchersigma0noindexrpinletholep=mk_upat_for~rigid:(funev->Evd.memsigmaev)(sigma,hole)inletfind_X,end_X=mk_tpattern_matchersigmaoccholepinletconcl=find_TEenv0concl01~k:(funenvc_h->letp_sigma=unify_HOenv(create_evar_defssigma)cpinletp,e_body=pop_evarp_sigmap0infsp_sigma(find_Xenvph~k:(funenvc_h->lete_sigma=unify_HOenvsigmae_bodyeinlete_body=fse_sigmaeindo_substenve_bodye_bodyh)))inlet_=end_X()inlet_,_,(_,_,us,_)=end_TE()inconcl,usletredex_of_pattern{pat_sigma=sigma;pat_pat=p}=matchpwith|In_T_|In_X_In_T_->None|X_In_T{in_hole=e}->Some(sigma,EConstr.mkEvare)|Te|E_As_X_In_T(e,_)|E_In_X_In_T(e,_)->Some(sigma,e)letredex_of_pattern_nfenvp=letsigma,e=matchredex_of_patternpwith|None->CErrors.anomaly(str"pattern without redex.")|Some(sigma,e)->sigma,einEvarutil.nf_evarsigmae,Evd.ustatesigmaletfill_occ_pattern?raise_NoMatchenvsigmaclpatocch=letdo_make_rel,occ=ifocc=Some(true,[])thenfalse,Some(false,[1])elsetrue,occinletr=refNoneinletfind_Renvc_h'=let()=do_oncer(fun()->c)inifdo_make_relthenEConstr.mkRel(h'+h-1)elsecinletcl,us=eval_pattern?raise_NoMatchenvsigmacl(Somepat)occfind_Rinlete=match!rwithNone->fst(redex_of_pattern_nfenvpat)|Somex->xin(e,us),clletfill_rel_occ_patternenvsigmaclpatocc=let(e,us),cl=tryfill_occ_pattern~raise_NoMatch:trueenvsigmaclpatocc1withNoMatch->redex_of_pattern_nfenvpat,clinletsigma=Evd.merge_ustatesigmausinsigma,e,cl(* clenup interface for external use *)letmk_tpattern?p_origin?ok~rigidenvsigma_tdirc=mk_tpattern?p_origin?ok~rigidenvsigma_tdircleteval_pattern?raise_NoMatchenv0sigma0concl0patternoccdo_subst=fst(eval_pattern?raise_NoMatchenv0sigma0concl0patternoccdo_subst)letpf_fill_occenvconcloccsigma0p(sigma,t)h=letrigidev=Evd.memsigma0evinletu=mk_tpattern~rigidenvtL2Rp(empty_tpatterns(create_evar_defssigma))inletfind_U,end_U=mk_tpattern_matcher~raise_NoMatch:truesigma0occuinletconcl=find_Uenvconclh~k:(fun___n->EConstr.mkReln)inletrdx,_,(c,sigma,uc,p)=end_U()inc,sigma,uc,p,concl,rdxletfill_occ_termenvsigma0clocc(sigma,t)=tryletchanged,sigma',uc,t',cl,_=pf_fill_occenvcloccsigma0t(sigma,t)1inifchangedthenCErrors.user_errPp.(str"matching impacts evars")elsecl,Evd.set_ustatesigma'uc,t'withNoMatch->tryletchanged,sigma',uc,t'=unif_endenvsigma0(create_evar_defssigma)t(fun_->true)inifchangedthenraiseNoMatchelsecl,Evd.set_ustatesigma'uc,t'withewhenCErrors.noncriticale->errorstrm(str"partial term "++pr_econstr_patenvsigmat++str" does not match any subterm of the goal")letcpattern_of_idid={kind=NoFlag;pattern=DAst.make@@GRef(GlobRef.VarRefid,None),None;interpretation=SomeTacinterp.({lfun=Id.Map.empty;poly=PolyFlags.default;extra=Tacinterp.TacStore.empty})}letis_wildcard({pattern=(l,r);_}:cpattern):bool=matchDAst.getl,rwith|_,Some{CAst.v=CHole_}|GHole_,None->true|_->false(* "ssrpattern" *)(** All the pattern types reuse the same dynamic toplevel tag *)letwit_ssrpatternarg=wit_rpatterntyletinterp_rpattern=interp_rpattern~wit_ssrpatternargletssrpatterntacarg=letopenProofview.NotationsinProofview.Goal.enterbeginfungl->letsigma0=Proofview.Goal.sigmaglinletconcl0=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinletpat=interp_rpatternenvsigma0arginlet(t,uc),concl_x=fill_occ_patternenvsigma0concl0patnoindex1inletsigma=Evd.set_ustatesigma0ucinletsigma,tty=Typing.type_ofenvsigmatinletconcl=EConstr.mkLetIn(make_annot(Name(Id.of_string"selected"))EConstr.ERelevance.relevant,t,tty,concl_x)inProofview.Unsafe.tclEVARSsigma<*>convert_concl~cast:false~check:trueconclDEFAULTcastend(* Register "ssrpattern" tactic *)let()=letmltac_ist=letarg=letv=Id.Map.find(Names.Id.of_string"pattern")ist.lfuninValue.cast(topwitwit_ssrpatternarg)vinssrpatterntacarginletname={mltac_plugin="rocq-runtime.plugins.ssrmatching";mltac_tactic="ssrpattern";}inlet()=Tacenv.register_ml_tacticname[|mltac|]inlettac=CAst.make(TacFun([Name(Id.of_string"pattern")],CAst.make(TacML({mltac_name=name;mltac_index=0},[]))))inletobj()=Tacenv.register_ltactruefalse(Id.of_string"ssrpattern")tacinMltop.(declare_cache_obj_full(interp_only_objobj)"rocq-runtime.plugins.ssrmatching")letssrinstancesofarg=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletconcl=Proofview.Goal.conclglinletconcl=Reductionops.nf_evarsigmaconclinlet{pat_sigma=sigma0;pat_pat=cpat}=interp_cpatternenvsigmaargNoneinletpat=matchcpatwithTx->x|_->errorstrm(str"Not supported")inletrigidev=Evd.memsigmaevinlettpat=mk_tpattern~rigidenvpatL2Rpat(empty_tpatternssigma0)inletfind=find_all_instancessigmatpatinletprintenvpc_=ppnl(hov1(str"instance:"++spc()++pr_econstr_envenv(Proofview.Goal.sigmagl)p++spc()++str"matches:"++spc()++pr_econstr_envenv(Proofview.Goal.sigmagl)c));cinlet()=ppnl(str"BEGIN INSTANCES")inlet()=findenvconcl1~k:printinlet()=ppnl(str"END INSTANCES")inTacticals.tclIDTACendmoduleInternal=structletwit_rpatternty=wit_rpatterntyletglob_rpattern=glob_rpatternletsubst_rpattern=subst_rpatternletinterp_rpattern=interp_rpattern0letpr_rpattern=pr_rpatternletmk_rpatternx=xletmk_lterm=mk_ltermletmk_term=mk_termletglob_cpattern=glob_cpatternletsubst_ssrterm=subst_ssrtermletinterp_ssrterm=interp_ssrtermletpr_ssrterm=pr_termend(* vim: set filetype=ocaml foldmethod=marker: *)