123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606(************************************************************************)(* * 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) *)(************************************************************************)(* Created by Jean-Christophe Filliâtre out of names.ml as part of the
rebuilding of Coq around a purely functional abstract type-checker,
Aug 1999 *)(* Miscellaneous extensions, restructurations and bug-fixes by Hugo
Herbelin and Bruno Barras *)(* This file defines types and combinators regarding indexes-based and
names-based contexts *)(** The modules defined below represent a {e local context}
as defined by Chapter 4 in the Reference Manual:
A {e local context} is an ordered list of of {e local declarations}
of names that we call {e variables}.
A {e local declaration} of some variable can be either:
- a {e local assumption}, or
- a {e local definition}.
*)openUtilopenNamestype('a,'r)pbinder_annot={binder_name:'a;binder_relevance:'r}leteq_annoteqeqr{binder_name=na1;binder_relevance=r1}{binder_name=na2;binder_relevance=r2}=eqna1na2&&eqrr1r2lethash_annoth{binder_name=n;binder_relevance=r}=Hashset.Combine.combinesmall(Sorts.relevance_hashr)(hn)letmap_annotf{binder_name=na;binder_relevance}=letna'=fnain{binder_name=na';binder_relevance}letmap_annot_relevance_smartfr({binder_name=na;binder_relevance=r}asa)=letr'=frrinifr==r'thenaelse{binder_name=na;binder_relevance=r'}letmap_annot_relevancefr{binder_name=na;binder_relevance=r}=letr'=frrin{binder_name=na;binder_relevance=r'}letmake_annotxr={binder_name=x;binder_relevance=r}letbinder_namex=x.binder_nameletbinder_relevancex=x.binder_relevanceletannotRx=make_annotxSorts.RelevantletnameRx=annotR(Namex)letanonR=annotRAnonymous(** Representation of contexts that can capture anonymous as well as non-anonymous variables.
Individual declarations are then designated by de Bruijn indexes. *)moduleRel=struct(** Representation of {e local declarations}. *)moduleDeclaration=struct(* local declaration *)type('constr,'types,'r)pt=|LocalAssumof(Name.t,'r)pbinder_annot*'types(** name, type *)|LocalDefof(Name.t,'r)pbinder_annot*'constr*'types(** name, value, type *)letget_annot=function|LocalAssum(na,_)|LocalDef(na,_,_)->na(** Return the name bound by a given declaration. *)letget_namex=(get_annotx).binder_name(** Return [Some value] for local-declarations and [None] for local-assumptions. *)letget_value=function|LocalAssum_->None|LocalDef(_,v,_)->Somev(** Return the type of the name bound by a given declaration. *)letget_type=function|LocalAssum(_,ty)|LocalDef(_,_,ty)->tyletget_relevancex=(get_annotx).binder_relevanceletset_annotxd=ifget_annotd==xthendelsematchdwith|LocalAssum(_,ty)->LocalAssum(x,ty)|LocalDef(_,v,ty)->LocalDef(x,v,ty)(** Set the name that is bound by a given declaration. *)letset_namena=function|LocalAssum(x,ty)->LocalAssum({xwithbinder_name=na},ty)|LocalDef(x,v,ty)->LocalDef({xwithbinder_name=na},v,ty)letset_relevancer=function|LocalAssum(x,ty)->LocalAssum({xwithbinder_relevance=r},ty)|LocalDef(x,v,ty)->LocalDef({xwithbinder_relevance=r},v,ty)(** Set the type of the bound variable in a given declaration. *)letset_typety=function|LocalAssum(na,_)->LocalAssum(na,ty)|LocalDef(na,v,_)->LocalDef(na,v,ty)(** Return [true] iff a given declaration is a local assumption. *)letis_local_assum=function|LocalAssum_->true|LocalDef_->false(** Return [true] iff a given declaration is a local definition. *)letis_local_def=function|LocalAssum_->false|LocalDef_->true(** Check whether any term in a given declaration satisfies a given predicate. *)letexistsf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv||fty(** Check whether all terms in a given declaration satisfy a given predicate. *)letfor_allf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv&&fty(** Check whether the two given declarations are equal. *)letequaleqreqdecl1decl2=matchdecl1,decl2with|LocalAssum(n1,ty1),LocalAssum(n2,ty2)->eq_annotName.equaleqrn1n2&&eqty1ty2|LocalDef(n1,v1,ty1),LocalDef(n2,v2,ty2)->eq_annotName.equaleqrn1n2&&eqv1v2&&eqty1ty2|_->false(** Map the name bound by a given declaration. *)letmap_namefx=letna=get_namexinletna'=fnainifna==na'thenxelseset_namena'xletmap_relevancefx=letr=get_relevancexinletr'=frinifr==r'thenxelseset_relevancer'x(** For local assumptions, this function returns the original local assumptions.
For local definitions, this function maps the value in the local definition. *)letmap_valuef=function|LocalAssum_asdecl->decl|LocalDef(na,v,t)asdecl->letv'=fvinifv==v'thendeclelseLocalDef(na,v',t)(** Map the type of the name bound by a given declaration. *)letmap_typef=function|LocalAssum(na,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalAssum(na,ty')|LocalDef(na,v,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalDef(na,v,ty')(** Map all terms in a given declaration. *)letmap_constrf=function|LocalAssum(na,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalAssum(na,ty')|LocalDef(na,v,ty)asdecl->letv'=fvinletty'=ftyinifv==v'&&ty==ty'thendeclelseLocalDef(na,v',ty')(** Map all terms in a given declaration. *)letmap_constr_with_relevancegf=function|LocalAssum(na,ty)asdecl->letna'=map_annot_relevance_smartgnainletty'=ftyinifna==na'&&ty==ty'thendeclelseLocalAssum(na',ty')|LocalDef(na,v,ty)asdecl->letna'=map_annot_relevance_smartgnainletv'=fvinletty'=ftyinifna==na'&&v==v'&&ty==ty'thendeclelseLocalDef(na',v',ty')letmap_constr_hetfrf=function|LocalAssum(na,ty)->letty'=ftyinLocalAssum(map_annot_relevancefrna,ty')|LocalDef(na,v,ty)->letv'=fvinletty'=ftyinLocalDef(map_annot_relevancefrna,v',ty')(** Perform a given action on all terms in a given declaration. *)letiter_constrf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv;fty(** Reduce all terms in a given declaration to a single value. *)letfold_constrfdeclacc=matchdeclwith|LocalAssum(_n,ty)->ftyacc|LocalDef(_n,v,ty)->fty(fvacc)letto_tuple=function|LocalAssum(na,ty)->na,None,ty|LocalDef(na,v,ty)->na,Somev,tyletdrop_body=function|LocalAssum_asd->d|LocalDef(na,_v,ty)->LocalAssum(na,ty)end(** Rel-context is represented as a list of declarations.
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)type('constr,'types,'r)pt=('constr,'types,'r)Declaration.ptlist(** empty rel-context *)letempty=[](** Return a new rel-context enriched by with a given inner-most declaration. *)letadddctx=d::ctx(** Return the number of {e local declarations} in a given rel-context. *)letlength=List.length(** Return the number of {e local assumptions} in a given rel-context. *)letnhypsctx=letopenDeclarationinletrecnhypsacc=function|[]->acc|LocalAssum_::hyps->nhyps(succacc)hyps|LocalDef_::hyps->nhypsacchypsinnhyps0ctx(** Return a declaration designated by a given de Bruijn index.
@raise Not_found if the designated de Bruijn index is not present in the designated rel-context. *)letreclookupnctx=matchn,ctxwith|1,decl::_->decl|n,_::sign->lookup(n-1)sign|_,[]->raiseNot_found(** Check whether given two rel-contexts are equal. *)letequaleqreql=List.equal(func->Declaration.equaleqreqc)l(** Map all terms in a given rel-context. *)letmapf=List.Smart.map(Declaration.map_constrf)letmap_with_relevancegf=List.Smart.map(Declaration.map_constr_with_relevancegf)letmap_hetfrf=List.map(Declaration.map_constr_hetfrf)(** Map all terms in a given rel-context. *)letmap_with_bindersfctx=letrecauxk=function|decl::ctxasl->letdecl'=Declaration.map_constr(fk)declinletctx'=aux(k-1)ctxinifdecl==decl'&&ctx==ctx'thenlelsedecl'::ctx'|[]->[]inaux(lengthctx)ctx(** Perform a given action on every declaration in a given rel-context. *)letiterf=List.iter(Declaration.iter_constrf)(** Reduce all terms in a given rel-context to a single value.
Innermost declarations are processed first. *)letfold_insidef~init=List.fold_leftfinit(** Reduce all terms in a given rel-context to a single value.
Outermost declarations are processed first. *)letfold_outsidefl~init=List.fold_rightflinit(** Return the set of all named variables bound in a given rel-context. *)letto_varsl=List.fold_left(funaccudecl->matchDeclaration.get_namedeclwith|Nameid->Id.Set.addidaccu|Anonymous->accu)Id.Set.emptyl(** Map a given rel-context to a list where each {e local assumption} is mapped to [true]
and each {e local definition} is mapped to [false]. *)letto_tagsl=letrecauxl=function|[]->l|Declaration.LocalDef_::ctx->aux(true::l)ctx|Declaration.LocalAssum_::ctx->aux(false::l)ctxinaux[]lletdrop_bodiesl=List.Smart.mapDeclaration.drop_bodyl(** Split a context so that the second part contains [n]
[LocalAssum], keeping all [LocalDef] in the middle in the first part *)letchop_nhypsnl=letrecauxl'=function|(0,l)->(List.revl',l)|(n,(Declaration.LocalDef_ash)::l)->aux(h::l')(n,l)|(n,(Declaration.LocalAssum_ash)::l)->aux(h::l')(n-1,l)|(_,[])->CErrors.anomaly(Pp.str"chop_nhyps: not enough hypotheses.")inaux[](n,l)(** [extended_list n Γ] builds an instance [args] such that [Γ,Δ ⊢ args:Γ]
with n = |Δ| and with the {e local definitions} of [Γ] skipped in
[args]. Example: for [x:T, y:=c, z:U] and [n]=2, it gives [Rel 5, Rel 3]. *)letto_extended_listmknl=letrecrelnlp=function|Declaration.LocalAssum_::hyps->reln(mk(n+p)::l)(p+1)hyps|Declaration.LocalDef_::hyps->relnl(p+1)hyps|[]->linreln[]1l(** [extended_vect n Γ] does the same, returning instead an array. *)letto_extended_vectmknhyps=Array.of_list(to_extended_listmknhyps)(** Consistency with terminology in Named *)letinstance=to_extended_vectletinstance_list=to_extended_listend(** This module represents contexts that can capture non-anonymous variables.
Individual declarations are then designated by the identifiers they bind. *)moduleNamed=struct(** Representation of {e local declarations}. *)moduleDeclaration=struct(** local declaration *)type('constr,'types,'r)pt=|LocalAssumof(Id.t,'r)pbinder_annot*'types(** identifier, type *)|LocalDefof(Id.t,'r)pbinder_annot*'constr*'types(** identifier, value, type *)letget_annot=function|LocalAssum(na,_)|LocalDef(na,_,_)->na(** Return the identifier bound by a given declaration. *)letget_idx=(get_annotx).binder_name(** Return [Some value] for local-declarations and [None] for local-assumptions. *)letget_value=function|LocalAssum_->None|LocalDef(_,v,_)->Somev(** Return the type of the name bound by a given declaration. *)letget_type=function|LocalAssum(_,ty)|LocalDef(_,_,ty)->tyletget_relevancex=(get_annotx).binder_relevance(** Set the identifier that is bound by a given declaration. *)letset_idid=letsetx={xwithbinder_name=id}infunction|LocalAssum(x,ty)->LocalAssum(setx,ty)|LocalDef(x,v,ty)->LocalDef(setx,v,ty)(** Set the type of the bound variable in a given declaration. *)letset_typety=function|LocalAssum(id,_)->LocalAssum(id,ty)|LocalDef(id,v,_)->LocalDef(id,v,ty)(** Return [true] iff a given declaration is a local assumption. *)letis_local_assum=function|LocalAssum_->true|LocalDef_->false(** Return [true] iff a given declaration is a local definition. *)letis_local_def=function|LocalDef_->true|LocalAssum_->false(** Check whether any term in a given declaration satisfies a given predicate. *)letexistsf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv||fty(** Check whether all terms in a given declaration satisfy a given predicate. *)letfor_allf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv&&fty(** Check whether the two given declarations are equal. *)letequaleqreqdecl1decl2=matchdecl1,decl2with|LocalAssum(id1,ty1),LocalAssum(id2,ty2)->eq_annotId.equaleqrid1id2&&eqty1ty2|LocalDef(id1,v1,ty1),LocalDef(id2,v2,ty2)->eq_annotId.equaleqrid1id2&&eqv1v2&&eqty1ty2|_->false(** Map the identifier bound by a given declaration. *)letmap_idfx=letid=get_idxinletid'=fidinifid==id'thenxelseset_idid'x(** For local assumptions, this function returns the original local assumptions.
For local definitions, this function maps the value in the local definition. *)letmap_valuef=function|LocalAssum_asdecl->decl|LocalDef(na,v,t)asdecl->letv'=fvinifv==v'thendeclelseLocalDef(na,v',t)(** Map the type of the name bound by a given declaration. *)letmap_typef=function|LocalAssum(id,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalAssum(id,ty')|LocalDef(id,v,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalDef(id,v,ty')(** Map all terms in a given declaration. *)letmap_constrf=function|LocalAssum(id,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalAssum(id,ty')|LocalDef(id,v,ty)asdecl->letv'=fvinletty'=ftyinifv==v'&&ty==ty'thendeclelseLocalDef(id,v',ty')(** Map all terms in a given declaration. *)letmap_constr_with_relevancegf=function|LocalAssum(id,ty)asdecl->letid'=map_annot_relevance_smartgidinletty'=ftyinifid==id'&&ty==ty'thendeclelseLocalAssum(id',ty')|LocalDef(id,v,ty)asdecl->letid'=map_annot_relevance_smartgidinletv'=fvinletty'=ftyinifid==id'&&v==v'&&ty==ty'thendeclelseLocalDef(id',v',ty')letmap_constr_hetfrf=function|LocalAssum(id,ty)->letty'=ftyinLocalAssum(map_annot_relevancefrid,ty')|LocalDef(id,v,ty)->letv'=fvinletty'=ftyinLocalDef(map_annot_relevancefrid,v',ty')(** Perform a given action on all terms in a given declaration. *)letiter_constrf=function|LocalAssum(_,ty)->fty|LocalDef(_,v,ty)->fv;fty(** Reduce all terms in a given declaration to a single value. *)letfold_constrfdecla=matchdeclwith|LocalAssum(_,ty)->ftya|LocalDef(_,v,ty)->a|>fv|>ftyletto_tuple=function|LocalAssum(id,ty)->id,None,ty|LocalDef(id,v,ty)->id,Somev,tyletof_tuple=function|id,None,ty->LocalAssum(id,ty)|id,Somev,ty->LocalDef(id,v,ty)letdrop_body=function|LocalAssum_asd->d|LocalDef(id,_v,ty)->LocalAssum(id,ty)letof_rel_declf=function|Rel.Declaration.LocalAssum(na,t)->LocalAssum(map_annotfna,t)|Rel.Declaration.LocalDef(na,v,t)->LocalDef(map_annotfna,v,t)letto_rel_decl=letnamex={binder_name=Namex.binder_name;binder_relevance=x.binder_relevance}infunction|LocalAssum(id,t)->Rel.Declaration.LocalAssum(nameid,t)|LocalDef(id,v,t)->Rel.Declaration.LocalDef(nameid,v,t)end(** Named-context is represented as a list of declarations.
Inner-most declarations are at the beginning of the list.
Outer-most declarations are at the end of the list. *)type('constr,'types,'r)pt=('constr,'types,'r)Declaration.ptlist(** empty named-context *)letempty=[](** Return a new named-context enriched by with a given inner-most declaration. *)letadddctx=d::ctx(** Return the number of {e local declarations} in a given named-context. *)letlength=List.length(** Return a declaration designated by a given identifier
@raise Not_found if the designated identifier is not present in the designated named-context. *)letreclookupid=function|decl::_whenId.equalid(Declaration.get_iddecl)->decl|_::sign->lookupidsign|[]->raiseNot_found(** Check whether given two named-contexts are equal. *)letequaleqreql=List.equal(func->Declaration.equaleqreqc)l(** Map all terms in a given named-context. *)letmapf=List.Smart.map(Declaration.map_constrf)letmap_with_relevancegf=List.Smart.map(Declaration.map_constr_with_relevancegf)letmap_hetfrf=List.map(Declaration.map_constr_hetfrf)(** Perform a given action on every declaration in a given named-context. *)letiterf=List.iter(Declaration.iter_constrf)(** Reduce all terms in a given named-context to a single value.
Innermost declarations are processed first. *)letfold_insidef~init=List.fold_leftfinit(** Reduce all terms in a given named-context to a single value.
Outermost declarations are processed first. *)letfold_outsidefl~init=List.fold_rightflinit(** Return the set of all identifiers bound in a given named-context. *)letto_varsl=List.fold_left(funaccudecl->Id.Set.add(Declaration.get_iddecl)accu)Id.Set.emptylletdrop_bodiesl=List.Smart.mapDeclaration.drop_bodyl(** [to_instance Ω] builds an instance [args] in reverse order such
that [Ω ⊢ args:Ω] where [Ω] is a named context and with the local
definitions of [Ω] skipped. Example: for [id1:T,id2:=c,id3:U], it
gives [Var id1, Var id3]. All [idj] are supposed distinct. *)letto_instancemkl=letfilter=function|Declaration.LocalAssum(id,_)->Some(mkid.binder_name)|_->NoneinList.map_filterfilterl(** [instance Ω] builds an instance [args] such
that [Ω ⊢ args:Ω] where [Ω] is a named context and with the local
definitions of [Ω] skipped. Example: for [id1:T,id2:=c,id3:U], it
gives [Var id1, Var id3]. All [idj] are supposed distinct. *)letinstance_listmkl=letfilter=function|Declaration.LocalAssum(id,_)->Some(mkid.binder_name)|_->NoneinList.rev(List.map_filterfilterl)letinstancemkl=Array.of_list(instance_listmkl)endmoduleCompacted=structmoduleDeclaration=structtype('constr,'types,'r)pt=|LocalAssumof(Id.t,'r)pbinder_annotlist*'types|LocalDefof(Id.t,'r)pbinder_annotlist*'constr*'typesletmap_constrf=function|LocalAssum(ids,ty)asdecl->letty'=ftyinifty==ty'thendeclelseLocalAssum(ids,ty')|LocalDef(ids,c,ty)asdecl->letty'=ftyinletc'=fcinifc==c'&&ty==ty'thendeclelseLocalDef(ids,c',ty')letof_named_decl=function|Named.Declaration.LocalAssum(id,t)->LocalAssum([id],t)|Named.Declaration.LocalDef(id,v,t)->LocalDef([id],v,t)letto_named_context=function|LocalAssum(ids,t)->List.map(funid->Named.Declaration.LocalAssum(id,t))ids|LocalDef(ids,v,t)->List.map(funid->Named.Declaration.LocalDef(id,v,t))idsendtype('constr,'types,'r)pt=('constr,'types,'r)Declaration.ptlistletfoldfl~init=List.fold_rightflinitend