123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041(************************************************************************)(* * 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 *)openPpopenCErrorsopenUtil(* 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)lrletsubst_unionlr=union(fun_klr->matchl,rwith|Some_,_->Somel|None,None->Somel|_,_->Somer)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"}")letof_arrayl=Array.fold_left(funaccx->addxacc)emptylendendtypeuniverse_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=xendtypeconstraint_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))endtypeconstraints=Constraints.tmoduleHconstraint=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=constraintstypeu=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*constraintsletconstraints_of(_,cst)=cst(** Constraints functions. *)type'aconstraint_function='a->'a->constraints->constraintsletenforce_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.tmoduleVariance=struct(** A universe position in the instance given to a cumulative
inductive can be the following. Note there is no Contravariant
case because [forall x : A, B <= forall x : A', B'] requires [A =
A'] as opposed to [A' <= A]. *)typet=Irrelevant|Covariant|Invariantletsupxy=matchx,ywith|Irrelevant,s|s,Irrelevant->s|Invariant,_|_,Invariant->Invariant|Covariant,Covariant->Covariantletequalab=matcha,bwith|Irrelevant,Irrelevant|Covariant,Covariant|Invariant,Invariant->true|(Irrelevant|Covariant|Invariant),_->falseletcheck_subtypexy=matchx,ywith|(Irrelevant|Covariant|Invariant),Irrelevant->true|Irrelevant,Covariant->false|(Covariant|Invariant),Covariant->true|(Irrelevant|Covariant),Invariant->false|Invariant,Invariant->trueletpr=function|Irrelevant->str"*"|Covariant->str"+"|Invariant->str"="letleq_constraintcstsvarianceuu'=matchvariancewith|Irrelevant->csts|Covariant->enforce_leq_leveluu'csts|Invariant->enforce_eq_leveluu'cstsleteq_constraintcstsvarianceuu'=matchvariancewith|Irrelevant->csts|Covariant|Invariant->enforce_eq_leveluu'cstsletleq_constraintsvarianceuu'csts=letlen=Array.lengthuinassert(len=Array.lengthu'&&len=Array.lengthvariance);Array.fold_left3leq_constraintcstsvarianceuu'leteq_constraintsvarianceuu'csts=letlen=Array.lengthuinassert(len=Array.lengthu'&&len=Array.lengthvariance);Array.fold_left3eq_constraintcstsvarianceuu'endmoduleInstance:sigtypet=Level.tarrayvalempty:tvalis_empty:t->boolvalof_array:Level.tarray->tvalto_array:t->Level.tarrayvalappend:t->t->tvalequal:t->t->boolvallength:t->intvalhcons:t->tvalhash:t->intvalshare:t->t*intvalsubst_fn:(Level.t->Level.t)->t->tvalpr:(Level.t->Pp.t)->?variance:Variance.tarray->t->Pp.tvallevels:t->Level.Set.tend=structtypet=Level.tarrayletempty:t=[||]moduleHInstancestruct=structtypenonrect=ttypeu=Level.t->Level.tlethashconshuniva=letlen=Array.lengthainifInt.equallen0thenemptyelsebeginfori=0tolen-1doletx=Array.unsafe_getaiinletx'=hunivxinifx==x'then()elseArray.unsafe_setaix'done;aendleteqt1t2=t1==t2||(Int.equal(Array.lengtht1)(Array.lengtht2)&&letrecauxi=(Int.equali(Array.lengtht1))||(t1.(i)==t2.(i)&&aux(i+1))inaux0)lethasha=letaccu=ref0infori=0toArray.lengtha-1doletl=Array.unsafe_getaiinleth=Level.hashlinaccu:=Hashset.Combine.combine!accuh;done;(* [h] must be positive. *)leth=!acculand0x3FFFFFFFinhendmoduleHInstance=Hashcons.Make(HInstancestruct)lethcons=Hashcons.simple_hconsHInstance.generateHInstance.hconsLevel.hconslethash=HInstancestruct.hashletsharea=(hconsa,hasha)letempty=hcons[||]letis_emptyx=Int.equal(Array.lengthx)0letappendxy=ifArray.lengthx=0thenyelseifArray.lengthy=0thenxelseArray.appendxyletof_arraya=aletto_arraya=aletlengtha=Array.lengthaletsubst_fnfnt=lett'=CArray.Smart.mapfntinift'==tthentelseof_arrayt'letlevelsx=Level.Set.of_arrayxletprprl?variance=letppuiu=letv=Option.map(funv->v.(i))varianceinpr_opt_no_spcVariance.prv++prluinprvecti_with_sepspcppuletequaltu=t==u||(Array.is_emptyt&&Array.is_emptyu)||(CArray.for_all2Level.equaltu(* Necessary as universe instances might come from different modules and
unmarshalling doesn't preserve sharing *))endletenforce_eq_instancesxy=letax=Instance.to_arrayxanday=Instance.to_arrayyinifArray.lengthax!=Array.lengthaythenanomaly(Pp.(++)(Pp.str"Invalid argument: enforce_eq_instances called with")(Pp.str" instances of different lengths."));CArray.fold_right2enforce_eq_levelaxayletenforce_eq_variance_instances=Variance.eq_constraintsletenforce_leq_variance_instances=Variance.leq_constraintsletsubst_instance_levelsl=matchl.Level.datawith|Level.Varn->s.(n)|_->lletsubst_instance_instancesi=Array.Smart.map(funl->subst_instance_levelsl)iletsubst_instance_universesu=letfx=Universe.Expr.map(funu->subst_instance_levelsu)xinletu'=List.Smart.mapfuinifu==u'thenuelseUniverse.sortu'letsubst_instance_constraints(u,d,vasc)=letu'=subst_instance_levelsuinletv'=subst_instance_levelsvinifu'==u&&v'==vthencelse(u',d,v')letsubst_instance_constraintsscsts=Constraints.fold(funccsts->Constraints.add(subst_instance_constraintsc)csts)cstsConstraints.emptytype'apuniverses='a*Instance.tletout_punivs(x,_y)=xletin_punivsx=(x,Instance.empty)leteq_puniversesf(x,u)(y,u')=fxy&&Instance.equaluu'(** A context of universe levels with universe constraints,
representing local universe variables and constraints *)moduleUContext=structtypet=Names.Name.tarray*Instance.tconstrainedletmakenames(univs,_asx)=assert(Array.lengthnames=Array.lengthunivs);assert(Array.for_all(funu->not(Level.is_smallu))univs);(names,x)(** Universe contexts (variables as a list) *)letempty=([||],(Instance.empty,Constraints.empty))letis_empty(_,(univs,cst))=Instance.is_emptyunivs&&Constraints.is_emptycstletprprl?variance(_,(univs,cst)asctx)=ifis_emptyctxthenmt()elseh(Instance.prprl?varianceunivs++str" |= ")++h(v0(Constraints.prprlcst))lethcons(names,(univs,cst))=(Array.mapNames.Name.hconsnames,(Instance.hconsunivs,hcons_constraintscst))letnames(names,_)=namesletinstance(_,(univs,_cst))=univsletconstraints(_,(_univs,cst))=cstletunion(na,(univs,cst))(na',(univs',cst'))=Array.appendnana',(Instance.appendunivsunivs',Constraints.unioncstcst')letsize(_,(x,_))=Instance.lengthxletrefine_namesnames'(names,x)=letmerge_names=Array.map2Names.(funoldrefined->matchrefinedwithAnonymous->old|Name_->refined)in(merge_namesnamesnames',x)endtypeuniverse_context=UContext.tlethcons_universe_context=UContext.hconsmoduleAbstractContext=structtypet=Names.Name.tarrayconstrainedletmakenamescsts:t=names,cstsletrepr(inst,cst)=(inst,(Array.init(Array.lengthinst)(funi->Level.vari),cst))letprf?variancectx=UContext.prf?variance(reprctx)letinstantiateinst(u,cst)=assert(Array.lengthu=Array.lengthinst);subst_instance_constraintsinstcstletnames(nas,_)=naslethcons(univs,cst)=(Array.mapNames.Name.hconsunivs,hcons_constraintscst)letempty=([||],Constraints.empty)letis_empty(nas,cst)=Array.is_emptynas&&Constraints.is_emptycstletunion(nas,cst)(nas',cst')=(Array.appendnasnas',Constraints.unioncstcst')letsize(nas,_)=Array.lengthnasendtype'auniv_abstracted={univ_abstracted_value:'a;univ_abstracted_binder:AbstractContext.t;}letmap_univ_abstractedf{univ_abstracted_value;univ_abstracted_binder}=letuniv_abstracted_value=funiv_abstracted_valuein{univ_abstracted_value;univ_abstracted_binder}lethcons_abstract_universe_context=AbstractContext.hcons(** 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'letsort_levelsa=Array.sortLevel.comparea;aletto_contextf(ctx,cst)=letinst=Instance.of_array(sort_levels(Array.of_list(Level.Set.elementsctx)))in(finst,(inst,cst))letof_context(_,(ctx,cst))=(Instance.levelsctx,cst)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='a*universe_contexttype'ain_universe_context_set='a*universe_context_setletextend_in_context_set(a,ctx)ctx'=(a,ContextSet.unionctxctx')(** 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_instancesubsti=leti'=Instance.subst_fn(subst_univs_level_levelsubst)iinifi==i'thenielsei'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.emptyletsubst_univs_level_abstract_universe_contextsubst(inst,csts)=inst,subst_univs_level_constraintssubstcstsletmake_instance_substi=letarr=Instance.to_arrayiinArray.fold_left_i(funiaccl->Level.Map.addl(Level.vari)acc)Level.Map.emptyarrletmake_abstract_instance(ctx,_)=Array.init(Array.lengthctx)(funi->Level.vari)letabstract_universesuctx=letnas=UContext.namesuctxinletinstance=UContext.instanceuctxinlet()=assert(Int.equal(Array.lengthnas)(Instance.lengthinstance))inletsubst=make_instance_substinstanceinletcstrs=subst_univs_level_constraintssubst(UContext.constraintsuctx)inletctx=(nas,cstrs)ininstance,ctxletreccompact_univsvarsiu=matchuwith|[]->(s,List.revvars)|(lvl,_)::u->matchLevel.var_indexlvlwith|Somekwhennot(Level.Map.memlvls)->letlvl'=Level.variincompact_univ(Level.Map.addlvllvl's)(k::vars)(i+1)u|_->compact_univsvarsiuletcompact_univu=let(s,s')=compact_univLevel.Map.empty[]0uin(subst_univs_level_universesu,s')(** Pretty-printing *)letpr_constraintsprl=Constraints.prprlletpr_universe_context=UContext.prletpr_abstract_universe_context=AbstractContext.prletpr_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