12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880(************************************************************************)(* * 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) *)(************************************************************************)openPpopenUtilopenCErrorsopenNamesopenConstropenContextopenEvdopenEConstropenVarsopenEnvironopenMod_substopenGlobnamesopenLibobjectopenNamegenopenLibnamesopenTermopsopenInductiveopsopenTypeclassesopenPatternopenPatternopsopenTacredopenPrintermoduleNamedDecl=Context.Named.Declaration(****************************************)(* General functions *)(****************************************)typedebug=Debug|Info|OffexceptionBoundletrechead_boundsigmat=matchEConstr.kindsigmatwith|Prod(_,_,b)->head_boundsigmab|LetIn(_,_,_,b)->head_boundsigmab|App(c,_)->head_boundsigmac|Case(_,_,_,_,_,c,_)->head_boundsigmac|Ind(ind,_)->GlobRef.IndRefind|Const(c,_)->GlobRef.ConstRefc|Construct(c,_)->GlobRef.ConstructRefc|Varid->GlobRef.VarRefid|Proj(p,_,_)->GlobRef.ConstRef(Projection.constantp)|Cast(c,_,_)->head_boundsigmac|Evar_|Rel_|Meta_|Sort_|Fix_|Lambda_|CoFix_|Int_|Float_|String_|Array_->raiseBoundlethead_constrsigmac=tryhead_boundsigmacwithBound->user_err(Pp.str"Head identifier must be a constant, section variable, \
(co)inductive type, (co)inductive type constructor, or projection.")letdecompose_app_boundsigmat=lett=strip_outer_castsigmatinlet_,ccl=decompose_prod_declssigmatinlethd,args=decompose_appsigmacclinletopenGlobRefinmatchEConstr.kindsigmahdwith|Const(c,u)->ConstRefc,args|Ind(i,u)->IndRefi,args|Construct(c,u)->ConstructRefc,args|Varid->VarRefid,args|Proj(p,_,c)->ConstRef(Projection.constantp),Array.conscargs|_->raiseBound(** Compute the set of section variables that remain in the named context.
Starts from the top to the bottom of the context, stops at the first
different declaration between the named hyps and the section context. *)letsecvars_of_hypshyps=letsecctx=Global.named_context()inletopenContext.Named.Declarationinletpred,all=List.fold_left(fun(pred,all)decl->trylet_=Context.Named.lookup(get_iddecl)hypsin(* Approximation, it might be an hypothesis reintroduced with same name and unconvertible types,
we must allow it currently, as comparing the declarations for syntactic equality is too
strong a check (e.g. an unfold in a section variable would make it unusable). *)(Id.Pred.add(get_iddecl)pred,all)withNot_found->(pred,false))(Id.Pred.empty,true)secctxinifallthenId.Pred.full(* If the whole section context is available *)elsepredletempty_hint_info={hint_priority=None;hint_pattern=None}(************************************************************************)(* The Type of Constructions Autotactic Hints *)(************************************************************************)type'ahint_ast=|Res_pfof'a(* Hint Apply *)|ERes_pfof'a(* Hint EApply *)|Give_exactof'a|Res_pf_THEN_trivial_failof'a(* Hint Immediate *)|Unfold_nthofEvaluable.t(* Hint Unfold *)|ExternofPattern.constr_patternoption*Genarg.glob_generic_argument(* Hint Extern *)type'ahints_path_atom_gen=|PathHintsof'alist(* For forward hints, their names is the list of projections *)|PathAnytypehints_path_atom=GlobRef.thints_path_atom_gentype'ahints_path_gen=|PathAtomof'ahints_path_atom_gen|PathStarof'ahints_path_gen|PathSeqof'ahints_path_gen*'ahints_path_gen|PathOrof'ahints_path_gen*'ahints_path_gen|PathEmpty|PathEpsilontypepre_hints_path=Libnames.qualidhints_path_gentypehints_path=GlobRef.thints_path_gentypehint_term=|IsGlobRefofGlobRef.t|IsConstrofconstr*UnivGen.sort_context_setoption(* None if monomorphic *)type'awith_uid={obj:'a;uid:KerName.t;}typeraw_hint={rhint_term:constr;rhint_type:types;rhint_uctx:UnivGen.sort_context_setoption;rhint_arty:int;(* Number of goals generated by the intended tactic *)}typehint={hint_term:constr;hint_type:types;hint_uctx:UnivGen.sort_context_setoption;(* None if monomorphic *)hint_clnv:Clenv.clausenv;hint_arty:int;(* Number of goals generated by the intended tactic *)}typehint_pattern=|DefaultPattern|ConstrPatternofconstr_pattern|SyntacticPatternofconstr_patterntype'awith_metadata={pri:int(** A number lower is higher priority *);pat:hint_patternoption(** A pattern for the concl of the Goal *);name:GlobRef.toption(** A potential name to refer to the hint *);db:stringoption(** The database from which the hint comes *);secvars:Id.Pred.t(** The set of section variables the hint depends on *);code:'a(** the tactic to apply when the concl matches pat *)}typefull_hint=hinthint_astwith_uidwith_metadatatypehint_entry=GlobRef.toption*raw_hinthint_astwith_uidwith_metadatatypehint_mode=|ModeInput(* No evars *)|ModeNoHeadEvar(* No evar at the head *)|ModeOutput(* Anything *)type'ahints_transparency_target=|HintsVariables|HintsConstants|HintsProjections|HintsReferencesof'alisttypeimport_level=HintLax|HintWarn|HintStrictlethint_as_termh=(h.hint_uctx,h.hint_term)letwarn_hint_to_string=function|HintLax->"Lax"|HintWarn->"Warn"|HintStrict->"Strict"letstring_to_warn_hint=function|"Lax"->HintLax|"Warn"->HintWarn|"Strict"->HintStrict|_->user_errPp.(str"Only the following values are accepted: Lax, Warn, Strict.")let{Goptions.get=warn_hint}=Goptions.declare_interpreted_string_option_and_ref~key:["Loose";"Hint";"Behavior"]~value:HintLaxstring_to_warn_hintwarn_hint_to_string()letfresh_key=letid=Summary.ref~name:"HINT-COUNTER"0infun()->letcur=incrid;!idinletlbl=Id.of_string("_"^string_of_intcur)inletkn=Lib.make_knlblinlet(mp,_)=KerName.reprknin(* We embed the full path of the kernel name in the label so that
the identifier should be unique. This ensures that including
two modules together won't confuse the corresponding labels. *)letlbl=Id.of_string_soft(Printf.sprintf"%s#%i"(ModPath.to_stringmp)cur)inKerName.makemp(Label.of_idlbl)letpri_order_int(id1,{pri=pri1})(id2,{pri=pri2})=letd=pri1-pri2inifInt.equald0thenid2-id1elsedletpri_ordert1t2=pri_order_intt1t2<=0letget_default_pattern(h:hinthint_ast)=matchhwith|Give_exacth->h.hint_type|Res_pfh|ERes_pfh|Res_pf_THEN_trivial_failh->Clenv.clenv_typeh.hint_clnv|Unfold_nth_|Extern_->(* These hints cannot contain DefaultPattern *)assertfalse(* Nov 98 -- Papageno *)(* Les Hints sont ré-organisés en plusieurs databases.
La table impérative "searchtable", de type "hint_db_table",
associe une database (hint_db) à chaque nom.
Une hint_db est une table d'association fonctionelle constr -> search_entry
Le constr correspond à la constante de tête de la conclusion.
Une search_entry est un triplet comprenant :
- la liste des tactiques qui n'ont pas de pattern associé
- la liste des tactiques qui ont un pattern
- un discrimination net borné (Btermdn.t) constitué de tous les
patterns de la seconde liste de tactiques *)typestored_data=int*full_hint(* First component is the index of insertion in the table, to keep most recent first semantics. *)moduleBounded_net:sigtypetvalempty:TransparentState.toption->tvalbuild:TransparentState.toption->stored_datalist->tvaladd:t->hint_pattern->stored_data->tvallookup:Environ.env->Evd.evar_map->t->EConstr.constr->stored_datalistend=structmoduleData=structtypet=stored_dataletcompare=pri_order_intendmoduleBnet=Btermdn.Make(Data)typediff=hint_pattern*stored_datatypedata=|Bnetof(TransparentState.toption*Bnet.t)|Diffofdiff*dataref|BuildofTransparentState.toption*stored_datalisttypet=datarefletemptyst=ref(Bnet(st,Bnet.empty))letaddnetpv=ref(Diff((p,v),net))letbuildstdata=ref(Build(st,data))letadd0envsigmastpvdn=letp=matchpwith|ConstrPatternp->Bnet.patternenvstp|SyntacticPatternp->Bnet.pattern_syntacticenvp|DefaultPattern->letc=get_default_pattern(sndv).code.objinBnet.constr_patternenvsigmastcinBnet.adddnpvletrecforceenvsigmanet=match!netwith|Bnetdn->dn|Diff((p,v),rem)->letst,dn=forceenvsigmareminletdn=add0envsigmastpvdninlet()=net:=(Bnet(st,dn))inst,dn|Build(st,data)->letfolddnv=add0envsigmast(Option.get(sndv).pat)vdninletans=List.fold_leftfoldBnet.emptydatainlet()=net:=Bnet(st,ans)inst,ansletlookupenvsigmanetp=letst,dn=forceenvsigmanetinBnet.lookupenvsigmastdnpendmoduleStoredData:sigtypetvalempty:tvalmem:KerName.t->t->boolvaladd:stored_data->t->tvalremove:GlobRef.Set.t->t->tvalelements:t->stored_datalistend=structtypet={data:stored_datalist;set:KNset.t;}letempty={data=[];set=KNset.empty}letmemknsd=KNset.memknsd.setletaddtsd={data=List.insertpri_ordertsd.data;set=KNset.add(sndt).code.uidsd.set;}letremovegrssd=letfold(accu,ans)((_,h)asv)=letkeep=matchh.namewith|Somegr->not(GlobRef.Set.memgrgrs)|None->trueinifkeepthen(accu,v::ans)else(KNset.removeh.code.uidaccu,ans)inletset,data=List.fold_leftfold(sd.set,[])sd.datainifset==sd.setthensdelse{data=List.revdata;set}letelementsv=v.dataendtypesearch_entry={sentry_nopat:StoredData.t;sentry_pat:StoredData.t;sentry_bnet:Bounded_net.t;sentry_mode:hint_modearraylist;}letempty_sest={sentry_nopat=StoredData.empty;sentry_pat=StoredData.empty;sentry_bnet=Bounded_net.emptyst;sentry_mode=[];}letadd_tacpattse=matchpatwith|None->letuid=(sndt).code.uidinifStoredData.memuidse.sentry_nopatthenseelse{sewithsentry_nopat=StoredData.addtse.sentry_nopat}|Somepat->letuid=(sndt).code.uidinifStoredData.memuidse.sentry_patthenseelse{sewithsentry_pat=StoredData.addtse.sentry_pat;sentry_bnet=Bounded_net.addse.sentry_bnetpatt;}letrebuild_dnstse=letdn'=Bounded_net.buildst(StoredData.elementsse.sentry_pat)in{sewithsentry_bnet=dn'}letlookup_tacsenvsigmaconclse=letl'=Bounded_net.lookupenvsigmase.sentry_bnetconclinletsl'=List.stable_sortpri_order_intl'inList.mergepri_order_int(StoredData.elementsse.sentry_nopat)sl'letmerge_context_set_optsigmactx=matchctxwith|None->sigma|Somectx->Evd.merge_sort_context_setEvd.univ_flexiblesigmactxletinstantiate_hintenvsigmap=letmk_clenv{rhint_term=c;rhint_type=cty;rhint_uctx=ctx;rhint_arty=ar}=letsigma=merge_context_set_optsigmactxinletcl=Clenv.mk_clenv_fromenvsigma(c,cty)inletcl=Clenv.clenv_strip_proj_paramsclin{hint_term=c;hint_type=cty;hint_uctx=ctx;hint_clnv=cl;hint_arty=ar}inletcode=matchp.code.objwith|Res_pfc->Res_pf(mk_clenvc)|ERes_pfc->ERes_pf(mk_clenvc)|Res_pf_THEN_trivial_failc->Res_pf_THEN_trivial_fail(mk_clenvc)|Give_exactc->Give_exact(mk_clenvc)|(Unfold_nth_|Extern_)ash->hin{pwithcode={p.codewithobj=code}}lethint_mode_eqm1m2=matchm1,m2with|ModeInput,ModeInput->true|ModeNoHeadEvar,ModeNoHeadEvar->true|ModeOutput,ModeOutput->true|(ModeInput|ModeNoHeadEvar|ModeOutput),_->falselethints_path_atom_eqh1h2=matchh1,h2with|PathHintsl1,PathHintsl2->List.equalGlobRef.CanOrd.equall1l2|PathAny,PathAny->true|_->falseletrechints_path_eqh1h2=matchh1,h2with|PathAtomh1,PathAtomh2->hints_path_atom_eqh1h2|PathStarh1,PathStarh2->hints_path_eqh1h2|PathSeq(l1,r1),PathSeq(l2,r2)->hints_path_eql1l2&&hints_path_eqr1r2|PathOr(l1,r1),PathOr(l2,r2)->hints_path_eql1l2&&hints_path_eqr1r2|PathEmpty,PathEmpty->true|PathEpsilon,PathEpsilon->true|_->falseletpath_matcheshphints=letrecauxhphintsk=matchhp,hintswith|PathAtom_,[]->false|PathAtomPathAny,(_::hints')->khints'|PathAtomp,(h::hints')->ifhints_path_atom_eqphthenkhints'elsefalse|PathStarhp',hints->khints||auxhp'hints(funhints'->auxhphints'k)|PathSeq(hp,hp'),hints->auxhphints(funhints'->auxhp'hints'k)|PathOr(hp,hp'),hints->auxhphintsk||auxhp'hintsk|PathEmpty,_->false|PathEpsilon,hints->khintsinauxhphints(funhints'->true)letrecmatches_epsilon=function|PathAtom_->false|PathStar_->true|PathSeq(p,p')->matches_epsilonp&&matches_epsilonp'|PathOr(p,p')->matches_epsilonp||matches_epsilonp'|PathEmpty->false|PathEpsilon->trueletpath_matches_epsilon=matches_epsilonletrecis_empty=function|PathAtom_->false|PathStar_->false|PathSeq(p,p')->is_emptyp||is_emptyp'|PathOr(p,p')->matches_epsilonp&&matches_epsilonp'|PathEmpty->true|PathEpsilon->falseletpath_seqpp'=matchp,p'with|PathEpsilon,p'->p'|p,PathEpsilon->p|p,p'->PathSeq(p,p')letrecpath_derivatehphint=letrecderivate_atomshintshints'=matchhints,hints'with|gr::grs,gr'::grs'whenGlobRef.CanOrd.equalgrgr'->derivate_atomsgrsgrs'|[],[]->PathEpsilon|[],hints->PathEmpty|grs,[]->PathAtom(PathHintsgrs)|_,_->PathEmptyinmatchhpwith|PathAtomPathAny->PathEpsilon|PathAtom(PathHintsgrs)->(matchgrs,hintwith|h::_,PathAny->PathEmpty|hints,PathHintshints'->derivate_atomshintshints'|_,_->assertfalse)|PathStarp->ifpath_matchesp[hint]thenhpelsePathEpsilon|PathSeq(hp,hp')->lethpder=path_derivatehphintinifmatches_epsilonhpthenPathOr(path_seqhpderhp',path_derivatehp'hint)elseifis_emptyhpderthenPathEmptyelsepath_seqhpderhp'|PathOr(hp,hp')->PathOr(path_derivatehphint,path_derivatehp'hint)|PathEmpty->PathEmpty|PathEpsilon->PathEmptyletrecnormalize_pathh=matchhwith|PathStarPathEpsilon->PathEpsilon|PathOr(p,q)->(matchnormalize_pathpwith|PathEmpty->normalize_pathq|p'->matchnormalize_pathqwith|PathEmpty->p'|q'->ifhints_path_eqp'q'thenp'elsePathOr(p',q'))|PathSeq(p,q)->(matchnormalize_pathpwith|PathEmpty->PathEmpty|PathEpsilon->normalize_pathq|p'->matchnormalize_pathqwith|PathEmpty->PathEmpty|PathEpsilon->p'|q'->PathSeq(p',q'))|_->hletpath_derivatehphint=lethint=matchhintwith|None->PathAny|Somegr->PathHints[gr]innormalize_path(path_derivatehphint)letpp_hints_path_atomprga=matchawith|PathAny->str"_"|PathHintsgrs->pr_sequenceprggrsletpp_hints_path_genprg=letrecaux=function|PathAtompa->pp_hints_path_atomprgpa|PathStar(PathAtomPathAny)->str"_*"|PathStarp->str"("++auxp++str")*"|PathSeq(p,p')->auxp++spc()++auxp'|PathOr(p,p')->str"("++auxp++spc()++str"|"++cut()++spc()++auxp'++str")"|PathEmpty->str"emp"|PathEpsilon->str"eps"inauxletpp_hints_path=pp_hints_path_genpr_globalletglob_hints_path_atomp=matchpwith|PathHintsg->PathHints(List.mapNametab.globalg)|PathAny->PathAnyletglob_hints_path=letrecaux=function|PathAtompa->PathAtom(glob_hints_path_atompa)|PathStarp->PathStar(auxp)|PathSeq(p,p')->PathSeq(auxp,auxp')|PathOr(p,p')->PathOr(auxp,auxp')|PathEmpty->PathEmpty|PathEpsilon->PathEpsiloninauxletsubst_path_atomsubstp=matchpwith|PathAny->p|PathHintsgrs->letgr'gr=fst(subst_globalsubstgr)inletgrs'=List.Smart.mapgr'grsinifgrs'==grsthenpelsePathHintsgrs'letrecsubst_hints_pathsubsthp=matchhpwith|PathAtomp->letp'=subst_path_atomsubstpinifp'==pthenhpelsePathAtomp'|PathStarp->letp'=subst_hints_pathsubstpinifp'==pthenhpelsePathStarp'|PathSeq(p,q)->letp'=subst_hints_pathsubstpinletq'=subst_hints_pathsubstqinifp'==p&&q'==qthenhpelsePathSeq(p',q')|PathOr(p,q)->letp'=subst_hints_pathsubstpinletq'=subst_hints_pathsubstqinifp'==p&&q'==qthenhpelsePathOr(p',q')|_->hptypehint_db_name=stringtypemode_match=|NoMode|WithModeofhint_modearraytype'awith_mode=|ModeMatchofmode_match*'a|ModeMismatchmoduleHint_db:sigtypetvalempty:?name:hint_db_name->TransparentState.t->bool->tvalmap_none:secvars:Id.Pred.t->t->full_hintlistvalmap_all:secvars:Id.Pred.t->GlobRef.t->t->full_hintlistvalmap_eauto:Environ.env->evar_map->secvars:Id.Pred.t->(GlobRef.t*constrarray)->constr->t->full_hintlistwith_modevalmap_auto:Environ.env->evar_map->secvars:Id.Pred.t->(GlobRef.t*constrarray)->constr->t->full_hintlistvaladd_list:env->evar_map->hint_entrylist->t->tvalremove_one:Environ.env->GlobRef.t->t->tvalremove_list:Environ.env->GlobRef.tlist->t->tvaliter:(GlobRef.toption->hint_modearraylist->full_hintlist->unit)->t->unitvaluse_dn:t->boolvaltransparent_state:t->TransparentState.tvalset_transparent_state:t->TransparentState.t->tvaladd_cut:hints_path->t->tvaladd_mode:GlobRef.t->hint_modearray->t->tvalcut:t->hints_pathvalunfolds:t->Id.Set.t*Cset.t*PRset.tvaladd_modes:hint_modearraylistGlobRef.Map.t->t->tvalmodes:t->hint_modearraylistGlobRef.Map.tvalfold:(GlobRef.toption->hint_modearraylist->full_hintlist->'a->'a)->t->'a->'aend=structtypet={hintdb_state:TransparentState.t;hintdb_cut:hints_path;hintdb_unfolds:Id.Set.t*Cset.t*PRset.t;hintdb_max_id:int;use_dn:bool;hintdb_map:search_entryGlobRef.Map.t;(* A list of unindexed entries with no associated pattern. *)hintdb_nopat:stored_datalist;hintdb_name:stringoption;}letnext_hint_iddb=leth=db.hintdb_max_idin{dbwithhintdb_max_id=succdb.hintdb_max_id},hletempty?namestuse_dn={hintdb_state=st;hintdb_cut=PathEmpty;hintdb_unfolds=(Id.Set.empty,Cset.empty,PRset.empty);hintdb_max_id=0;use_dn=use_dn;hintdb_map=GlobRef.Map.empty;hintdb_nopat=[];hintdb_name=name;}letdn_tsdb=ifdb.use_dnthen(Somedb.hintdb_state)elseNoneletfindkeydb=tryGlobRef.Map.findkeydb.hintdb_mapwithNot_found->empty_se(dn_tsdb)letrealize_tacsecvars(id,tac)=ifId.Pred.subsettac.secvarssecvarsthenSometacelse(* Warn about no longer typable hint? *)Nonelethead_evarsigmac=letrechrecc=matchEConstr.kindsigmacwith|Evar(evk,_)->evk|App(c,_)->hrecc|Cast(c,_,_)->hrecc|_->raiseEvarutil.NoHeadEvarinhreccletmatch_modesigmamarg=matchmwith|ModeInput->not(occur_existentialsigmaarg)|ModeNoHeadEvar->(tryignore(head_evarsigmaarg);falsewithEvarutil.NoHeadEvar->true)|ModeOutput->trueletmatches_modesigmaargsmode=ifArray.lengthmode==Array.lengthargs&&Array.for_all2(match_modesigma)modeargsthenSomemodeelseNoneletmatches_modessigmaargsmodes=ifList.is_emptymodesthenSomeNoModeelseOption.map(funx->WithModex)(List.find_map(matches_modesigmaargs)modes)letmerge_entrysecvarsdbnopatpat=leth=List.sortpri_order_intdb.hintdb_nopatinleth=List.mergepri_order_inthnopatinleth=List.mergepri_order_inthpatinList.map_filter(realize_tacsecvars)hletmap_none~secvarsdb=merge_entrysecvarsdb[][]letmap_all~secvarskdb=letse=findkdbinmerge_entrysecvarsdb(StoredData.elementsse.sentry_nopat)(StoredData.elementsse.sentry_pat)(* Precondition: concl has no existentials *)letmap_autoenvsigma~secvars(k,args)concldb=letse=findkdbinletpat=lookup_tacsenvsigmaconclseinmerge_entrysecvarsdb[]pat(* [c] contains an existential *)letmap_eautoenvsigma~secvars(k,args)concldb=letse=findkdbinmatchmatches_modessigmaargsse.sentry_modewith|Somem->letpat=lookup_tacsenvsigmaconclseinModeMatch(m,merge_entrysecvarsdb[]pat)|None->ModeMismatchletis_exact=function|Give_exact_->true|_->falseletaddkvgridvdb=letidv=id,{vwithdb=db.hintdb_name}inmatchgrwith|None->letis_present(_,v')=KerName.equalv.code.uidv'.code.uidinifnot(List.existsis_presentdb.hintdb_nopat)then(* FIXME *){dbwithhintdb_nopat=idv::db.hintdb_nopat}elsedb|Somegr->letpat=ifnotdb.use_dn&&is_exactv.code.objthenNoneelsev.patinletoval=findgrdbin{dbwithhintdb_map=GlobRef.Map.addgr(add_tacpatidvoval)db.hintdb_map}letrebuild_dbst'db=letdb'={dbwithhintdb_map=GlobRef.Map.map(rebuild_dn(Somest'))db.hintdb_map;hintdb_state=st';hintdb_nopat=[]}inList.fold_left(fundb(id,v)->addkvNoneidvdb)db'db.hintdb_nopatletadd_oneenvsigma(k,v)db=letv=instantiate_hintenvsigmavinletst',db,rebuild=matchv.code.objwith|Unfold_nthegr->letaddunfts(ids,csts,prjs)=letopenTransparentStateinmatchegrwith|Evaluable.EvalVarRefid->{tswithtr_var=Id.Pred.addidts.tr_var},(Id.Set.addidids,csts,prjs)|Evaluable.EvalConstRefcst->{tswithtr_cst=Cpred.addcstts.tr_cst},(ids,Cset.addcstcsts,prjs)|Evaluable.EvalProjectionRefp->{tswithtr_prj=PRpred.addpts.tr_prj},(ids,csts,PRset.addpprjs)inletstate,unfs=addunfdb.hintdb_statedb.hintdb_unfoldsinstate,{dbwithhintdb_unfolds=unfs},true|_->db.hintdb_state,db,falseinletdb=ifdb.use_dn&&rebuildthenrebuild_dbst'dbelsedbinletdb,id=next_hint_iddbinaddkvkidvdbletadd_listenvsigmaldb=List.fold_left(fundbk->add_oneenvsigmakdb)dblletremovestgrsse=letgrs=List.fold_left(funaccugr->GlobRef.Set.addgraccu)GlobRef.Set.emptygrsinletnopat=StoredData.removegrsse.sentry_nopatinletpat=StoredData.removegrsse.sentry_patinifpat==se.sentry_pat&&nopat==se.sentry_nopatthenseelseletse={sewithsentry_nopat=nopat;sentry_pat=pat}inrebuild_dnstseletremove_listenvgrsdb=letfilter(_,h)=matchh.namewithSomegr->not(List.mem_fGlobRef.CanOrd.equalgrgrs)|None->trueinlethintmap=GlobRef.Map.map(fune->remove(dn_tsdb)grse)db.hintdb_mapinlethintnopat=List.filterfilterdb.hintdb_nopatin{dbwithhintdb_map=hintmap;hintdb_nopat=hintnopat}letremove_oneenvgrdb=remove_listenv[gr]dbletget_entryse=leth=List.mergepri_order_int(StoredData.elementsse.sentry_nopat)(StoredData.elementsse.sentry_pat)inList.mapsndhletiterfdb=letiter_sekse=f(Somek)se.sentry_mode(get_entryse)infNone[](List.mapsnddb.hintdb_nopat);GlobRef.Map.iteriter_sedb.hintdb_mapletfoldfdbaccu=letaccu=fNone[](List.mapsnddb.hintdb_nopat)accuinGlobRef.Map.fold(funkse->f(Somek)se.sentry_mode(get_entryse))db.hintdb_mapacculettransparent_statedb=db.hintdb_stateletset_transparent_statedbst=ifdb.use_dnthenrebuild_dbstdbelse{dbwithhintdb_state=st}letadd_cutpathdb={dbwithhintdb_cut=normalize_path(PathOr(db.hintdb_cut,path))}letadd_modegrmdb=letse=findgrdbinletse={sewithsentry_mode=m::List.remove(Array.equalhint_mode_eq)mse.sentry_mode}in{dbwithhintdb_map=GlobRef.Map.addgrsedb.hintdb_map}letcutdb=db.hintdb_cutletunfoldsdb=db.hintdb_unfoldsletadd_modesmodesdb=letfgreme=Some{ewithsentry_mode=me.sentry_mode@e.sentry_mode}inletmode_entries=GlobRef.Map.map(funm->{(empty_se(dn_tsdb))withsentry_mode=m})modesin{dbwithhintdb_map=GlobRef.Map.unionfdb.hintdb_mapmode_entries}letmodesdb=GlobRef.Map.map(funse->se.sentry_mode)db.hintdb_mapletuse_dndb=db.use_dnendmoduleHintdbmap=String.Maptypehint_db=Hint_db.tletsearchtable=Summary.ref~name:"searchtable"Hintdbmap.emptyletstatustable=Summary.ref~name:"statustable"KNmap.emptyletsearchtable_mapname=Hintdbmap.findname!searchtableletsearchtable_add(name,db)=searchtable:=Hintdbmap.addnamedb!searchtableletcurrent_db_names()=Hintdbmap.domain!searchtableletcurrent_db()=Hintdbmap.bindings!searchtableletcurrent_pure_db()=List.mapsnd(current_db())leterror_no_such_hint_databasex=user_err(str"No such Hint database: "++strx++str".")(**************************************************************************)(* Auxiliary functions to prepare AUTOHINT objects *)(**************************************************************************)letrecnb_hypsigmac=matchEConstr.kindsigmacwith|Prod(_,_,c2)->ifnoccurnsigma1c2then1+(nb_hypsigmac2)elsenb_hypsigmac2|_->0(* adding and removing tactics in the search table *)letwith_uidc={obj=c;uid=fresh_key()}letsecvars_of_idsets=Id.Set.fold(funidp->ifis_section_variable(Global.env())idthenId.Pred.addidpelsep)sId.Pred.emptyletsecvars_of_constrenvsigmac=secvars_of_idset(Termops.global_vars_setenvsigmac)letsecvars_of_globalenvgr=secvars_of_idset(vars_of_globalenvgr)letmake_exact_entryenvsigmainfo?name(c,cty,ctx)=letsecvars=secvars_of_constrenvsigmacinletcty=strip_outer_castsigmactyinmatchEConstr.kindsigmactywith|Prod_->failwith"make_exact_entry"|_->lethd=tryhead_boundsigmactywithBound->failwith"make_exact_entry"inletpri=matchinfo.hint_prioritywithNone->0|Somep->pinletpat=matchinfo.hint_patternwith|Somepat->ConstrPattern(sndpat)|None->DefaultPatterninleth={rhint_term=c;rhint_type=cty;rhint_uctx=ctx;rhint_arty=0}in(Somehd,{pri;pat=Somepat;name;db=None;secvars;code=with_uid(Give_exacth);})letname_of_hint=function|IsGlobRefgr->Somegr|IsConstr_->Noneletmake_apply_entryenvsigmahnfinfo?name(c,cty,ctx)=letcty=ifhnfthenhnf_constr0envsigmactyelsectyinmatchEConstr.kindsigmactywith|Prod_->letcty=ifhnfthenReductionops.nf_betaiotaenvsigmactyelsectyinletsigma'=merge_context_set_optsigmactxinletce=Clenv.mk_clenv_fromenvsigma'(c,cty)inletc'=Clenv.clenv_type(* ~reduce:false *)ceinlethd=tryhead_bound(Clenv.clenv_evdce)c'withBound->failwith"make_apply_entry"inletmiss=Clenv.clenv_missingceinletnmiss=List.lengthmissinletsecvars=secvars_of_constrenvsigmacinlethyps=nb_hypsigma'ctyinletpri=matchinfo.hint_prioritywithNone->hyps+nmiss|Somep->pinletpat=matchinfo.hint_patternwith|Somep->ConstrPattern(sndp)|None->DefaultPatterninleth={rhint_term=c;rhint_type=cty;rhint_uctx=ctx;rhint_arty=hyps;}inifInt.equalnmiss0then(Somehd,{pri;pat=Somepat;name;db=None;secvars;code=with_uid(Res_pfh);})else(Somehd,{pri;pat=Somepat;name;db=None;secvars;code=with_uid(ERes_pfh);})|_->failwith"make_apply_entry"(* flags is (e,h,v) with e=true if eapply and h=true if hnf and v=true if verbose
c is a constr
cty is the type of constr *)letfresh_global_or_constrenvsigmacr=matchcrwith|IsGlobRefgr->let(c,ctx)=UnivGen.fresh_global_instanceenvgrinletctx=ifEnviron.is_polymorphicenvgrthenSomectxelseNonein(EConstr.of_constrc,ctx)|IsConstr(c,ctx)->(c,ctx)letmake_resolvesenvsigma(eapply,hnf)info~checkcr=letname=name_of_hintcrinletc,ctx=fresh_global_or_constrenvsigmacrinletcty=Retyping.get_type_ofenvsigmacinlettry_applyf=trylet(_,hint)asans=f(c,cty,ctx)inmatchhint.code.objwith|ERes_pf_->ifnoteapplythenNoneelseSomeans|_->SomeanswithFailure_->Noneinletents=List.map_filtertry_apply[make_exact_entryenvsigmainfo?name;make_apply_entryenvsigmahnfinfo?name]inifcheck&&List.is_emptyentsthenuser_err(pr_leconstr_envenvsigmac++spc()++(ifeapplythenstr"cannot be used as a hint."elsestr"can be used as a hint only for eauto."));ents(* used to add an hypothesis to the local hint database *)letmake_resolve_hypenvsigmahname=letdecl=EConstr.lookup_namedhnameenvinletc=mkVarhnameintry[make_apply_entryenvsigmatrueempty_hint_info~name:(GlobRef.VarRefhname)(c,NamedDecl.get_typedecl,None)]with|Failure_->[]|ewhennoncriticale->anomaly(Pp.str"make_resolve_hyp.")(* REM : in most cases hintname = id *)letmake_unfolderef=letg=global_of_evaluable_referenceerefin(Someg,{pri=4;pat=None;name=Someg;db=None;secvars=secvars_of_global(Global.env())g;code=with_uid(Unfold_ntheref)})letmake_externpripattacast=lethdconstr=matchpatwith|None->None|Somec->trySome(head_pattern_boundc)withBoundPattern->user_err(Pp.str"Head pattern or sub-pattern must be a global constant, a section variable, \
an if, case, or let expression, an application, or a projection.")in(hdconstr,{pri=pri;pat=Option.map(funp->SyntacticPatternp)pat;name=None;db=None;secvars=Id.Pred.empty;(* Approximation *)code=with_uid(Extern(pat,tacast))})letmake_moderefm=letopenTerminletty,_=Typeops.type_of_global_in_context(Global.env())refinletctx,t=decompose_prodtyinletn=List.lengthctxinletm'=Array.of_listminifnot(n==Array.lengthm')thenuser_err(pr_globalref++str" has "++intn++str" arguments while the mode declares "++int(Array.lengthm')++str".")elsem'letmake_trivialenvsigmar=letname=name_of_hintrinletc,ctx=fresh_global_or_constrenvsigmarinletsigma=merge_context_set_optsigmactxinlett=hnf_constrenvsigma(Retyping.get_type_ofenvsigmac)inlethd=head_constrsigmatinleth={rhint_term=c;rhint_type=t;rhint_uctx=ctx;rhint_arty=0}in(Somehd,{pri=1;pat=SomeDefaultPattern;name=name;db=None;secvars=secvars_of_constrenvsigmac;code=with_uid(Res_pf_THEN_trivial_failh)})(**************************************************************************)(* declaration of the AUTOHINT library object *)(**************************************************************************)(* If the database does not exist, it is created *)(* TODO: should a warning be printed in this case ?? *)letget_dbdbname=trysearchtable_mapdbnamewithNot_found->Hint_db.empty~name:dbnameTransparentState.emptyfalseletadd_hintdbnamehintlist=letcheck(_,h)=let()=ifKNmap.memh.code.uid!statustablethenuser_errPp.(str"Conflicting hint keys. This can happen when including \
twice the same module.")instatustable:=KNmap.addh.code.uidfalse!statustableinlet()=List.itercheckhintlistinletdb=get_dbdbnameinletenv=Global.env()inletsigma=Evd.from_envenvinletdb'=Hint_db.add_listenvsigmahintlistdbinsearchtable_add(dbname,db')letadd_transparencydbnametargetb=letopenTransparentStateinletdb=get_dbdbnameinletst=Hint_db.transparent_statedbinletst'=matchtargetwith|HintsVariables->{stwithtr_var=(ifbthenId.Pred.fullelseId.Pred.empty)}|HintsConstants->{stwithtr_cst=(ifbthenCpred.fullelseCpred.empty)}|HintsProjections->{stwithtr_prj=(ifbthenPRpred.fullelsePRpred.empty)}|HintsReferencesgrs->List.fold_left(funstgr->matchgrwith|Evaluable.EvalConstRefc->{stwithtr_cst=(ifbthenCpred.addelseCpred.remove)cst.tr_cst}|Evaluable.EvalVarRefv->{stwithtr_var=(ifbthenId.Pred.addelseId.Pred.remove)vst.tr_var}|Evaluable.EvalProjectionRefp->{stwithtr_prj=(ifbthenPRpred.addelsePRpred.remove)pst.tr_prj})stgrsinsearchtable_add(dbname,Hint_db.set_transparent_statedbst')letremove_hintdbnamegrs=letenv=Global.env()inletdb=get_dbdbnameinletdb'=Hint_db.remove_listenvgrsdbinsearchtable_add(dbname,db')letadd_cutdbnamepath=letdb=get_dbdbnameinletdb'=Hint_db.add_cutpathdbinsearchtable_add(dbname,db')letadd_modedbnamelm=letdb=get_dbdbnameinletdb'=Hint_db.add_modelmdbinsearchtable_add(dbname,db')typedb_obj={db_local:bool;db_name:string;db_use_dn:bool;db_ts:TransparentState.t;}letcache_db{db_name=name;db_use_dn=b;db_ts=ts}=searchtable_add(name,Hint_db.empty~nametsb)letload_db_x=cache_dbxletclassify_dbdb=ifdb.db_localthenDisposeelseSubstituteletinDB:db_obj->obj=declare_object{(default_object"AUTOHINT_DB")withcache_function=cache_db;load_function=load_db;subst_function=(fun(_,x)->x);classify_function=classify_db;}letcreate_hint_dblntsb=lethint={db_local=l;db_name=n;db_use_dn=b;db_ts=ts}inLib.add_leaf(inDBhint)typehint_action=|AddTransparencyof{grefs:Evaluable.thints_transparency_target;state:bool;}|AddHintsofhint_entrylist|RemoveHintsofGlobRef.tlist|AddCutofhints_path|AddModeof{gref:GlobRef.t;mode:hint_modearray}typehint_locality=Local|Export|SuperGlobaltypehint_obj={hint_local:hint_locality;hint_name:string;hint_action:hint_action;}letis_trivial_action=function|AddTransparency{grefs}->beginmatchgrefswith|HintsVariables|HintsConstants|HintsProjections->false|HintsReferencesl->List.is_emptylend|AddHintsl->List.is_emptyl|RemoveHintsl->List.is_emptyl|AddCut_|AddMode_->falseletrecis_section_path=function|PathAtomPathAny->false|PathAtom(PathHintsgrs)->letcheckc=isVarRefc&&Lib.is_in_sectioncinList.existscheckgrs|PathStarp->is_section_pathp|PathSeq(p,q)|PathOr(p,q)->is_section_pathp||is_section_pathq|PathEmpty|PathEpsilon->falseletsuperglobalh=matchh.hint_localwith|SuperGlobal->true|Local|Export->falseletload_autohint_h=letname=h.hint_nameinletsuperglobal=superglobalhinmatchh.hint_actionwith|AddTransparency{grefs;state}->ifsuperglobalthenadd_transparencynamegrefsstate|AddHintshints->ifsuperglobalthenadd_hintnamehints|RemoveHintshints->ifsuperglobalthenremove_hintnamehints|AddCutpaths->ifsuperglobalthenadd_cutnamepaths|AddMode{gref;mode}->ifsuperglobalthenadd_modenamegrefmodeletopen_autohintih=letsuperglobal=superglobalhinifInt.equali1thenmatchh.hint_actionwith|AddHintshints->let()=ifnotsuperglobalthen(* Import-bound hints must be declared when not imported yet *)letfilter(_,h)=not@@KNmap.memh.code.uid!statustableinadd_hinth.hint_name(List.filterfilterhints)inletadd(_,hint)=statustable:=KNmap.addhint.code.uidtrue!statustableinList.iteraddhints|AddCutpaths->ifnotsuperglobalthenadd_cuth.hint_namepaths|AddTransparency{grefs;state}->ifnotsuperglobalthenadd_transparencyh.hint_namegrefsstate|RemoveHintshints->ifnotsuperglobalthenremove_hinth.hint_namehints|AddMode{gref;mode}->ifnotsuperglobalthenadd_modeh.hint_namegrefmodeletcache_autohinto=load_autohint1o;open_autohint1oletsubst_autohint(subst,obj)=letsubst_keygr=let(gr',t)=subst_globalsubstgrinmatchtwith|None->gr'|Somet->(tryhead_boundEvd.empty(EConstr.of_constrt.UVars.univ_abstracted_value)withBound->gr')inletsubst_mpssubstc=EConstr.of_constr(subst_mpssubst(EConstr.Unsafe.to_constrc))inletsubst_aux({rhint_term=c;rhint_type=t;rhint_uctx=ctx;rhint_arty=ar}ash)=letc'=subst_mpssubstcinlett'=subst_mpssubsttinifc==c'&&t'==tthenhelse{rhint_term=c';rhint_type=t';rhint_uctx=ctx;rhint_arty=ar}inletsubst_hint(k,dataashint)=letk'=Option.Smart.mapsubst_keykinletenv=Global.env()inletsigma=Evd.from_envenvinletsubst_hint_pattern=function|DefaultPattern->DefaultPattern|ConstrPatternpasp0->letp'=subst_patternenvsigmasubstpinifp'==pthenp0elseConstrPatternp'|SyntacticPatternpasp0->letp'=subst_patternenvsigmasubstpinifp'==pthenp0elseSyntacticPatternp'inletpat'=Option.Smart.mapsubst_hint_patterndata.patinletcode'=matchdata.code.objwith|Res_pfh->leth'=subst_auxhinifh==h'thendata.code.objelseRes_pfh'|ERes_pfh->leth'=subst_auxhinifh==h'thendata.code.objelseERes_pfh'|Give_exacth->leth'=subst_auxhinifh==h'thendata.code.objelseGive_exacth'|Res_pf_THEN_trivial_failh->leth'=subst_auxhinifh==h'thendata.code.objelseRes_pf_THEN_trivial_failh'|Unfold_nthref->letref'=subst_evaluable_referencesubstrefinifref==ref'thendata.code.objelseUnfold_nthref'|Extern(pat,tac)->letpat'=Option.Smart.map(subst_patternenvsigmasubst)patinlettac'=Gensubst.generic_substitutesubsttacinifpat==pat'&&tac==tac'thendata.code.objelseExtern(pat',tac')inletname'=Option.Smart.map(subst_global_referencesubst)data.nameinletuid'=subst_knsubstdata.code.uidinletdata'=ifdata.code.uid==uid'&&data.pat==pat'&&data.name==name'&&data.code.obj==code'thendataelse{datawithpat=pat';name=name';code={obj=code';uid=uid'}}inifk'==k&&data'==datathenhintelse(k',data')inletaction=matchobj.hint_actionwith|AddTransparency{grefs=target;state=b}->lettarget'=matchtargetwith|HintsVariables->target|HintsConstants->target|HintsProjections->target|HintsReferencesgrs->letgrs'=List.Smart.map(subst_evaluable_referencesubst)grsinifgrs==grs'thentargetelseHintsReferencesgrs'iniftarget'==targetthenobj.hint_actionelseAddTransparency{grefs=target';state=b}|AddHintshints->lethints'=List.Smart.mapsubst_hinthintsinifhints'==hintsthenobj.hint_actionelseAddHintshints'|RemoveHintsgrs->letgrs'=List.Smart.map(subst_global_referencesubst)grsinifgrs==grs'thenobj.hint_actionelseRemoveHintsgrs'|AddCutpath->letpath'=subst_hints_pathsubstpathinifpath'==paththenobj.hint_actionelseAddCutpath'|AddMode{gref=l;mode=m}->letl'=subst_global_referencesubstlinifl'==lthenobj.hint_actionelseAddMode{gref=l';mode=m}inifaction==obj.hint_actionthenobjelse{objwithhint_action=action}letis_hint_local=functionLocal->true|Export|SuperGlobal->falseletclassify_autohintobj=ifis_hint_localobj.hint_local||is_trivial_actionobj.hint_actionthenDisposeelseSubstituteletdischarge_autohintobj=ifis_hint_localobj.hint_localthenNoneelseletaction=matchobj.hint_actionwith|AddTransparency{grefs;state}->letgrefs=matchgrefswith|HintsVariables|HintsConstants|HintsProjections->grefs|HintsReferencesgrs->letfiltere=matchewith|Evaluable.EvalConstRefc->Somee|Evaluable.EvalProjectionRefp->letp=Lib.discharge_proj_reprpinSome(Evaluable.EvalProjectionRefp)|Evaluable.EvalVarRefid->ifLib.is_in_section(GlobRef.VarRefid)thenNoneelseSomeeinletgrs=List.filter_mapfiltergrsinHintsReferencesgrsinAddTransparency{grefs;state}|AddHints_|RemoveHints_->(* not supported yet *)assertfalse|AddCutpath->ifis_section_pathpaththenAddHints[](* dummy *)elseobj.hint_action|AddMode{gref;mode}->ifLib.is_in_sectiongrefthenifisVarRefgrefthenAddHints[](* dummy *)elseletinst=Lib.section_instancegrefin(* Default mode for discharged parameters is output *)letmode=Array.append(Array.make(Array.lengthinst)ModeOutput)modeinAddMode{gref;mode}elseobj.hint_actioninifis_trivial_actionactionthenNoneelseSome{objwithhint_action=action}lethint_cat=create_category"hints"letinAutoHint:hint_obj->obj=declare_object{(default_object"AUTOHINT")withcache_function=cache_autohint;load_function=load_autohint;open_function=simple_open~cat:hint_catopen_autohint;subst_function=subst_autohint;classify_function=classify_autohint;discharge_function=discharge_autohint;}letcheck_localitylocality=letnot_localwhat=CErrors.user_errPp.(str"This command does not support the "++strwhat++str" attribute in sections.")inifLib.sections_are_opened()thenmatchlocalitywith|Local->()|SuperGlobal->not_local"global"|Export->not_local"export"letmake_hint~localitynameaction={hint_local=locality;hint_name=name;hint_action=action;}letremove_hints~localitydbnamesgrs=let()=check_localitylocalityinletdbnames=ifList.is_emptydbnamesthen["core"]elsedbnamesinList.iter(fundbname->lethint=make_hint~localitydbname(RemoveHintsgrs)inLib.add_leaf(inAutoHinthint))dbnames(**************************************************************************)(* The "Hint" vernacular command *)(**************************************************************************)letadd_resolvesenvsigmaclist~localitydbnames=List.iter(fundbname->letr=List.flatten(List.map(fun(pri,hnf,gr)->make_resolvesenvsigma(true,hnf)pri~check:truegr)clist)inletcheck(_,hint)=matchhint.code.objwith|ERes_pf{rhint_term=c;rhint_type=cty;rhint_uctx=ctx}->letsigma'=merge_context_set_optsigmactxinletce=Clenv.mk_clenv_fromenvsigma'(c,cty)inletmiss=Clenv.clenv_missingceinletnmiss=List.lengthmissinletvariables=str(CString.pluralnmiss"variable")inFeedback.msg_info(strbrk"The hint "++pr_leconstr_envenvsigma'c++strbrk" will only be used by eauto, because applying "++pr_leconstr_envenvsigma'c++strbrk" would leave "++variables++Pp.spc()++Pp.prlist_with_sepPp.pr_commaName.print(List.map(Evd.meta_name(Clenv.clenv_evdce))miss)++strbrk" as unresolved existential "++variables++str".")|_->()inlet()=ifnot!Flags.quietthenList.itercheckrinlethint=make_hint~localitydbname(AddHintsr)inLib.add_leaf(inAutoHinthint))dbnamesletadd_unfoldsl~localitydbnames=List.iter(fundbname->lethint=make_hint~localitydbname(AddHints(List.mapmake_unfoldl))inLib.add_leaf(inAutoHinthint))dbnamesletadd_cutsl~localitydbnames=List.iter(fundbname->lethint=make_hint~localitydbname(AddCutl)inLib.add_leaf(inAutoHinthint))dbnamesletadd_modelm~localitydbnames=List.iter(fundbname->letm'=make_modelminlethint=make_hint~localitydbname(AddMode{gref=l;mode=m'})inLib.add_leaf(inAutoHinthint))dbnamesletadd_transparencylb~localitydbnames=List.iter(fundbname->lethint=make_hint~localitydbname(AddTransparency{grefs=l;state=b})inLib.add_leaf(inAutoHinthint))dbnamesletadd_externinfotacast~localitydbname=letpat=matchinfo.hint_patternwith|None->None|Some(_,pat)->Somepatinlethint=make_hint~localitydbname(AddHints[make_extern(Option.getinfo.hint_priority)pattacast])inLib.add_leaf(inAutoHinthint)letadd_externsinfotacast~localitydbnames=List.iter(add_externinfotacast~locality)dbnamesletadd_trivialsenvsigmal~localitydbnames=List.iter(fundbname->letl=List.map(func->make_trivialenvsigmac)linlethint=make_hint~localitydbname(AddHintsl)inLib.add_leaf(inAutoHinthint))dbnamestypehnf=booltypenonrechint_info=hint_infotypehints_entry=|HintsResolveEntryof(hint_info*hnf*hint_term)list|HintsImmediateEntryofhint_termlist|HintsCutEntryofhints_path|HintsUnfoldEntryofEvaluable.tlist|HintsTransparencyEntryofEvaluable.thints_transparency_target*bool|HintsModeEntryofGlobRef.t*hint_modelist|HintsExternEntryofhint_info*Genarg.glob_generic_argumentletdefault_prepare_hint_ident=Id.of_string"H"exceptionFoundofconstr*typesletprepare_hintenvinit(sigma,c)=letsigma=Typeclasses.resolve_typeclasses~fail:falseenvsigmain(* We re-abstract over uninstantiated evars and universes.
It is actually a bit stupid to generalize over evars since the first
thing make_resolves will do is to re-instantiate the products *)letc=Evarutil.nf_evarsigmacinletc=drop_extra_implicit_argssigmacinletvars=ref(collect_varssigmac)inletsubst=ref[]inletrecfind_next_evarc=matchEConstr.kindsigmacwith|Evar(evk,argsasev)->(* We skip the test whether args is the identity or not *)lett=Evarutil.nf_evarsigma(existential_typesigmaev)inlett=List.fold_right(fun(e,id)c->replace_termsigmaeidc)!substtinifnot(closed0sigmac)thenuser_errPp.(str"Hints with holes dependent on a bound variable not supported.");ifoccur_existentialsigmatthen(* Not clever enough to construct dependency graph of evars *)user_errPp.(str"Not clever enough to deal with evars dependent in other evars.");raise(Found(c,t))|_->EConstr.itersigmafind_next_evarcinletreciterc=tryfind_next_evarc;cwithFound(evar,t)->letid=next_ident_away_fromdefault_prepare_hint_ident(funid->Id.Set.memid!vars)invars:=Id.Set.addid!vars;subst:=(evar,mkVarid)::!subst;mkNamedLambdasigma(make_annotidERelevance.relevant)t(iter(replace_termsigmaevar(mkVarid)c))inletc'=itercinletdiff=UnivGen.diff_sort_context(Evd.sort_context_setsigma)(Evd.sort_context_setinit)in(c',diff)letwarn_non_local_section_hint=CWarnings.create~name:"non-local-section-hint"~category:CWarnings.CoreCategories.automation(fun()->strbrk"This hint is not local but depends on a section variable. It will disappear when the section is closed.")letis_notlocal=function|Local->false|Export|SuperGlobal->trueletadd_hints~localitydbnamesh=let()=matchhwith|HintsResolveEntry_|HintsImmediateEntry_|HintsUnfoldEntry_|HintsExternEntry_->check_localitylocality|HintsTransparencyEntry((HintsVariables|HintsConstants|HintsProjections),_)->()|HintsTransparencyEntry(HintsReferencesgrs,_)->letitergr=letgr=global_of_evaluable_referencegrinifis_notlocallocality&&isVarRefgr&&Lib.is_in_sectiongrthenwarn_non_local_section_hint()inList.iteritergrs|HintsCutEntryp->ifis_notlocallocality&&is_section_pathpthenwarn_non_local_section_hint()|HintsModeEntry(gr,_)->ifis_notlocallocality&&isVarRefgr&&Lib.is_in_sectiongrthenwarn_non_local_section_hint()inifString.List.mem"nocore"dbnamesthenuser_errPp.(str"The hint database \"nocore\" is meant to stay empty.");assert(not(List.is_emptydbnames));letenv=Global.env()inletsigma=Evd.from_envenvinmatchhwith|HintsResolveEntrylhints->add_resolvesenvsigmalhints~localitydbnames|HintsImmediateEntrylhints->add_trivialsenvsigmalhints~localitydbnames|HintsCutEntrylhints->add_cutslhints~localitydbnames|HintsModeEntry(l,m)->add_modelm~localitydbnames|HintsUnfoldEntrylhints->add_unfoldslhints~localitydbnames|HintsTransparencyEntry(lhints,b)->add_transparencylhintsb~localitydbnames|HintsExternEntry(info,tacexp)->add_externsinfotacexp~localitydbnameslethint_globrefgr=IsGlobRefgrlethint_constr(c,diff)=IsConstr(c,diff)letwarn_non_reference_hint_using=CWarnings.create~name:"non-reference-hint-using"~category:CWarnings.CoreCategories.deprecatedPp.(fun(env,sigma,c)->str"Use of the non-reference term "++pr_leconstr_envenvsigmac++str" in \"using\" clauses is deprecated")letexpand_constructor_hintsenvsigmalems=List.map_append(funlem->letevd,lem=lemenvsigmainletlem0=drop_extra_implicit_argsevdleminmatchEConstr.kindevdlem0with|Ind(ind,u)->List.init(nconstructorsenvind)(funi->IsGlobRef(GlobRef.ConstructRef((ind,i+1))))|Const(cst,_)->[IsGlobRef(GlobRef.ConstRefcst)]|Varid->[IsGlobRef(GlobRef.VarRefid)]|Construct(cstr,_)->[IsGlobRef(GlobRef.ConstructRefcstr)]|_->let()=warn_non_reference_hint_using(env,evd,lem)inlet(c,ctx)=prepare_hintenvsigma(evd,lem)inletctx=ifUnivGen.is_empty_sort_contextctxthenNoneelseSomectxin[IsConstr(c,ctx)])lems(* builds a hint database from a constr signature *)(* typically used with (lid, ltyp) = pf_hyps_types <some goal> *)letconstructor_hintsenvsigmaeapplylems=letlems=expand_constructor_hintsenvsigmalemsinList.map_append(funlem->make_resolvesenvsigma(eapply,true)empty_hint_info~check:truelem)lemsletmake_local_hint_dbenvsigmatseapplylems=letsign=EConstr.named_contextenvinletts=matchtswith|None->Hint_db.transparent_state(searchtable_map"core")|Somets->tsinlethintlist=List.map_append(fundecl->make_resolve_hypenvsigma(Named.Declaration.get_iddecl))signinHint_db.emptytsfalse|>Hint_db.add_listenvsigmahintlist|>Hint_db.add_listenvsigma(constructor_hintsenvsigmaeapplylems)letmake_local_hint_dbenvsigma?tseapplylems=make_local_hint_dbenvsigmatseapplylemsletmake_db_listdbnames=letuse_core=not(List.mem"nocore"dbnames)inletdbnames=List.removeString.equal"nocore"dbnamesinletdbnames=ifuse_corethen"core"::dbnameselsedbnamesinletlookupdb=trysearchtable_mapdbwithNot_found->error_no_such_hint_databasedbinList.maplookupdbnamesletpush_resolvesenvsigmahintdb=letentries=make_resolvesenvsigma(true,false)empty_hint_info~check:false(IsGlobRefhint)inHint_db.add_listenvsigmaentriesdbletpush_resolve_hypenvsigmadecldb=letentries=make_resolve_hypenvsigmadeclinHint_db.add_listenvsigmaentriesdb(**************************************************************************)(* Functions for printing the hints *)(**************************************************************************)letpr_hint_eltenvsigmah=pr_econstr_envenvsigmah.hint_termletpr_hintenvsigmah=matchh.objwith|Res_pfc->(str"simple apply "++pr_hint_eltenvsigmac)|ERes_pfc->(str"simple eapply "++pr_hint_eltenvsigmac)|Give_exactc->(str"exact "++pr_hint_eltenvsigmac)|Res_pf_THEN_trivial_failc->(str"simple apply "++pr_hint_eltenvsigmac++str" ; trivial")|Unfold_nthc->str"unfold "++pr_evaluable_referencec|Extern(_,tac)->str"(*external*) "++Pputils.pr_glb_genericenvsigmatacletpr_id_hintenvsigma(id,v)=letpr_patp=matchp.patwith|None->mt()|Some(ConstrPatternp|SyntacticPatternp)->str", pattern "++pr_lconstr_pattern_envenvsigmap|SomeDefaultPattern->str", pattern "++pr_leconstr_envenvsigma(get_default_patternv.code.obj)in(pr_hintenvsigmav.code++str"(level "++intv.pri++pr_patv++str", id "++intid++str")"++spc())letpr_hint_listenvsigmahintlist=(str" "++hov0(prlist(pr_id_hintenvsigma)hintlist)++fnl())letpr_hints_dbenvsigma(name,db,hintlist)=(str"In the database "++strname++str":"++ifList.is_emptyhintlistthen(str" nothing"++fnl())else(fnl()++pr_hint_listenvsigmahintlist))(* Print all hints associated to head c in any database *)letpr_hint_list_for_headenvsigmac=letdbs=current_db()inletvalidate(name,db)=lethints=List.map(funv->0,v)(Hint_db.map_all~secvars:Id.Pred.fullcdb)in(name,db,hints)inletvalid_dbs=List.mapvalidatedbsinifList.is_emptyvalid_dbsthen(str"No hint declared for :"++pr_globalc)elsehov0(str"For "++pr_globalc++str" -> "++fnl()++hov0(prlist(pr_hints_dbenvsigma)valid_dbs))letpr_hint_refref=pr_hint_list_for_headref(* Print all hints associated to head id in any database *)letpr_hint_termenvsigmacl=tryletdbs=current_db()inletvalid_dbs=letfn=trylethdc=decompose_app_boundsigmaclinifoccur_existentialsigmaclthen(fundb->matchHint_db.map_eautoenvsigma~secvars:Id.Pred.fullhdccldbwith|ModeMatch(_,l)->l|ModeMismatch->[])elseHint_db.map_autoenvsigma~secvars:Id.Pred.fullhdcclwithBound->Hint_db.map_none~secvars:Id.Pred.fullinletfndb=List.map(funx->0,x)(fndb)inList.map(fun(name,db)->(name,db,fndb))dbsinifList.is_emptyvalid_dbsthen(str"No hint applicable for current goal")else(str"Applicable Hints :"++fnl()++hov0(prlist(pr_hints_dbenvsigma)valid_dbs))withMatch_failure_|Failure_->(str"No hint applicable for current goal")(* print all hints that apply to the concl of the current goal *)letpr_applicable_hintpf=letenv=Global.env()inletProof.{goals;sigma}=Proof.datapfinmatchgoalswith|[]->CErrors.user_errPp.(str"No focused goal.")|g::_->pr_hint_termenvsigma(Evd.evar_concl(Evd.find_undefinedsigmag))letpp_hint_mode=function|ModeInput->str"+"|ModeNoHeadEvar->str"!"|ModeOutput->str"-"(* displays the whole hint database db *)letpr_hint_db_envenvsigmadb=letpr_mode=prvect_with_sepspcpp_hint_modeinletpr_modesl=ifList.is_emptylthenmt()elsestr" (modes "++prlist_with_seppr_commapr_model++str")"inletcontent=letfoldheadmodeshintlistaccu=letgoal_descr=matchheadwith|None->str"For any goal"|Somehead->str"For "++pr_globalhead++pr_modesmodesinlethints=pr_hint_listenvsigma(List.map(funx->(0,x))hintlist)inlethint_descr=hov0(goal_descr++str" -> "++hints)inaccu++hint_descrinHint_db.foldfolddb(mt())inlet{TransparentState.tr_var=ids;tr_cst=csts;tr_prj=ps}=Hint_db.transparent_statedbinhov0((ifHint_db.use_dndbthenstr"Discriminated database"elsestr"Non-discriminated database"))++fnl()++hov2(str"Unfoldable variable definitions: "++pr_idpredids)++fnl()++hov2(str"Unfoldable constant definitions: "++pr_cpredcsts)++fnl()++hov2(str"Unfoldable projection definitions: "++pr_prpredps)++fnl()++hov2(str"Cut: "++pp_hints_path(Hint_db.cutdb))++fnl()++contentletpr_hint_db_by_nameenvsigmadbname=tryletdb=searchtable_mapdbnameinpr_hint_db_envenvsigmadbwithNot_found->error_no_such_hint_databasedbname(* displays all the hints of all databases *)letpr_searchtableenvsigma=letfoldnamedbaccu=accu++str"In the database "++strname++str":"++fnl()++pr_hint_db_envenvsigmadb++fnl()inHintdbmap.foldfold!searchtable(mt())letprint_mpmp=tryletqid=Nametab.shortest_qualid_of_modulempinstr" from "++pr_qualidqidwithNot_found->mt()letis_importedh=tryKNmap.findh.uid!statustablewithNot_found->truelethint_trace=Evd.Store.field"hint_trace"letlog_hinth=letopenProofview.NotationsinProofview.tclEVARMAP>>=funsigma->letstore=get_extra_datasigmainmatchStore.getstorehint_tracewith|None->(* All calls to hint logging should be well-scoped *)assertfalse|Sometrace->lettrace=KNmap.addh.uidhtraceinletstore=Store.setstorehint_tracetraceinProofview.Unsafe.tclEVARS(set_extra_datastoresigma)letwarn_non_imported_hint=CWarnings.create~name:"non-imported-hint"~category:CWarnings.CoreCategories.automation(fun(hint,mp)->strbrk"Hint used but not imported: "++hint++print_mpmp)letwarnenvsigmah=lethint=pr_hintenvsigmahinletmp=KerName.modpathh.uidinwarn_non_imported_hint(hint,mp)letwrap_hint_warningt=letopenProofview.NotationsinProofview.tclEVARMAP>>=funsigma->letstore=get_extra_datasigmainletold=Store.getstorehint_traceinletstore=Store.setstorehint_traceKNmap.emptyinProofview.Unsafe.tclEVARS(set_extra_datastoresigma)>>=fun()->t>>=funans->Proofview.tclENV>>=funenv->Proofview.tclEVARMAP>>=funsigma->letstore=get_extra_datasigmainlethints=matchStore.getstorehint_tracewith|None->assertfalse|Somehints->hintsinlet()=KNmap.iter(fun_h->warnenvsigmah)hintsinletstore=matcholdwith|None->Store.removestorehint_trace|Somev->Store.setstorehint_tracevinProofview.Unsafe.tclEVARS(set_extra_datastoresigma)>>=fun()->Proofview.tclUNITansletwrap_hint_warning_funenvsigmat=letstore=get_extra_datasigmainletold=Store.getstorehint_traceinletstore=Store.setstorehint_traceKNmap.emptyinlet(ans,sigma)=t(set_extra_datastoresigma)inletstore=get_extra_datasigmainlethints=matchStore.getstorehint_tracewith|None->assertfalse|Somehints->hintsinlet()=KNmap.iter(fun_h->warnenvsigmah)hintsinletstore=matcholdwith|None->Store.removestorehint_trace|Somev->Store.setstorehint_tracevin(ans,set_extra_datastoresigma)letrun_hinttack=matchwarn_hint()with|HintLax->ktac.obj|HintWarn->ifis_importedtacthenktac.objelseProofview.tclTHEN(log_hinttac)(ktac.obj)|HintStrict->ifis_importedtacthenktac.objelseletinfo=Exninfo.reify()inProofview.tclZERO~info(UserError(str"Tactic failure."))moduleFullHint=structtypet=full_hintletpriority(h:t)=h.priletdatabase(h:t)=h.dbletpattern(h:t)=matchh.patwith|None->None|Some(ConstrPatternp|SyntacticPatternp)->Somep|SomeDefaultPattern->Noneletrun(h:t)k=run_hinth.codekletprintenvsigma(h:t)=pr_hintenvsigmah.codeletname(h:t)=h.nameletsubgoals(h:t)=matchh.code.objwith|Res_pfh|ERes_pfh|Give_exacth|Res_pf_THEN_trivial_failh->Someh.hint_arty|Unfold_nth_->Some1|Extern_->Noneletrepr(h:t)=h.code.objendletconnect_hint_clenvhgl=let{hint_uctx=ctx;hint_clnv=clenv}=hin(* [clenv] has been generated by a hint-making function, so the only relevant
data in its evarmap is the set of metas. The function
below just replaces the metas of sigma by those coming from the clenv. *)letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinClenv.clenv_refreshenvsigmactxclenvletfresh_hintenvsigmah=let{hint_term=c;hint_uctx=ctx}=hinmatchh.hint_uctxwith|None->sigma,c|Somectx->(* Refresh the instance of the hint *)let(subst,ctx)=UnivGen.fresh_sort_context_instancectxinletc=Vars.subst_univs_level_constrsubstcinletsigma=Evd.merge_sort_context_setEvd.univ_flexiblesigmactxinsigma,clethint_res_pf?with_evars?with_classes?flagsh=Proofview.Goal.enterbeginfungl->letclenv=connect_hint_clenvhglinClenv.res_pf?with_evars?with_classes?flagsclenvend