123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenCAstopenNamesopenNameopsopenGlob_termopenEvar_kinds(* Untyped intermediate terms, after ASTs and before constr. *)letcases_pattern_locc=c.CAst.locletalias_of_patpat=DAst.with_val(function|PatVarname->name|PatCstr(_,_,name)->name)patletset_pat_aliasid=DAst.map(function|PatVarAnonymous->PatVar(Nameid)|PatCstr(cstr,patl,Anonymous)->PatCstr(cstr,patl,Nameid)|pat->assertfalse)letcases_predicate_namestml=List.flatten(List.map(function|(tm,(na,None))->[na]|(tm,(na,Some{v=(_,nal)}))->na::nal)tml)letmkGApp?locpl=DAst.make?loc@@matchDAst.getpwith|GApp(f,l')->GApp(f,l'@l)|_->GApp(p,l)letmap_glob_decl_left_to_rightf(na,r,k,obd,ty)=letcomp1=Option.mapfobdinletcomp2=ftyin(na,r,k,comp1,comp2)letglob_qvar_eqg1g2=matchg1,g2with|GLocalQVarna1,GLocalQVarna2->CAst.eqName.equalna1na2|GQVarq1,GQVarq2->Sorts.QVar.equalq1q2|GRawQVarq1,GRawQVarq2->Sorts.QVar.equalq1q2|(GLocalQVar_|GQVar_|GRawQVar_),_->falseletglob_quality_eqg1g2=matchg1,g2with|GQConstantq1,GQConstantq2->Sorts.Quality.Constants.equalq1q2|GQualVarq1,GQualVarq2->glob_qvar_eqq1q2|(GQConstant_|GQualVar_),_->falseletglob_sort_name_eqg1g2=matchg1,g2with|GSProp,GSProp|GProp,GProp|GSet,GSet->true|GUnivu1,GUnivu2->Univ.Level.equalu1u2|GLocalUnivu1,GLocalUnivu2->lident_equ1u2|GRawUnivu1,GRawUnivu2->Univ.Level.equalu1u2|(GSProp|GProp|GSet|GUniv_|GLocalUniv_|GRawUniv_),_->falseexceptionComplexSortletglob_Type_sort=None,UAnonymous{rigid=UnivRigid}letglob_SProp_sort=None,UNamed[GSProp,0]letglob_Prop_sort=None,UNamed[GProp,0]letglob_Set_sort=None,UNamed[GSet,0]letmap_glob_sort_genf=function|UNamedl->UNamed(fl)|UAnonymous_asx->xletglob_sort_gen_eqfu1u2=matchu1,u2with|UAnonymous{rigid=r1},UAnonymous{rigid=r2}->r1=r2|UNamedl1,UNamedl2->fl1l2|(UNamed_|UAnonymous_),_->falseletglob_sort_eq(q1,l1)(q2,l2)=Option.equalglob_qvar_eqq1q2&&glob_sort_gen_eq(List.equal(fun(x,m)(y,n)->glob_sort_name_eqxy&&Int.equalmn))l1l2letglob_sort_familys=letopenSortsinifglob_sort_eqsglob_Type_sortthenInTypeelsematchswith|None,UNamed[s,0]->beginmatchswith|GSProp->InSProp|GProp->InProp|GSet->InSet|GUniv_|GLocalUniv_|GRawUniv_->raiseComplexSortend|_->raiseComplexSortletglob_level_equ1u2=glob_sort_gen_eqglob_sort_name_equ1u2letinstance_eq(q1,u1)(q2,u2)=List.equalglob_quality_eqq1q2&&List.equalglob_level_equ1u2letbinding_kind_eqbk1bk2=matchbk1,bk2with|Explicit,Explicit->true|NonMaxImplicit,NonMaxImplicit->true|MaxImplicit,MaxImplicit->true|(Explicit|NonMaxImplicit|MaxImplicit),_->falseletglob_relevance_eqab=matcha,bwith|GRelevant,GRelevant|GIrrelevant,GIrrelevant->true|GRelevanceVarq1,GRelevanceVarq2->glob_qvar_eqq1q2|(GRelevant|GIrrelevant|GRelevanceVar_),_->falseletrelevance_info_eq=Option.equalglob_relevance_eqletcase_style_eqs1s2=letopenConstrinmatchs1,s2with|LetStyle,LetStyle->true|IfStyle,IfStyle->true|LetPatternStyle,LetPatternStyle->true|MatchStyle,MatchStyle->true|RegularStyle,RegularStyle->true|(LetStyle|IfStyle|LetPatternStyle|MatchStyle|RegularStyle),_->falseletrecmk_cases_pattern_eqgp1p2=matchDAst.getp1,DAst.getp2with|PatVarna1,PatVarna2->gna1na2|PatCstr(c1,pl1,na1),PatCstr(c2,pl2,na2)->Construct.CanOrd.equalc1c2&&List.equal(mk_cases_pattern_eqg)pl1pl2&&Name.equalna1na2|(PatVar_|PatCstr_),_->falseletcast_kind_eqt1t2=letopenConstrinmatcht1,t2with|DEFAULTcast,DEFAULTcast|VMcast,VMcast|NATIVEcast,NATIVEcast->true|(DEFAULTcast|VMcast|NATIVEcast),_->falseletmatching_var_kind_eqk1k2=matchk1,k2with|FirstOrderPatVarido1,FirstOrderPatVarido2->Id.equalido1ido2|SecondOrderPatVarid1,SecondOrderPatVarid2->Id.equalid1id2|(FirstOrderPatVar_|SecondOrderPatVar_),_->falselettomatch_tuple_eqf(c1,p1)(c2,p2)=leteqp{CAst.v=(i1,na1)}{CAst.v=(i2,na2)}=Ind.CanOrd.equali1i2&&List.equalName.equalna1na2inleteq_pred(n1,o1)(n2,o2)=Name.equaln1n2&&Option.equaleqpo1o2infc1c2&&eq_predp1p2andcases_clause_eqfg{CAst.v=(id1,p1,c1)}{CAst.v=(id2,p2,c2)}=(* In principle, id1 and id2 canonically derive from p1 and p2 *)List.equal(mk_cases_pattern_eqg)p1p2&&fc1c2letglob_decl_eqf(na1,r1,bk1,c1,t1)(na2,r2,bk2,c2,t2)=Name.equalna1na2&&relevance_info_eqr1r2&&binding_kind_eqbk1bk2&&Option.equalfc1c2&&ft1t2letfix_kind_eqk1k2=matchk1,k2with|GFix(a1,i1),GFix(a2,i2)->Int.equali1i2&&Array.equal(Option.equalInt.equal)a1a2|GCoFixi1,GCoFixi2->Int.equali1i2|(GFix_|GCoFix_),_->falseletevar_instance_eqf(x1,c1)(x2,c2)=Id.equalx1.CAst.vx2.CAst.v&&fc1c2letmk_glob_constr_eqfgc1c2=matchDAst.getc1,DAst.getc2with|GRef(gr1,u1),GRef(gr2,u2)->GlobRef.CanOrd.equalgr1gr2&&Option.equalinstance_equ1u2|GVarid1,GVarid2->Id.equalid1id2|GEvar(id1,arg1),GEvar(id2,arg2)->Id.equalid1.CAst.vid2.CAst.v&&List.equal(evar_instance_eqf)arg1arg2|GPatVark1,GPatVark2->matching_var_kind_eqk1k2|GApp(f1,arg1),GApp(f2,arg2)->ff1f2&&List.equalfarg1arg2|GLambda(na1,r1,bk1,t1,c1),GLambda(na2,r2,bk2,t2,c2)->gna1na2(Somet1)(Somet2)&&relevance_info_eqr1r2&&binding_kind_eqbk1bk2&&ft1t2&&fc1c2|GProd(na1,r1,bk1,t1,c1),GProd(na2,r2,bk2,t2,c2)->gna1na2(Somet1)(Somet2)&&relevance_info_eqr1r2&&binding_kind_eqbk1bk2&&ft1t2&&fc1c2|GLetIn(na1,r1,b1,t1,c1),GLetIn(na2,r2,b2,t2,c2)->gna1na2t1t2&&relevance_info_eqr1r2&&fb1b2&&Option.equalft1t2&&fc1c2|GCases(st1,c1,tp1,cl1),GCases(st2,c2,tp2,cl2)->case_style_eqst1st2&&Option.equalfc1c2&&List.equal(tomatch_tuple_eqf)tp1tp2&&List.equal(cases_clause_eqf(funna1na2->gna1na2NoneNone))cl1cl2|GLetTuple(na1,(n1,p1),c1,t1),GLetTuple(na2,(n2,p2),c2,t2)->List.equal(funna1na2->gna1na2NoneNone)na1na2&&gn1n2NoneNone&&Option.equalfp1p2&&fc1c2&&ft1t2|GIf(m1,(pat1,p1),c1,t1),GIf(m2,(pat2,p2),c2,t2)->fm1m2&&gpat1pat2NoneNone&&Option.equalfp1p2&&fc1c2&&ft1t2|GRec(kn1,id1,decl1,t1,c1),GRec(kn2,id2,decl2,t2,c2)->fix_kind_eqkn1kn2&&Array.equalId.equalid1id2&&Array.equal(funl1l2->List.equal(glob_decl_eqf)l1l2)decl1decl2&&Array.equalfc1c2&&Array.equalft1t2|GSorts1,GSorts2->glob_sort_eqs1s2|GHole(_kn1),GHole(_kn2)->true(* this deserves a FIXME *)|GGenarggn1,GGenarggn2->gn1==gn2(* Only thing sensible *)|GCast(c1,k1,t1),GCast(c2,k2,t2)->fc1c2&&Option.equalcast_kind_eqk1k2&&ft1t2|GProj((cst1,u1),args1,c1),GProj((cst2,u2),args2,c2)->GlobRef.(CanOrd.equal(ConstRefcst1)(ConstRefcst2))&&Option.equalinstance_equ1u2&&List.equalfargs1args2&&fc1c2|GInti1,GInti2->Uint63.equali1i2|GFloatf1,GFloatf2->Float64.equalf1f2|GStrings1,GStrings2->Pstring.equals1s2|GArray(u1,t1,def1,ty1),GArray(u2,t2,def2,ty2)->Array.equalft1t2&&fdef1def2&&fty1ty2&&Option.equalinstance_equ1u2|(GRef_|GVar_|GEvar_|GPatVar_|GApp_|GLambda_|GProd_|GLetIn_|GCases_|GLetTuple_|GIf_|GRec_|GSort_|GHole_|GGenarg_|GCast_|GProj_|GInt_|GFloat_|GString_|GArray_),_->falseletrecglob_constr_eqc=mk_glob_constr_eqglob_constr_eq(funna1na2__->Name.equalna1na2)cletcases_pattern_eqc=mk_cases_pattern_eqName.equalcletrecmap_case_pattern_bindersf=DAst.map(function|PatVarnaasx->letr=fnainifr==nathenxelsePatVarr|PatCstr(c,ps,na)asx->letrna=fnainletrps=CList.Smart.map(funp->map_case_pattern_bindersfp)psinifrna==na&&rps==psthenxelsePatCstr(c,rps,rna))letmap_glob_constr_left_to_right_with_namesfg=DAst.map(function|GApp(g,args)->letcomp1=fginletcomp2=Util.List.map_leftfargsinGApp(comp1,comp2)|GLambda(na,r,bk,ty,c)->letcomp1=ftyinletcomp2=fcinGLambda(gna,r,bk,comp1,comp2)|GProd(na,r,bk,ty,c)->letcomp1=ftyinletcomp2=fcinGProd(gna,r,bk,comp1,comp2)|GLetIn(na,r,b,t,c)->letcomp1=fbinletcompt=Option.mapftinletcomp2=fcinGLetIn(gna,r,comp1,compt,comp2)|GCases(sty,rtntypopt,tml,pl)->letcomp1=Option.mapfrtntypoptinletcomp2=Util.List.map_left(fun(tm,(x,indxl))->(ftm,(gx,Option.map(CAst.map(fun(ind,xl)->(ind,List.mapgxl)))indxl)))tmlinletcomp3=Util.List.map_left(CAst.map(fun(idl,p,c)->(List.map(funid->Name.get_id(g(Nameid)))idl,List.map(map_case_pattern_bindersg)p,fc)))plinGCases(sty,comp1,comp2,comp3)|GLetTuple(nal,(na,po),b,c)->letcomp1=Option.mapfpoinletcomp2=fbinletcomp3=fcinGLetTuple(List.mapgnal,(gna,comp1),comp2,comp3)|GIf(c,(na,po),b1,b2)->letcomp1=Option.mapfpoinletcomp2=fb1inletcomp3=fb2inGIf(fc,(gna,comp1),comp2,comp3)|GRec(fk,idl,bl,tyl,bv)->letcomp1=Array.map(Util.List.map_left(map_glob_decl_left_to_rightf))blinletcomp2=Array.mapftylinletcomp3=Array.mapfbvinletgid=Name.get_id(g(Nameid))inGRec(fk,Array.mapgidl,comp1,comp2,comp3)|GCast(c,k,t)->letc=fcinlett=ftinGCast(c,k,t)|GProj(p,args,c)->letcomp1=Util.List.map_leftfargsinletcomp2=fcinGProj(p,comp1,comp2)|GArray(u,t,def,ty)->letcomp1=Array.map_leftftinletcomp2=fdefinletcomp3=ftyinGArray(u,comp1,comp2,comp3)|(GVar_|GSort_|GHole_|GGenarg_|GRef_|GEvar_|GPatVar_|GInt_|GFloat_|GString_)asx->x)letmap_glob_constr_left_to_rightf=map_glob_constr_left_to_right_with_namesf(funna->na)letmap_glob_constr=map_glob_constr_left_to_rightletfold_return_typefacc(na,tyopt)=Option.fold_leftfacctyoptletfold_glob_constrfacc=DAst.with_val(function|GVar_->acc|GApp(c,args)->List.fold_leftf(faccc)args|GLambda(_,_,_,b,c)|GProd(_,_,_,b,c)->f(faccb)c|GLetIn(_,_,b,t,c)->f(Option.fold_leftf(faccb)t)c|GCases(_,rtntypopt,tml,pl)->letfold_patternacc{CAst.v=(idl,p,c)}=facccinList.fold_leftfold_pattern(List.fold_leftf(Option.fold_leftfaccrtntypopt)(List.mapfsttml))pl|GLetTuple(_,rtntyp,b,c)->f(f(fold_return_typefaccrtntyp)b)c|GIf(c,rtntyp,b1,b2)->f(f(f(fold_return_typefaccrtntyp)c)b1)b2|GRec(_,_,bl,tyl,bv)->letacc=Array.fold_left(List.fold_left(funacc(_,_,_,bbd,bty)->f(Option.fold_leftfaccbbd)bty))accblinArray.fold_leftf(Array.fold_leftfacctyl)bv|GCast(c,k,t)->letacc=facctinfaccc|GProj(p,args,c)->f(List.fold_leftfaccargs)c|GArray(_u,t,def,ty)->f(f(Array.fold_leftfacct)def)ty|(GSort_|GHole_|GGenarg_|GRef_|GEvar_|GPatVar_|GInt_|GFloat_|GString_)->acc)letfold_return_type_with_bindersfgvacc(na,tyopt)=(* eta expansion is important if g has effects, eg bound_glob_vars below, see #11959 *)Option.fold_left(funacc->f(Name.fold_rightgnav)acc)acctyoptletfold_glob_constr_with_bindersgfvacc=DAst.(with_val(function|GVar_->acc|GApp(c,args)->List.fold_left(fv)(fvaccc)args|GLambda(na,_,_,b,c)|GProd(na,_,_,b,c)->f(Name.fold_rightgnav)(fvaccb)c|GLetIn(na,_,b,t,c)->f(Name.fold_rightgnav)(Option.fold_left(fv)(fvaccb)t)c|GCases(_,rtntypopt,tml,pl)->letfold_patternacc{v=(idl,p,c)}=f(List.fold_rightgidlv)acccinletfold_tomatch(v',acc)(tm,(na,onal))=((ifrtntypopt=Nonethenv'elseOption.fold_left(funv''{v=(_,nal)}->List.fold_right(Name.fold_rightg)nalv'')(Name.fold_rightgnav')onal),fvacctm)inlet(v',acc)=List.fold_leftfold_tomatch(v,acc)tmlinletacc=Option.fold_left(fv')accrtntypoptinList.fold_leftfold_patternaccpl|GLetTuple(nal,rtntyp,b,c)->f(List.fold_right(Name.fold_rightg)nalv)(fv(fold_return_type_with_bindersfgvaccrtntyp)b)c|GIf(c,rtntyp,b1,b2)->fv(fv(fv(fold_return_type_with_bindersfgvaccrtntyp)c)b1)b2|GRec(_,idl,bll,tyl,bv)->letv'=Array.fold_rightgidlvinletf'iaccfid=letv,acc=List.fold_left(fun(v,acc)(na,_,_,bbd,bty)->(Name.fold_rightgnav,fv(Option.fold_left(fv)accbbd)bty))(v,acc)bll.(i)infv'(fvacctyl.(i))(bv.(i))inArray.fold_left_if'accidl|GCast(c,k,t)->letacc=fvacctinfvaccc|GProj(p,args,c)->fv(List.fold_left(fv)accargs)c|GArray(_u,t,def,ty)->fv(fv(Array.fold_left(fv)acct)def)ty|(GSort_|GHole_|GGenarg_|GRef_|GEvar_|GPatVar_|GInt_|GFloat_|GString_)->acc))letiter_glob_constrf=fold_glob_constr(fun()->f)()letoccur_glob_constrid=letrecoccurbarredaccc=matchDAst.getcwith|GVarid'->Id.equalidid'|_->(* [g] looks if [id] appears in a binding position, in which
case, we don't have to look in the corresponding subterm *)letgid'barred=barred||Id.equalidid'inletfbarredaccc=acc||notbarred&&occurfalseacccinfold_glob_constr_with_bindersgfbarredacccinoccurfalsefalseletfree_glob_vars=letrecvarsboundvsc=matchDAst.getcwith|GVarid'->ifId.Set.memid'boundthenvselseId.Set.addid'vs|_->fold_glob_constr_with_bindersId.Set.addvarsboundvscinfunrt->letvs=varsId.Set.emptyId.Set.emptyrtinvsletglob_visible_short_qualidc=letrecauxaccc=matchDAst.getcwith|GRef(c,_)->letqualid=Nametab.shortest_qualid_of_globalId.Set.emptycinletdir,id=Libnames.repr_qualidqualidinifDirPath.is_emptydirthenId.Set.addidaccelseacc|_->fold_glob_constrauxacccinauxId.Set.emptycletwarn_variable_collision=letopenPpinCWarnings.create~name:"variable-collision"~category:CWarnings.CoreCategories.ltac(funname->strbrk"Collision between bound variables of name "++Id.printname)letadd_and_check_identidset=ifId.Set.memidsetthenwarn_variable_collisionid;Id.Set.addidsetletbound_glob_vars=letrecvarsbound=fold_glob_constr_with_binders(funid()->bound:=add_and_check_identid!bound)(fun()()->varsbound)()()infunrt->letbound=refId.Set.emptyinvarsboundrt;!bound(** Mapping of names in binders *)(* spiwack: I used a smart-style kind of mapping here, because the
operation will be the identity almost all of the time (with any
term outside of Ltac to begin with). But to be honest, there would
probably be no significant penalty in doing reallocation as
pattern-matching expressions are usually rather small. *)letmap_inpattern_bindersf({loc;v=(id,nal)}asx)=letr=CList.Smart.mapfnalinifr==nalthenxelseCAst.make?loc(id,r)letmap_tomatch_bindersf((c,(na,inp))asx):tomatch_tuple=letr=Option.Smart.map(funp->map_inpattern_bindersfp)inpinifr==inpthenxelsec,(fna,r)letmap_cases_branch_bindersf({CAst.loc;v=(il,cll,rhs)}asx):cases_clause=(* spiwack: not sure if I must do something with the list of idents.
It is intended to be a superset of the free variable of the
right-hand side, if I understand correctly. But I'm not sure when
or how they are used. *)letr=List.Smart.map(funcl->map_case_pattern_bindersfcl)cllinifr==cllthenxelseCAst.make?loc(il,r,rhs)letmap_pattern_bindersftomatchbranches=CList.Smart.map(funtm->map_tomatch_bindersftm)tomatch,CList.Smart.map(funbr->map_cases_branch_bindersfbr)branches(** /mapping of names in binders *)letmap_tomatchf(c,pp):tomatch_tuple=fc,ppletmap_cases_branchf=CAst.map(fun(il,cll,rhs)->(il,cll,frhs))letmap_patternftomatchbranches=List.map(funtm->map_tomatchftm)tomatch,List.map(funbr->map_cases_branchfbr)branchesletloc_of_glob_constrc=c.CAst.loc(**********************************************************************)(* Alpha-renaming *)exceptionUnsoundRenamingletcollide_idlid=List.exists(fun(id',id'')->Id.equalidid'||Id.equalidid'')llettest_idlid=ifcollide_idlidthenraiseUnsoundRenaminglettest_nalna=Name.iter(test_idl)naletupdate_substnal=letin_rangeidl=List.exists(fun(_,id')->Id.equalidid')linletl'=Name.fold_rightId.List.remove_assocnalinName.fold_right(funid_->ifin_rangeidl'thenletid'=Namegen.next_ident_away_fromid(funid'->in_rangeid'l')inNameid',(id,id')::lelsena,l)na(na,l)letrename_varlid=tryletid'=Id.List.associdlin(* Check that no other earlier binding hides the one found *)let_,(id'',_)=List.extract_first(fun(_,id)->Id.equalidid')linifId.equalidid''thenid'elseraiseUnsoundRenamingwithNot_found->ifList.exists(fun(_,id')->Id.equalidid')lthenraiseUnsoundRenamingelseidletforcec=DAst.make?loc:c.CAst.loc(DAst.getc)letrecrename_glob_varslc=force@@DAst.map_with_loc(fun?loc->function|GVaridasr->letid'=rename_varlidinifid==id'thenrelseGVarid'|GRef(GlobRef.VarRefid,_)asr->ifList.exists(fun(_,id')->Id.equalidid')lthenraiseUnsoundRenamingelser|GProd(na,r,bk,t,c)->letna',l'=update_substnalinGProd(na',r,bk,rename_glob_varslt,rename_glob_varsl'c)|GLambda(na,r,bk,t,c)->letna',l'=update_substnalinGLambda(na',r,bk,rename_glob_varslt,rename_glob_varsl'c)|GLetIn(na,r,b,t,c)->letna',l'=update_substnalinGLetIn(na',r,rename_glob_varslb,Option.map(rename_glob_varsl)t,rename_glob_varsl'c)(* Lazy strategy: we fail if a collision with renaming occurs, rather than renaming further *)|GCases(ci,po,tomatchl,cls)->lettest_pred_pat(na,ino)=test_nalna;Option.iter(fun{v=(_,nal)}->List.iter(test_nal)nal)inoinlettest_clauseidl=List.iter(test_idl)idlinletpo=Option.map(rename_glob_varsl)poinlettomatchl=Util.List.map_left(fun(tm,x)->test_pred_patx;(rename_glob_varsltm,x))tomatchlinletcls=Util.List.map_left(CAst.map(fun(idl,p,c)->test_clauseidl;(idl,p,rename_glob_varslc)))clsinGCases(ci,po,tomatchl,cls)|GLetTuple(nal,(na,po),c,b)->List.iter(test_nal)(na::nal);GLetTuple(nal,(na,Option.map(rename_glob_varsl)po),rename_glob_varslc,rename_glob_varslb)|GIf(c,(na,po),b1,b2)->test_nalna;GIf(rename_glob_varslc,(na,Option.map(rename_glob_varsl)po),rename_glob_varslb1,rename_glob_varslb2)|GRec(k,idl,decls,bs,ts)->Array.iter(test_idl)idl;GRec(k,idl,Array.map(List.map(fun(na,r,k,bbd,bty)->test_nalna;(na,r,k,Option.map(rename_glob_varsl)bbd,rename_glob_varslbty)))decls,Array.map(rename_glob_varsl)bs,Array.map(rename_glob_varsl)ts)|_->DAst.get(map_glob_constr(rename_glob_varsl)c))c(**********************************************************************)(* Conversion from glob_constr to cases pattern, if possible *)letis_gvaridc=matchDAst.getcwith|GVarid'->Id.equalidid'|_->falseletreccases_pattern_of_glob_constrenvnac=(* Forcing evaluation to ensure that the possible raising of
Not_found is not delayed *)letc=DAst.forcecinDAst.map(function|GVarid->beginmatchnawith|Name_->(* Unable to manage the presence of both an alias and a variable *)raiseNot_found|Anonymous->PatVar(Nameid)end|GHole_->PatVarna|GGenarg_->PatVarna(* XXX does this really make sense? *)|GRef(GlobRef.VarRefid,_)->PatVar(Nameid)|GRef(GlobRef.ConstructRefcstr,_)->PatCstr(cstr,[],na)|GApp(c,l)->beginmatchDAst.getcwith|GRef(GlobRef.ConstructRefcstr,_)->letnparams=Inductiveops.inductive_nparamsenv(fstcstr)inlet_,l=List.chopnparamslinPatCstr(cstr,List.map(cases_pattern_of_glob_constrenvAnonymous)l,na)|_->raiseNot_foundend|GLetIn(Nameidasna',_,b,None,e)whenis_gvaride&&na=Anonymous->(* A canonical encoding of aliases *)DAst.get(cases_pattern_of_glob_constrenvna'b)|_->raiseNot_found)copenDeclarationsopenContext(* Keep only patterns which are not bound to a local definitions *)letdrop_local_defsparamsdeclsargs=letdecls=List.skipn(Rel.lengthparams)(List.revdecls)inletrecauxdeclsargs=matchdecls,argswith|[],[]->[]|Rel.Declaration.LocalDef_::decls,pat::args->beginmatchDAst.getpatwith|PatVarAnonymous->auxdeclsargs|_->raiseNot_found(* The pattern is used, one cannot drop it *)end|Rel.Declaration.LocalAssum_::decls,a::args->a::auxdeclsargs|_->assertfalseinauxdeclsargsletadd_patterns_for_params_remove_local_defsenv(ind,j)l=let(mib,mip)=Inductive.lookup_mind_specifenvindinletnparams=mib.Declarations.mind_nparamsinletl=ifmip.mind_consnrealdecls.(j-1)=mip.mind_consnrealargs.(j-1)then(* Optimisation *)lelselet(ctx,_)=mip.mind_nf_lc.(j-1)indrop_local_defsmib.mind_params_ctxtctxlinUtil.List.addnnparams(DAst.make@@PatVarAnonymous)lletadd_alias?locnac=matchnawith|Anonymous->c|Nameid->GLetIn(na,None,DAst.make?locc,None,DAst.make?loc(GVarid))(* Turn a closed cases pattern into a glob_constr *)letrecglob_constr_of_cases_pattern_auxenvisclosedx=DAst.map_with_loc(fun?loc->function|PatCstr(cstr,[],na)->add_alias?locna(GRef(GlobRef.ConstructRefcstr,None))|PatCstr(cstr,l,na)->letref=DAst.make?loc@@GRef(GlobRef.ConstructRefcstr,None)inletl=add_patterns_for_params_remove_local_defsenvcstrlinadd_alias?locna(GApp(ref,List.map(glob_constr_of_cases_pattern_auxenvisclosed)l))|PatVar(Nameid)whennotisclosed->GVarid|PatVarAnonymouswhennotisclosed->GHole(GQuestionMark{Evar_kinds.default_question_markwithEvar_kinds.qm_obligation=Definefalse;})|_->raiseNot_found)xletglob_constr_of_closed_cases_patternenvp=matchDAst.getpwith|PatCstr(cstr,l,na)->letloc=p.CAst.locinna,glob_constr_of_cases_pattern_auxenvtrue(DAst.make?loc@@PatCstr(cstr,l,Anonymous))|_->raiseNot_foundletglob_constr_of_cases_patternenvp=glob_constr_of_cases_pattern_auxenvfalsepletkind_of_glob_kind=function|GImplicitArg(gr,p,b)->ImplicitArg(gr,p,b)|GBinderTypena->BinderTypena|GNamedHole(fresh,id)->NamedHoleid|GQuestionMarkqm->QuestionMarkqm|GCasesType->CasesTypefalse|GInternalHole->InternalHole|GImpossibleCase->ImpossibleCaseletnaming_of_glob_kind=function|GNamedHole(true,id)->Namegen.IntroFreshid|GNamedHole(false,id)->Namegen.IntroIdentifierid|_->Namegen.IntroAnonymous(* This has to be in some file... *)openLtac_pretypeletempty_lvar:ltac_var_map={ltac_constrs=Id.Map.empty;ltac_uconstrs=Id.Map.empty;ltac_idents=Id.Map.empty;ltac_genargs=Id.Map.empty;}