12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055(************************************************************************)(* * 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.processendmoduleRawLevel=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"|UGlobal.(Level{library=d;process=s;uid=n})->Names.DirPath.to_stringd^(ifCString.is_emptysthen""else"."^s)^"."^string_of_intn|Varn->"Var("^string_of_intn^")"letpru=str(to_stringu)letvars=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)extemptyletprfm=h(prlist_with_sepfnl(fun(u,v)->pru++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')elseSuperDiffcmpletto_string(v,n)=ifInt.equaln0thenLevel.to_stringvelseLevel.to_stringv^"+"^string_of_intnletprx=str(to_stringx)letpr_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=tipxletprl=matchlwith|[u]->Expr.pru|_->str"max("++hov0(prlist_with_seppr_commaExpr.prl)++str")"letpr_withfl=matchlwith|[u]->Expr.pr_withfu|_->str"max("++hov0(prlist_with_seppr_comma(Expr.pr_withf)l)++str")"letis_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);(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)letof_instancei=of_set(Instance.levelsi)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'letadd_instanceinst(univs,cst)=letv=Instance.to_arrayinstinletfoldaccuu=Level.Set.adduaccuinletunivs=Array.fold_leftfoldunivsvin(univs,cst)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_subst=Level.Map.pr(funu->str" := "++Level.pru++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.hconsxtypeexplanation=Level.t*(constraint_type*Level.t)list