123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683(************************************************************************)(* * 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 in Caml by Gérard Huet for CoC 4.8 [Dec 1988] *)(* Functional code by Jean-Christophe Filliâtre for Coq V7.0 [1999] *)(* Extension with algebraic universes by HH for Coq V7.0 [Sep 2001] *)(* Additional support for sort-polymorphic inductive types by HH [Mar 2006] *)(* Support for universe polymorphism by MS [2014] *)(* Revisions by Bruno Barras, Hugo Herbelin, Pierre Letouzey, Matthieu
Sozeau, Pierre-Marie Pédrot *)openPpopenUtil(* Universes are stratified by a partial ordering $\le$.
Let $\~{}$ be the associated equivalence. We also have a strict ordering
$<$ between equivalence classes, and we maintain that $<$ is acyclic,
and contained in $\le$ in the sense that $[U]<[V]$ implies $U\le V$.
At every moment, we have a finite number of universes, and we
maintain the ordering in the presence of assertions $U<V$ and $U\le V$.
The equivalence $\~{}$ is represented by a tree structure, as in the
union-find algorithm. The assertions $<$ and $\le$ are represented by
adjacency lists *)moduleUGlobal=structopenNamestypet={library:DirPath.t;process:string;uid:int;}letmakelibraryprocessuid={library;process;uid}letreprx=(x.library,x.process,x.uid)letequalu1u2=Int.equalu1.uidu2.uid&&DirPath.equalu1.libraryu2.library&&String.equalu1.processu2.processlethashu=Hashset.Combine.combine3u.uid(String.hashu.process)(DirPath.hashu.library)letcompareu1u2=letc=Int.compareu1.uidu2.uidinifc<>0thencelseletc=DirPath.compareu1.libraryu2.libraryinifc<>0thencelseString.compareu1.processu2.processletto_string{library=d;process=s;uid=n}=DirPath.to_stringd^(ifCString.is_emptysthen""else"."^s)^"."^string_of_intnendmoduleRawLevel=structtypet=|Set|LevelofUGlobal.t|Varofint(* Hash-consing *)letequalxy=x==y||matchx,ywith|Set,Set->true|Levell,Levell'->UGlobal.equalll'|Varn,Varn'->Int.equalnn'|_->falseletcompareuv=matchu,vwith|Set,Set->0|Set,_->-1|_,Set->1|Levell1,Levell2->UGlobal.comparel1l2|Level_,_->-1|_,Level_->1|Varn,Varm->Int.comparenmlethequalxy=x==y||matchx,ywith|Set,Set->true|UGlobal.(Level{library=d;process=s;uid=n},Level{library=d';process=s';uid=n'})->n==n'&&s==s'&&d==d'|Varn,Varn'->n==n'|_->falselethcons=function|Setasx->x|UGlobal.(Level{library=d;process=s;uid=n})asx->lets'=CString.hconssinletd'=Names.DirPath.hconsdinifs'==s&&d'==dthenxelseLevel(UGlobal.maked's'n)|Var_nasx->xopenHashset.Combinelethash=function|Set->combinesmall12|Varn->combinesmall2n|Levell->combinesmall3(UGlobal.hashl)endmoduleLevel=structtyperaw_level=RawLevel.t=|Set|LevelofUGlobal.t|Varofint(** Embed levels with their hash value *)typet={hash:int;data:RawLevel.t}letequalxy=x==y||Int.equalx.hashy.hash&&RawLevel.equalx.datay.datalethashx=x.hashletdatax=x.data(** Hashcons on levels + their hash *)moduleSelf=structtypenonrect=ttypeu=unitleteqxy=x.hash==y.hash&&RawLevel.hequalx.datay.datalethashx=x.hashlethashcons()x=letdata'=RawLevel.hconsx.datainifx.data==data'thenxelse{xwithdata=data'}endlethcons=letmoduleH=Hashcons.Make(Self)inHashcons.simple_hconsH.generateH.hcons()letmakel=hcons{hash=RawLevel.hashl;data=l}letset=makeSetletis_smallx=matchdataxwith|Level_->false|Var_->false|Set->trueletis_setx=matchdataxwith|Set->true|_->falseletcompareuv=ifu==vthen0elseRawLevel.compare(datau)(datav)letto_stringx=matchdataxwith|Set->"Set"|Levell->UGlobal.to_stringl|Varn->"Var("^string_of_intn^")"letraw_pru=str(to_stringu)letpr=raw_prletvars=Array.init20(funi->make(Vari))letvarn=ifn<20thenvars.(n)elsemake(Varn)letvar_indexu=matchdatauwith|Varn->Somen|_->Noneletmakeqid=make(Levelqid)letnameu=matchdatauwith|Levell->Somel|_->None(** Level maps *)moduleMap=structmoduleSelf=structtypenonrect=tlethash=hashletcompare=compareendmoduleM=HMap.Make(Self)includeMletlunionlr=union(fun_kl_r->Somel)lrletdiffextorig=fold(funuvacc->ifmemuorigthenaccelseadduvacc)extemptyletprprlfm=h(prlist_with_sepfnl(fun(u,v)->prlu++fv)(bindingsm))endmoduleSet=structincludeMap.Setletprprls=hov1(str"{"++prlist_with_sepspcprl(elementss)++str"}")endendtypeuniverse_level=Level.ttypeuniverse_set=Level.Set.t(* An algebraic universe [universe] is either a universe variable
[Level.t] or a formal universe known to be greater than some
universe variables and strictly greater than some (other) universe
variables
Universes variables denote universes initially present in the term
to type-check and non variable algebraic universes denote the
universes inferred while type-checking: it is either the successor
of a universe present in the initial term to type-check or the
maximum of two algebraic universes
*)moduleUniverse=struct(* Invariants: non empty, sorted and without duplicates *)moduleExpr=structtypet=Level.t*int(* Hashing of expressions *)moduleExprHash=structtypet=Level.t*inttypeu=Level.t->Level.tlethashconshdir(b,nasx)=letb'=hdirbinifb'==bthenxelse(b',n)leteql1l2=l1==l2||matchl1,l2with|(b,n),(b',n')->b==b'&&n==n'lethash(x,n)=n+Level.hashxendmoduleH=Hashcons.Make(ExprHash)lethcons=Hashcons.simple_hconsH.generateH.hconsLevel.hconsletmakel=(l,0)letcompareuv=ifu==vthen0elselet(x,n)=uand(x',n')=vinletc=Int.comparenn'inifInt.equal0cthenLevel.comparexx'elsecletset=hcons(Level.set,0)lettype1=hcons(Level.set,1)letis_small=function|(l,0)->Level.is_smalll|_->falseletequalxy=x==y||(let(u,n)=xand(v,n')=yinInt.equalnn'&&Level.equaluv)lethash=ExprHash.hashletsuccessor(u,nase)=ifis_smallethentype1else(u,n+1)typesuper_result=SuperSameofbool(* The level expressions are in cumulativity relation. boolean
indicates if left is smaller than right? *)|SuperDiffofint(* The level expressions are unrelated, the comparison result
is canonical *)(** [super u v] compares two level expressions,
returning [SuperSame] if they refer to the same level at potentially different
increments or [SuperDiff] if they are different. The booleans indicate if the
left expression is "smaller" than the right one in both cases. *)letsuper(u,n)(v,n')=letcmp=Level.compareuvinifInt.equalcmp0thenSuperSame(n<n')elseSuperDiffcmpletpr_withf(v,n)=ifInt.equaln0thenfvelsefv++str"+"++intnletis_level=function|(_v,0)->true|_->falseletlevel=function|(v,0)->Somev|_->Noneletget_level(v,_n)=vletmapf(v,nasx)=letv'=fvinifv'==vthenxelse(v',n)endtypet=Expr.tlistlettipl=[l]letconsxl=x::lletrechash=function|[]->0|e::l->Hashset.Combine.combinesmall(Expr.ExprHash.hashe)(hashl)letequalxy=x==y||List.equalExpr.equalxyletcomparexy=ifx==ythen0elseList.compareExpr.comparexymoduleHuniv=Hashcons.Hlist(Expr)lethcons=Hashcons.simple_hconsHuniv.generateHuniv.hconsExpr.hconsmoduleSelf=structtypenonrect=tletcompare=compareendmoduleMap=CMap.Make(Self)moduleSet=CSet.Make(Self)letmakel=tip(Expr.makel)lettipx=tipxletprfl=matchlwith|[u]->Expr.pr_withfu|_->str"max("++hov0(prlist_with_seppr_comma(Expr.pr_withf)l)++str")"letraw_prl=prLevel.raw_prlletis_levell=matchlwith|[l]->Expr.is_levell|_->falseletrecis_levelsl=matchlwith|l::r->Expr.is_levell&&is_levelsr|[]->trueletlevell=matchlwith|[l]->Expr.levell|_->Noneletlevelsl=letfoldaccx=letl=Expr.get_levelxinLevel.Set.addlaccinList.fold_leftfoldLevel.Set.emptylletis_smallu=matchuwith|[l]->Expr.is_smalll|_->false(* The level of sets *)lettype0=tipExpr.set(* When typing [Prop] and [Set], there is no constraint on the level,
hence the definition of [type1_univ], the type of [Prop] *)lettype1=tipExpr.type1letis_type0x=equaltype0x(* Returns the formal universe that lies just above the universe variable u.
Used to type the sort u. *)letsuperl=ifis_smalllthentype1elseList.Smart.map(funx->Expr.successorx)lletrecmerge_univsl1l2=matchl1,l2with|[],_->l2|_,[]->l1|h1::t1,h2::t2->letopenExprin(matchsuperh1h2with|SuperSametrue(* h1 < h2 *)->merge_univst1l2|SuperSamefalse->merge_univsl1t2|SuperDiffc->ifc<=0(* h1 < h2 is name order *)thenconsh1(merge_univst1l2)elseconsh2(merge_univsl1t2))letsortu=letrecauxal=matchlwith|b::l'->letopenExprin(matchsuperabwith|SuperSamefalse->auxal'|SuperSametrue->l|SuperDiffc->ifc<=0thenconsalelseconsb(auxal'))|[]->consalinList.fold_right(funaacc->auxaacc)u[](* Returns the formal universe that is greater than the universes u and v.
Used to type the products. *)letsupxy=merge_univsxyletexists=List.existsletfor_all=List.for_allletreprx:t=xletunreprl=assert(not(List.is_emptyl));sortlendtypeconstraint_type=AcyclicGraph.constraint_type=Lt|Le|Eqletconstraint_type_ordc1c2=matchc1,c2with|Lt,Lt->0|Lt,_->-1|Le,Lt->1|Le,Le->0|Le,Eq->-1|Eq,Eq->0|Eq,_->1(* Constraints and sets of constraints. *)typeuniv_constraint=Level.t*constraint_type*Level.tletpr_constraint_typeop=letop_str=matchopwith|Lt->" < "|Le->" <= "|Eq->" = "instrop_strmoduleUConstraintOrd=structtypet=univ_constraintletcompare(u,c,v)(u',c',v')=leti=constraint_type_ordcc'inifnot(Int.equali0)thenielseleti'=Level.compareuu'inifnot(Int.equali'0)theni'elseLevel.comparevv'endmoduleConstraints=structmoduleS=Set.Make(UConstraintOrd)includeSletprprlc=v0(prlist_with_sepspc(fun(u1,op,u2)->hov0(prlu1++pr_constraint_typeop++prlu2))(elementsc))endmoduleHconstraint=Hashcons.Make(structtypet=univ_constrainttypeu=universe_level->universe_levellethashconshul(l1,k,l2)=(hull1,k,hull2)leteq(l1,k,l2)(l1',k',l2')=l1==l1'&&k==k'&&l2==l2'lethash=Hashtbl.hashend)moduleHconstraints=Hashcons.Make(structtypet=Constraints.ttypeu=univ_constraint->univ_constraintlethashconshucs=Constraints.fold(funx->Constraints.add(hucx))sConstraints.emptyleteqss'=List.for_all2eq(==)(Constraints.elementss)(Constraints.elementss')lethash=Hashtbl.hashend)lethcons_constraint=Hashcons.simple_hconsHconstraint.generateHconstraint.hconsLevel.hconslethcons_constraints=Hashcons.simple_hconsHconstraints.generateHconstraints.hconshcons_constraint(** A value with universe constraints. *)type'aconstrained='a*Constraints.tletconstraints_of(_,cst)=cst(** Constraints functions. *)type'aconstraint_function='a->'a->Constraints.t->Constraints.tletenforce_eq_leveluvc=(* We discard trivial constraints like u=u *)ifLevel.equaluvthencelseConstraints.add(u,Eq,v)cletenforce_leq_leveluvc=ifLevel.equaluvthencelseConstraints.add(u,Le,v)c(* Miscellaneous functions to remove or test local univ assumed to
occur in a universe *)letuniv_level_memuv=List.exists(fun(l,n)->Int.equaln0&&Level.equalul)vletuniv_level_remuvmin=matchUniverse.levelvwith|Someu'->ifLevel.equaluu'thenminelsev|None->List.filter(fun(l,n)->not(Int.equaln0&&Level.equalul))v(* Is u mentioned in v (or equals to v) ? *)(**********************************************************************)(** Universe polymorphism *)(**********************************************************************)(** A universe level substitution, note that no algebraic universes are
involved *)typeuniverse_level_subst=universe_levelLevel.Map.t(** A set of universes with universe constraints.
We linearize the set to a list after typechecking.
Beware, representation could change.
*)moduleContextSet=structtypet=universe_setconstrainedletempty=(Level.Set.empty,Constraints.empty)letis_empty(univs,cst)=Level.Set.is_emptyunivs&&Constraints.is_emptycstletequal(univs,cstasx)(univs',cst'asy)=x==y||(Level.Set.equalunivsunivs'&&Constraints.equalcstcst')letof_sets=(s,Constraints.empty)letsingletonl=of_set(Level.Set.singletonl)letunion(univs,cstasx)(univs',cst'asy)=ifx==ythenxelseLevel.Set.unionunivsunivs',Constraints.unioncstcst'letappend(univs,cst)(univs',cst')=letunivs=Level.Set.foldLevel.Set.addunivsunivs'inletcst=Constraints.foldConstraints.addcstcst'in(univs,cst)letdiff(univs,cst)(univs',cst')=Level.Set.diffunivsunivs',Constraints.diffcstcst'letadd_universeu(univs,cst)=Level.Set.adduunivs,cstletadd_constraintscst'(univs,cst)=univs,Constraints.unioncstcst'letprprl(univs,cstasctx)=ifis_emptyctxthenmt()elsehov0(h(Level.Set.prprlunivs++str" |=")++brk(1,2)++h(Constraints.prprlcst))letconstraints(_univs,cst)=cstletlevels(univs,_cst)=univsletsize(univs,_)=Level.Set.cardinalunivsendtypeuniverse_context_set=ContextSet.t(** A value in a universe context (resp. context set). *)type'ain_universe_context_set='a*universe_context_set(** Substitutions. *)letempty_level_subst=Level.Map.emptyletis_empty_level_subst=Level.Map.is_empty(** Substitution functions *)(** With level to level substitutions. *)letsubst_univs_level_levelsubstl=tryLevel.Map.findlsubstwithNot_found->lletsubst_univs_level_universesubstu=letfx=Universe.Expr.map(funu->subst_univs_level_levelsubstu)xinletu'=List.Smart.mapfuinifu==u'thenuelseUniverse.sortu'letsubst_univs_level_constraintsubst(u,d,v)=letu'=subst_univs_level_levelsubstuandv'=subst_univs_level_levelsubstvinifd!=Lt&&Level.equalu'v'thenNoneelseSome(u',d,v')letsubst_univs_level_constraintssubstcsts=Constraints.fold(func->Option.fold_rightConstraints.add(subst_univs_level_constraintsubstc))cstsConstraints.empty(** Pretty-printing *)letpr_universe_context_set=ContextSet.prletpr_universe_level_substprl=Level.Map.prprl(funu->str" := "++prlu++spc())moduleHuniverse_set=Hashcons.Make(structtypet=universe_settypeu=universe_level->universe_levellethashconshucs=Level.Set.fold(funx->Level.Set.add(hucx))sLevel.Set.emptyleteqss'=Level.Set.equalss'lethash=Hashtbl.hashend)lethcons_universe_set=Hashcons.simple_hconsHuniverse_set.generateHuniverse_set.hconsLevel.hconslethcons_universe_context_set(v,c)=(hcons_universe_setv,hcons_constraintsc)lethcons_univx=Universe.hconsx