123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668(************************************************************************)(* * 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) *)(************************************************************************)openPpopenUtilopenNamesopenNameopsopenLibnamesopenGlob_termopenNotationexternopenConstrexpr(***********)(* Universes *)letexpr_Type_sort=None,UAnonymous{rigid=UnivRigid}letexpr_SProp_sort=None,UNamed[CSProp,0]letexpr_Prop_sort=None,UNamed[CProp,0]letexpr_Set_sort=None,UNamed[CSet,0]letsort_name_expr_eqc1c2=matchc1,c2with|CSProp,CSProp|CProp,CProp|CSet,CSet->true|CTypeq1,CTypeq2->Libnames.qualid_eqq1q2|CRawTypeu1,CRawTypeu2->Univ.Level.equalu1u2|(CSProp|CProp|CSet|CType_|CRawType_),_->falseletqvar_expr_eqc1c2=matchc1,c2with|CQVarq1,CQVarq2->Libnames.qualid_eqq1q2|CQAnon_,CQAnon_->true|CRawQVarq1,CRawQVarq2->Sorts.QVar.equalq1q2|(CQVar_|CQAnon_|CRawQVar_),_->falseletrelevance_expr_eqab=matcha,bwith|CRelevant,CRelevant|CIrrelevant,CIrrelevant->true|CRelevanceVarq1,CRelevanceVarq2->qvar_expr_eqq1q2|(CRelevant|CIrrelevant|CRelevanceVar_),_->falseletrelevance_info_expr_eq=Option.equalrelevance_expr_eqletuniv_level_expr_equ1u2=Glob_ops.glob_sort_gen_eqsort_name_expr_equ1u2letsort_expr_eq(q1,l1)(q2,l2)=Option.equalqvar_expr_eqq1q2&&Glob_ops.glob_sort_gen_eq(List.equal(fun(x,m)(y,n)->sort_name_expr_eqxy&&Int.equalmn))l1l2(***********************)(* For binders parsing *)letbinder_kind_eqb1b2=matchb1,b2with|Defaultbk1,Defaultbk2->Glob_ops.binding_kind_eqbk1bk2|Generalized(ck1,b1),Generalized(ck2,b2)->Glob_ops.binding_kind_eqck1ck2&&(ifb1thenb2elsenotb2)|(Default_|Generalized_),_->falseletdefault_binder_kind=DefaultExplicitletnames_of_local_assumsbl=List.flatten(List.map(functionCLocalAssum(l,_,_,_)->l|_->[])bl)letnames_of_local_bindersbl=List.flatten(List.map(functionCLocalAssum(l,_,_,_)->l|CLocalDef(l,_,_,_)->[l]|CLocalPattern_->assertfalse)bl)(**********************************************************************)(* Functions on constr_expr *)(* Note: redundant Number representations, such as -0 and +0 (and others),
are considered different here. *)letprim_token_eqt1t2=matcht1,t2with|Numbern1,Numbern2->NumTok.Signed.equaln1n2|Strings1,Strings2->String.equals1s2|(Number_|String_),_->falseletexplicitation_eqpos1pos2=matchpos1,pos2with|ExplByNameid1,ExplByNameid2->Id.equalid1id2|ExplByPosn1,ExplByPosn2->Int.equaln1n2|(ExplByName_|ExplByPos_),_->falseletreccases_pattern_expr_eqp1p2=ifCAst.(p1.v==p2.v)thentrueelsematchCAst.(p1.v,p2.v)with|CPatAlias(a1,i1),CPatAlias(a2,i2)->CAst.eqName.equali1i2&&cases_pattern_expr_eqa1a2|CPatCstr(c1,a1,b1),CPatCstr(c2,a2,b2)->qualid_eqc1c2&&Option.equal(List.equalcases_pattern_expr_eq)a1a2&&List.equalcases_pattern_expr_eqb1b2|CPatAtom(r1),CPatAtom(r2)->Option.equalqualid_eqr1r2|CPatOra1,CPatOra2->List.equalcases_pattern_expr_eqa1a2|CPatNotation(inscope1,n1,s1,l1),CPatNotation(inscope2,n2,s2,l2)->Option.equalnotation_with_optional_scope_eqinscope1inscope2&¬ation_eqn1n2&&cases_pattern_notation_substitution_eqs1s2&&List.equalcases_pattern_expr_eql1l2|CPatPrimi1,CPatPrimi2->prim_token_eqi1i2|CPatRecordl1,CPatRecordl2->letequal(r1,e1)(r2,e2)=qualid_eqr1r2&&cases_pattern_expr_eqe1e2inList.equalequall1l2|CPatDelimiters(depth1,s1,e1),CPatDelimiters(depth2,s2,e2)->depth1=depth2&&String.equals1s2&&cases_pattern_expr_eqe1e2|_->falseandcases_pattern_notation_substitution_eq(s1,n1,b1)(s2,n2,b2)=List.equalcases_pattern_expr_eqs1s2&&List.equal(List.equalcases_pattern_expr_eq)n1n2&&List.equal(eq_paircases_pattern_expr_eqGlob_ops.binding_kind_eq)b1b2letkinded_cases_pattern_expr_eq(p1,bk1)(p2,bk2)=cases_pattern_expr_eqp1p2&&Glob_ops.binding_kind_eqbk1bk2leteq_universesu1u2=matchu1,u2with|None,None->true|Somel,Somel'->l=l'|_,_->false(* We use a functor to avoid passing the recursion all over the place *)moduleEqGen(A:sigvalconstr_expr_eq:constr_expr->constr_expr->boolend)=structopenAletargs_eq(a1,e1)(a2,e2)=Option.equal(CAst.eqexplicitation_eq)e1e2&&constr_expr_eqa1a2letcase_expr_eq(e1,n1,p1)(e2,n2,p2)=constr_expr_eqe1e2&&Option.equal(CAst.eqName.equal)n1n2&&Option.equalcases_pattern_expr_eqp1p2letbranch_expr_eq{CAst.v=(p1,e1)}{CAst.v=(p2,e2)}=List.equal(List.equalcases_pattern_expr_eq)p1p2&&constr_expr_eqe1e2letrecursion_order_expr_eq_rr1r2=matchr1,r2with|CStructReci1,CStructReci2->lident_eqi1i2|CWfRec(i1,e1),CWfRec(i2,e2)->constr_expr_eqe1e2|CMeasureRec(i1,e1,o1),CMeasureRec(i2,e2,o2)->Option.equallident_eqi1i2&&constr_expr_eqe1e2&&Option.equalconstr_expr_eqo1o2|_->falseletrecursion_order_expr_eqr1r2=CAst.eqrecursion_order_expr_eq_rr1r2letlocal_binder_eql1l2=matchl1,l2with|CLocalDef(n1,_,e1,t1),CLocalDef(n2,_,e2,t2)->CAst.eqName.equaln1n2&&constr_expr_eqe1e2&&Option.equalconstr_expr_eqt1t2|CLocalAssum(n1,_,_,e1),CLocalAssum(n2,_,_,e2)->(* Don't care about the metadata *)List.equal(CAst.eqName.equal)n1n2&&constr_expr_eqe1e2|_->falseletfix_expr_eq(id1,_,r1,bl1,a1,b1)(id2,_,r2,bl2,a2,b2)=(lident_eqid1id2)&&Option.equalrecursion_order_expr_eqr1r2&&List.equallocal_binder_eqbl1bl2&&constr_expr_eqa1a2&&constr_expr_eqb1b2letcofix_expr_eq(id1,_,bl1,a1,b1)(id2,_,bl2,a2,b2)=(lident_eqid1id2)&&List.equallocal_binder_eqbl1bl2&&constr_expr_eqa1a2&&constr_expr_eqb1b2letconstr_notation_substitution_eq(e1,el1,b1,bl1)(e2,el2,b2,bl2)=List.equalconstr_expr_eqe1e2&&List.equal(List.equalconstr_expr_eq)el1el2&&List.equalkinded_cases_pattern_expr_eqb1b2&&List.equal(List.equallocal_binder_eq)bl1bl2letinstance_eq(x1,c1)(x2,c2)=Id.equalx1.CAst.vx2.CAst.v&&constr_expr_eqc1c2letconstr_expr_eqe1e2=ifCAst.(e1.v==e2.v)thentrueelsematchCAst.(e1.v,e2.v)with|CRef(r1,u1),CRef(r2,u2)->qualid_eqr1r2&&eq_universesu1u2|CFix(id1,fl1),CFix(id2,fl2)->lident_eqid1id2&&List.equalfix_expr_eqfl1fl2|CCoFix(id1,fl1),CCoFix(id2,fl2)->lident_eqid1id2&&List.equalcofix_expr_eqfl1fl2|CProdN(bl1,a1),CProdN(bl2,a2)->List.equallocal_binder_eqbl1bl2&&constr_expr_eqa1a2|CLambdaN(bl1,a1),CLambdaN(bl2,a2)->List.equallocal_binder_eqbl1bl2&&constr_expr_eqa1a2|CLetIn(na1,a1,t1,b1),CLetIn(na2,a2,t2,b2)->CAst.eqName.equalna1na2&&constr_expr_eqa1a2&&Option.equalconstr_expr_eqt1t2&&constr_expr_eqb1b2|CAppExpl((r1,u1),al1),CAppExpl((r2,u2),al2)->qualid_eqr1r2&&eq_universesu1u2&&List.equalconstr_expr_eqal1al2|CApp(e1,al1),CApp(e2,al2)->constr_expr_eqe1e2&&List.equalargs_eqal1al2|CProj(e1,(p1,u1),al1,c1),CProj(e2,(p2,u2),al2,c2)->e1=(e2:bool)&&qualid_eqp1p2&&eq_universesu1u2&&List.equalargs_eqal1al2&&constr_expr_eqc1c2|CRecordl1,CRecordl2->letfield_eq(r1,e1)(r2,e2)=qualid_eqr1r2&&constr_expr_eqe1e2inList.equalfield_eql1l2|CCases(_,r1,a1,brl1),CCases(_,r2,a2,brl2)->(* Don't care about the case_style *)Option.equalconstr_expr_eqr1r2&&List.equalcase_expr_eqa1a2&&List.equalbranch_expr_eqbrl1brl2|CLetTuple(n1,(m1,e1),t1,b1),CLetTuple(n2,(m2,e2),t2,b2)->List.equal(CAst.eqName.equal)n1n2&&Option.equal(CAst.eqName.equal)m1m2&&Option.equalconstr_expr_eqe1e2&&constr_expr_eqt1t2&&constr_expr_eqb1b2|CIf(e1,(n1,r1),t1,f1),CIf(e2,(n2,r2),t2,f2)->constr_expr_eqe1e2&&Option.equal(CAst.eqName.equal)n1n2&&Option.equalconstr_expr_eqr1r2&&constr_expr_eqt1t2&&constr_expr_eqf1f2|CHole_,CHole_->true|(CGenarg_|CGenargGlob_),(CGenarg_|CGenargGlob_)->true|CPatVari1,CPatVari2->Id.equali1i2|CEvar(id1,c1),CEvar(id2,c2)->Id.equalid1.CAst.vid2.CAst.v&&List.equalinstance_eqc1c2|CSorts1,CSorts2->sort_expr_eqs1s2|CCast(c1,k1,t1),CCast(c2,k2,t2)->constr_expr_eqc1c2&&Option.equalGlob_ops.cast_kind_eqk1k2&&constr_expr_eqt1t2|CNotation(inscope1,n1,s1),CNotation(inscope2,n2,s2)->Option.equalnotation_with_optional_scope_eqinscope1inscope2&¬ation_eqn1n2&&constr_notation_substitution_eqs1s2|CPrimi1,CPrimi2->prim_token_eqi1i2|CGeneralization(bk1,e1),CGeneralization(bk2,e2)->Glob_ops.binding_kind_eqbk1bk2&&constr_expr_eqe1e2|CDelimiters(depth1,s1,e1),CDelimiters(depth2,s2,e2)->depth1=depth2&&String.equals1s2&&constr_expr_eqe1e2|CArray(u1,t1,def1,ty1),CArray(u2,t2,def2,ty2)->Array.equalconstr_expr_eqt1t2&&constr_expr_eqdef1def2&&constr_expr_eqty1ty2&&eq_universesu1u2|(CRef_|CFix_|CCoFix_|CProdN_|CLambdaN_|CLetIn_|CAppExpl_|CApp_|CProj_|CRecord_|CCases_|CLetTuple_|CIf_|CHole_|CGenarg_|CGenargGlob_|CPatVar_|CEvar_|CSort_|CCast_|CNotation_|CPrim_|CGeneralization_|CDelimiters_|CArray_),_->falseendletconstr_expr_eq_geneq=letmoduleEq=EqGen(structletconstr_expr_eq=eqend)inEq.constr_expr_eqmoduleEq=EqGen(structletrecconstr_expr_eqc1c2=constr_expr_eq_genconstr_expr_eqc1c2end)includeEqletconstr_locc=CAst.(c.loc)letcases_pattern_expr_loccp=CAst.(cp.loc)letlocal_binder_loc=letopenCAstinfunction|CLocalAssum({loc}::_,_,_,t)|CLocalDef({loc},_,t,None)->Loc.merge_optloc(constr_loct)|CLocalDef({loc},_,b,Somet)->Loc.merge_optloc(Loc.merge_opt(constr_locb)(constr_loct))|CLocalAssum([],_,_,_)->assertfalse|CLocalPattern{loc}->locletlocal_binders_locbll=matchbllwith|[]->None|h::l->Loc.merge_opt(local_binder_loch)(local_binder_loc(List.lastbll))(** Folds and maps *)letis_constructorid=matchSmartlocate.global_of_extended_global(Nametab.locate_extended(qualid_of_identid))with|exceptionNot_found->false|None->false|Somegref->Globnames.isConstructRefgrefletreccases_pattern_fold_namesfhnaccpt=matchCAst.(pt.v)with|CPatRecordl->List.fold_left(funnacc(r,cp)->cases_pattern_fold_namesfhnacccp)naccl|CPatAlias(pat,{CAst.v=na})->Name.fold_right(funna(n,acc)->(fnan,acc))na(cases_pattern_fold_namesfhnaccpat)|CPatOr(patl)->List.fold_left(cases_pattern_fold_namesfh)naccpatl|CPatCstr(_,patl1,patl2)->List.fold_left(cases_pattern_fold_namesfh)(Option.fold_left(List.fold_left(cases_pattern_fold_namesfh))naccpatl1)patl2|CPatNotation(_,_,(patl,patll,binderl),patl')->List.fold_left(cases_pattern_fold_namesfh)(List.fold_left(cases_pattern_fold_namesfh)nacc(patl@List.flattenpatll@List.mapfstbinderl))patl'|CPatDelimiters(_,_,pat)->cases_pattern_fold_namesfhnaccpat|CPatAtom(Someqid)whenqualid_is_identqid&¬(is_constructor@@qualid_basenameqid)->let(n,acc)=naccin(f(qualid_basenameqid)n,acc)|CPatPrim_|CPatAtom_->nacc|CPatCast(p,t)->let(n,acc)=naccincases_pattern_fold_namesfh(n,hacct)pletids_of_pattern_listp=fst(List.fold_left(List.fold_left(cases_pattern_fold_namesId.Set.add(fun()_->())))(Id.Set.empty,())p)letids_of_cases_tomatchtms=List.fold_right(fun(_,ona,indnal)l->Option.fold_right(funtids->fst(cases_pattern_fold_namesId.Set.add(fun()_->())(ids,())t))indnal(Option.fold_right(CAst.with_val(Name.fold_rightId.Set.add))onal))tmsId.Set.emptyletrecfold_local_bindersgfnaccb=letopenCAstinfunction|CLocalAssum(nal,_,bk,t)::l->letnal=List.(map(fun{v}->v)nal)inletn'=List.fold_right(Name.fold_rightg)nalninfn(fold_local_bindersgfn'accbl)t|CLocalDef({v=na},_,c,t)::l->Option.fold_left(fn)(fn(fold_local_bindersgf(Name.fold_rightgnan)accbl)c)t|CLocalPatternpat::l->letn,acc=cases_pattern_fold_namesg(fn)(n,acc)patinfold_local_bindersgfnaccbl|[]->fnaccbletfold_constr_expr_with_bindersgfnacc=CAst.with_val(function|CAppExpl((_,_),l)->List.fold_left(fn)accl|CApp(t,l)->List.fold_left(fn)(fnacct)(List.mapfstl)|CProj(e,_,l,t)->fn(List.fold_left(fn)acc(List.mapfstl))t|CProdN(l,b)|CLambdaN(l,b)->fold_local_bindersgfnaccbl|CLetIn(na,a,t,b)->f(Name.fold_rightg(na.CAst.v)n)(Option.fold_left(fn)(fnacca)t)b|CCast(a,_,b)->fn(fnacca)b|CNotation(_,_,(l,ll,bl,bll))->(* The following is an approximation: we don't know exactly if
an ident is binding nor to which subterms bindings apply *)letacc=List.fold_left(fn)acc(l@List.flattenll)inList.fold_left(funaccbl->fold_local_bindersgfnacc(CAst.make@@CHole(None))bl)accbll|CGeneralization(_,c)->fnaccc|CDelimiters(_,_,a)->fnacca|CRecordl->List.fold_left(funacc(id,c)->fnaccc)accl|CCases(sty,rtnpo,al,bl)->letids=ids_of_cases_tomatchalinletacc=Option.fold_left(f(Id.Set.foldgidsn))accrtnpoinletacc=List.fold_left(fn)acc(List.map(fun(fst,_,_)->fst)al)inList.fold_right(fun{CAst.v=(patl,rhs)}acc->letids=ids_of_pattern_listpatlinf(Id.Set.foldgidsn)accrhs)blacc|CLetTuple(nal,(ona,po),b,c)->letn'=List.fold_right(CAst.with_val(Name.fold_rightg))nalninf(Option.fold_right(CAst.with_val(Name.fold_rightg))onan')(fnaccb)c|CIf(c,(ona,po),b1,b2)->letacc=fn(fn(fnaccb1)b2)cinOption.fold_left(f(Option.fold_right(CAst.with_val(Name.fold_rightg))onan))accpo|CFix(_,l)->letn'=List.fold_right(fun({CAst.v=id},_,_,_,_,_)->gid)lninList.fold_right(fun(_,_,ro,lb,t,c)acc->fold_local_bindersgfn'(fold_local_bindersgfnacctlb)clb)lacc|CCoFix(_,_)->Feedback.msg_warning(strbrk"Capture check in multiple binders not done");acc|CArray(_u,t,def,ty)->fn(fn(Array.fold_left(fn)acct)def)ty|CHole_|CGenarg_|CGenargGlob_|CEvar_|CPatVar_|CSort_|CPrim_|CRef_->acc)letfree_vars_of_constr_exprc=letrecauxbdvarsl=function|{CAst.v=CRef(qid,_)}whenqualid_is_identqid->letid=qualid_basenameqidinifId.List.memidbdvarsthenlelseId.Set.addidl|c->fold_constr_expr_with_binders(funal->a::l)auxbdvarslcinaux[]Id.Set.emptycletnames_of_constr_exprc=letvars=refId.Set.emptyinletrecaux()()=function|{CAst.v=CRef(qid,_)}whenqualid_is_identqid->letid=qualid_basenameqidinvars:=Id.Set.addid!vars|c->fold_constr_expr_with_binders(funa()->vars:=Id.Set.adda!vars)aux()()cinaux()()c;!varsletoccur_var_constr_expridc=Id.Set.memid(free_vars_of_constr_exprc)letrecfold_map_cases_patternfhacc(CAst.{v=pt;loc}asp)=matchptwith|CPatRecordl->letacc,l=List.fold_left_map(funacc(r,cp)->letacc,cp=fold_map_cases_patternfhacccpinacc,(r,cp))acclinacc,CAst.make?loc(CPatRecordl)|CPatAlias(pat,({CAst.v=na}aslna))->letacc,p=fold_map_cases_patternfhaccpatinletacc=Name.fold_rightfnaaccinacc,CAst.make?loc(CPatAlias(pat,lna))|CPatOrpatl->letacc,patl=List.fold_left_map(fold_map_cases_patternfh)accpatlinacc,CAst.make?loc(CPatOrpatl)|CPatCstr(c,patl1,patl2)->letacc,patl1=Option.fold_left_map(List.fold_left_map(fold_map_cases_patternfh))accpatl1inletacc,patl2=List.fold_left_map(fold_map_cases_patternfh)accpatl2inacc,CAst.make?loc(CPatCstr(c,patl1,patl2))|CPatNotation(sc,ntn,(patl,patll,binderl),patl')->letacc,patl=List.fold_left_map(fold_map_cases_patternfh)accpatlinletacc,patll=List.fold_left_map(List.fold_left_map(fold_map_cases_patternfh))accpatllinletacc,binderl'=List.fold_left_map(fold_fst(fold_map_cases_patternfh))accbinderlinletacc,patl'=List.fold_left_map(fold_map_cases_patternfh)accpatl'inacc,CAst.make?loc(CPatNotation(sc,ntn,(patl,patll,binderl'),patl'))|CPatDelimiters(depth,d,pat)->letacc,p=fold_map_cases_patternfhaccpatinacc,CAst.make?loc(CPatDelimiters(depth,d,pat))|CPatAtom(Someqid)whenqualid_is_identqid&¬(is_constructor@@qualid_basenameqid)->f(qualid_basenameqid)acc,p|CPatPrim_|CPatAtom_->(acc,p)|CPatCast(pat,t)->letacc,pat=fold_map_cases_patternfhaccpatinlett=hacctinacc,CAst.make?loc(CPatCast(pat,t))(* Used in correctness and interface *)letmap_bindergenal=List.fold_right(CAst.with_val(Name.fold_rightg))naleletfold_map_local_bindersfgebl=(* TODO: avoid variable capture in [t] by some [na] in [List.tl nal] *)letopenCAstinleth(e,bl)=functionCLocalAssum(nal,r,k,ty)->(map_bindergenal,CLocalAssum(nal,r,k,fety)::bl)|CLocalDef({loc;v=na}ascna,r,c,ty)->(Name.fold_rightgnae,CLocalDef(cna,r,fec,Option.map(fe)ty)::bl)|CLocalPatternpat->lete,pat=fold_map_cases_patterngfepatin(e,CLocalPatternpat::bl)inlet(e,rbl)=List.fold_lefth(e,[])blin(e,List.revrbl)letmap_constr_expr_with_bindersgfe=CAst.map(function|CAppExpl(r,l)->CAppExpl(r,List.map(fe)l)|CApp(a,l)->CApp(fea,List.map(fun(a,i)->(fea,i))l)|CProj(expl,p,l,a)->CProj(expl,p,List.map(fun(a,i)->(fea,i))l,fea)|CProdN(bl,b)->let(e,bl)=fold_map_local_bindersfgeblinCProdN(bl,feb)|CLambdaN(bl,b)->let(e,bl)=fold_map_local_bindersfgeblinCLambdaN(bl,feb)|CLetIn(na,a,t,b)->CLetIn(na,fea,Option.map(fe)t,f(Name.fold_rightg(na.CAst.v)e)b)|CCast(a,k,c)->CCast(fea,k,fec)|CNotation(inscope,n,(l,ll,bl,bll))->(* This is an approximation because we don't know what binds what *)CNotation(inscope,n,(List.map(fe)l,List.map(List.map(fe))ll,bl,List.map(funbl->snd(fold_map_local_bindersfgebl))bll))|CGeneralization(b,c)->CGeneralization(b,fec)|CDelimiters(depth,s,a)->CDelimiters(depth,s,fea)|CRecordl->CRecord(List.map(fun(id,c)->(id,fec))l)|CCases(sty,rtnpo,a,bl)->letbl=List.map(fun{CAst.v=(patl,rhs);loc}->letids=ids_of_pattern_listpatlinCAst.make?loc(patl,f(Id.Set.foldgidse)rhs))blinletids=ids_of_cases_tomatchainletpo=Option.map(f(Id.Set.foldgidse))rtnpoinCCases(sty,po,List.map(fun(tm,x,y)->fetm,x,y)a,bl)|CLetTuple(nal,(ona,po),b,c)->lete'=List.fold_right(CAst.with_val(Name.fold_rightg))naleinlete''=Option.fold_right(CAst.with_val(Name.fold_rightg))onaeinCLetTuple(nal,(ona,Option.map(fe'')po),feb,fe'c)|CIf(c,(ona,po),b1,b2)->lete'=Option.fold_right(CAst.with_val(Name.fold_rightg))onaeinCIf(fec,(ona,Option.map(fe')po),feb1,feb2)|CFix(id,dl)->CFix(id,List.map(fun(id,r,n,bl,t,d)->let(e',bl')=fold_map_local_bindersfgeblinlett'=fe'tin(* Note: fix names should be inserted before the arguments... *)lete''=List.fold_left(fune({CAst.v=id},_,_,_,_,_)->gide)e'dlinletd'=fe''din(id,r,n,bl',t',d'))dl)|CCoFix(id,dl)->CCoFix(id,List.map(fun(id,r,bl,t,d)->let(e',bl')=fold_map_local_bindersfgeblinlett'=fe'tinlete''=List.fold_left(fune({CAst.v=id},_,_,_,_)->gide)e'dlinletd'=fe''din(id,r,bl',t',d'))dl)|CArray(u,t,def,ty)->CArray(u,Array.map(fe)t,fedef,fety)|CHole_|CGenarg_|CGenargGlob_|CEvar_|CPatVar_|CSort_|CPrim_|CRef_asx->x)(* Used in constrintern *)letrecreplace_vars_constr_exprlr=matchrwith|{CAst.loc;v=CRef(qid,us)}asxwhenqualid_is_identqid->letid=qualid_basenameqidin(tryCAst.make?loc@@CRef(qualid_of_ident?loc(Id.Map.findidl),us)withNot_found->x)|cn->map_constr_expr_with_bindersId.Map.removereplace_vars_constr_exprlcn(* Returns the ranges of locs of the notation that are not occupied by args *)(* and which are then occupied by proper symbols of the notation (or spaces) *)letlocs_of_notation?loclocsntn=letunlocloc=Option.cataLoc.unloc(0,0)locinlet(bl,el)=unloclocinletlocs=List.mapunloclocsinletrecauxpos=function|[]->ifInt.equalposelthen[]else[(pos,el)]|(ba,ea)::l->ifInt.equalposbathenauxealelse(pos,ba)::auxealinauxbl(List.sort(funl1l2->fstl1-fstl2)locs)letntn_loc?loc(args,argslist,binders,binderslist)=locs_of_notation?loc(List.mapconstr_loc(args@List.flattenargslist)@List.map(fun(x,_)->cases_pattern_expr_locx)binders@List.maplocal_binders_locbinderslist)letpatntn_loc?loc(args,argslist,binders)=locs_of_notation?loc(List.mapcases_pattern_expr_loc(args@List.flattenargslist@List.mapfstbinders))leterror_invalid_pattern_notation?loc()=CErrors.user_err?loc(str"Invalid notation for pattern.")(** Pseudo-constructors *)letmkIdentCid=CAst.make@@CRef(qualid_of_identid,None)letmkRefCr=CAst.make@@CRef(r,None)letmkCastC(a,k,t)=CAst.make@@CCast(a,k,t)letmkLambdaC(idl,bk,a,b)=CAst.make@@CLambdaN([CLocalAssum(idl,None,bk,a)],b)letmkLetInC(id,a,t,b)=CAst.make@@CLetIn(id,a,t,b)letmkProdC(idl,bk,a,b)=CAst.make@@CProdN([CLocalAssum(idl,None,bk,a)],b)letmkAppC(f,l)=letl=List.map(funx->(x,None))linmatchCAst.(f.v)with|CApp(g,l')->CAst.make@@CApp(g,l'@l)|_->CAst.make@@CApp(f,l)letmkProdCN?locbllc=ifbll=[]thencelseCAst.make?loc@@CProdN(bll,c)letmkLambdaCN?locbllc=ifbll=[]thencelseCAst.make?loc@@CLambdaN(bll,c)letmkCProdN?locbllc=CAst.make?loc@@CProdN(bll,c)letmkCLambdaN?locbllc=CAst.make?loc@@CLambdaN(bll,c)letcoerce_reference_to_idqid=ifqualid_is_identqidthenqualid_basenameqidelseCErrors.user_err?loc:qid.CAst.loc(str"This expression should be a simple identifier.")letcoerce_to_id=function|{CAst.loc;v=CRef(qid,None)}whenqualid_is_identqid->CAst.make?loc@@qualid_basenameqid|{CAst.loc;_}->CErrors.user_err?loc(str"This expression should be a simple identifier.")letcoerce_to_name=function|{CAst.loc;v=CRef(qid,None)}whenqualid_is_identqid->CAst.make?loc@@Name(qualid_basenameqid)|{CAst.loc;v=CHole(None)}->CAst.make?locAnonymous|{CAst.loc;_}->CErrors.user_err?loc(str"This expression should be a name.")letmkCPatOr?loc=function|[pat]->pat|disjpat->CAst.make?loc@@(CPatOrdisjpat)letmkAppPattern?locplp=ifList.is_emptylpthenpelseletopenCAstinmake?loc@@(matchp.vwith|CPatAtom(Somer)->CPatCstr(r,None,lp)|CPatCstr(r,None,l2)->CErrors.user_err?loc:p.loc(Pp.str"Nested applications not supported.")|CPatCstr(r,l1,l2)->CPatCstr(r,l1,l2@lp)|CPatNotation(inscope,n,s,l)->CPatNotation(inscope,n,s,l@lp)|_->CErrors.user_err?loc:p.loc(Pp.str"Such pattern cannot have arguments."))letreccoerce_to_cases_pattern_exprc=CAst.map_with_loc(fun?loc->function|CRef(r,None)->CPatAtom(Somer)|CHole(None)->CPatAtomNone|CLetIn({CAst.loc;v=Nameid},b,None,{CAst.v=CRef(qid,None)})whenqualid_is_identqid&&Id.equalid(qualid_basenameqid)->CPatAlias(coerce_to_cases_pattern_exprb,CAst.(make?loc@@Nameid))|CApp(p,args)whenList.for_all(fun(_,e)->e=None)args->(mkAppPattern(coerce_to_cases_pattern_exprp)(List.map(fun(a,_)->coerce_to_cases_pattern_expra)args)).CAst.v|CAppExpl((r,i),args)->CPatCstr(r,Some(List.mapcoerce_to_cases_pattern_exprargs),[])|CNotation(inscope,ntn,(c,cl,b,[]))->CPatNotation(inscope,ntn,(List.mapcoerce_to_cases_pattern_exprc,List.map(List.mapcoerce_to_cases_pattern_expr)cl,b),[])|CPrimp->CPatPrimp|CRecordl->CPatRecord(List.map(fun(r,p)->(r,coerce_to_cases_pattern_exprp))l)|CDelimiters(depth,s,p)->CPatDelimiters(depth,s,coerce_to_cases_pattern_exprp)|CCast(p,SomeConstr.DEFAULTcast,t)->CPatCast(coerce_to_cases_pattern_exprp,t)|CLambdaN_|CProdN_|CSort_|CLetIn_|CGeneralization_|CRef(_,Some_)|CCast(_,(Some(VMcast|NATIVEcast)|None),_)|CFix_|CCoFix_|CApp_|CProj_|CCases_|CLetTuple_|CIf_|CPatVar_|CEvar_|CNotation(_,_,(_,_,_,_::_))|CHole(Some_)|CGenarg_|CGenargGlob_->CErrors.user_err?loc(str"This expression should be coercible to a pattern.")|CArray_->CErrors.user_err?loc(str"Arrays in patterns not supported."))cletisCSorta=matcha.CAst.vwithConstrexpr.CSort_->true|_->false