1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114(************************************************************************)(* * 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenDeclarationsopenEntriesopenLibnamesopenLibobjectopenMod_subst(** {6 Inlining levels} *)(** Rigid / flexible module signature *)type'amodule_signature=|Enforceof'a(** ... : T *)|Checkof'alist(** ... <: T1 <: T2, possibly empty *)(** Which module inline annotations should we honor,
either None or the ones whose level is less or equal
to the given integer *)typeinline=|NoInline|DefaultInline|InlineAtofintletdefault_inline()=Some(Flags.get_inline_level())letinl2intopt=function|NoInline->None|InlineAti->Somei|DefaultInline->default_inline()(** ModSubstObjs : a cache of module substitutive objects
This table is common to modules and module types.
- For a Module M:=N, the objects of N will be reloaded
with M after substitution.
- For a Module M:SIG:=..., the module M gets its objects from SIG
Invariants:
- A alias (i.e. a module path inside a Ref constructor) should
never lead to another alias, but rather to a concrete Objs
constructor.
We will plug later a handler dealing with missing entries in the
cache. Such missing entries may come from inner parts of module
types, which aren't registered by the standard libobject machinery.
*)moduleModSubstObjs:sigvalset:ModPath.t->substitutive_objects->unitvalget:ModPath.t->substitutive_objectsvalset_missing_handler:(ModPath.t->substitutive_objects)->unitend=structlettable=Summary.ref(MPmap.empty:substitutive_objectsMPmap.t)~name:"MODULE-SUBSTOBJS"letmissing_handler=ref(funmp->assertfalse)letset_missing_handlerf=(missing_handler:=f)letsetmpobjs=(table:=MPmap.addmpobjs!table)letgetmp=tryMPmap.findmp!tablewithNot_found->!missing_handlermpend(** Some utilities about substitutive objects :
substitution, expansion *)letsobjs_no_functor(mbids,_)=List.is_emptymbidsletsubst_filteredsub(f,mp)=letf=matchfwith|Unfiltered->Unfiltered|Namesns->letmoduleNSet=Globnames.ExtRefSetinletns=NSet.fold(funnns->NSet.add(Globnames.subst_extended_referencesubn)ns)nsNSet.emptyinNamesnsinf,subst_mpsubmpletrecsubst_aobjssub=function|Objsoasobjs->leto'=subst_objectssuboinifo==o'thenobjselseObjso'|Ref(mp,sub0)asr->letsub0'=joinsub0subinifsub0'==sub0thenrelseRef(mp,sub0')andsubst_sobjssub(mbids,aobjsassobjs)=letaobjs'=subst_aobjssubaobjsinifaobjs'==aobjsthensobjselse(mbids,aobjs')andsubst_objectssubstseg=letsubst_one(id,objasnode)=matchobjwith|AtomicObjectobj->letobj'=Libobject.subst_object(subst,obj)inifobj'==objthennodeelse(id,AtomicObjectobj')|ModuleObjectsobjs->letsobjs'=subst_sobjssubstsobjsinifsobjs'==sobjsthennodeelse(id,ModuleObjectsobjs')|ModuleTypeObjectsobjs->letsobjs'=subst_sobjssubstsobjsinifsobjs'==sobjsthennodeelse(id,ModuleTypeObjectsobjs')|IncludeObjectaobjs->letaobjs'=subst_aobjssubstaobjsinifaobjs'==aobjsthennodeelse(id,IncludeObjectaobjs')|ExportObject{mpl}->letmpl'=List.Smart.map(subst_filteredsubst)mplinifmpl'==mplthennodeelse(id,ExportObject{mpl=mpl'})|KeepObject_->assertfalseinList.Smart.mapsubst_onesegletexpand_aobjs=function|Objso->o|Ref(mp,sub)->matchModSubstObjs.getmpwith|(_,Objso)->subst_objectssubo|_->assertfalse(* Invariant : any alias points to concrete objs *)letexpand_sobjs(_,aobjs)=expand_aobjsaobjs(** {6 ModObjs : a cache of module objects}
For each module, we also store a cache of
"prefix", "substituted objects", "keep objects".
This is used for instance to implement the "Import" command.
substituted objects :
roughly the objects above after the substitution - we need to
keep them to call open_object when the module is opened (imported)
keep objects :
The list of non-substitutive objects - as above, for each of
them we will call open_object when the module is opened
(Some) Invariants:
* If the module is a functor, it won't appear in this cache.
* Module objects in substitutive_objects part have empty substituted
objects.
* Modules which where created with Module M:=mexpr or with
Module M:SIG. ... End M. have the keep list empty.
*)typemodule_objects={module_prefix:Nametab.object_prefix;module_substituted_objects:Lib.lib_objects;module_keep_objects:Lib.lib_objects;}moduleModObjs:sigvalset:ModPath.t->module_objects->unitvalget:ModPath.t->module_objects(* may raise Not_found *)valall:unit->module_objectsMPmap.tend=structlettable=Summary.ref(MPmap.empty:module_objectsMPmap.t)~name:"MODULE-OBJS"letsetmpobjs=(table:=MPmap.addmpobjs!table)letgetmp=MPmap.findmp!tableletall()=!tableend(** {6 Name management}
Auxiliary functions to transform full_path and kernel_name given
by Lib into ModPath.t and DirPath.t needed for modules
*)letmp_of_knkn=letmp,l=KerName.reprkninMPdot(mp,l)letdir_of_spsp=letdir,id=repr_pathspinadd_dirpath_suffixdirid(** {6 Declaration of module substitutive objects} *)(** These functions register the visibility of the module and iterates
through its components. They are called by plenty of module functions *)letconsistency_checksexistsdirdirinfo=ifexiststhenletglobref=tryNametab.locate_dir(qualid_of_dirpathdir)withNot_found->user_err~hdr:"consistency_checks"(DirPath.printdir++str" should already exist!")inassert(Nametab.GlobDirRef.equalglobrefdirinfo)elseifNametab.exists_dirdirthenuser_err~hdr:"consistency_checks"(DirPath.printdir++str" already exists.")letcompute_visibilityexistsi=ifexiststhenNametab.ExactlyielseNametab.Untili(** Iterate some function [iter_objects] on all components of a module *)letdo_moduleexistsiter_objectsiobj_dirobj_mpsobjskobjs=letprefix=Nametab.{obj_dir;obj_mp;}inletdirinfo=Nametab.GlobDirRef.DirModuleprefixinconsistency_checksexistsobj_dirdirinfo;Nametab.push_dir(compute_visibilityexistsi)obj_dirdirinfo;ModSubstObjs.setobj_mpsobjs;(* If we're not a functor, let's iter on the internal components *)ifsobjs_no_functorsobjsthenbeginletobjs=expand_sobjssobjsinletmodule_objects={module_prefix=prefix;module_substituted_objects=objs;module_keep_objects=kobjs;}inModObjs.setobj_mpmodule_objects;iter_objects(i+1)prefixobjs;iter_objects(i+1)prefixkobjsendletdo_module'existsiter_objectsi((sp,kn),sobjs)=do_moduleexistsiter_objectsi(dir_of_spsp)(mp_of_knkn)sobjs[](** Nota: Interactive modules and module types cannot be recached!
This used to be checked here via a flag along the substobjs. *)(** {6 Declaration of module type substitutive objects} *)(** Nota: Interactive modules and module types cannot be recached!
This used to be checked more properly here. *)letload_modtypeispmpsobjs=ifNametab.exists_modtypespthenanomaly(pr_pathsp++str" already exists.");Nametab.push_modtype(Nametab.Untili)spmp;ModSubstObjs.setmpsobjs(** {6 Declaration of substitutive objects for Include} *)letrecload_objecti(name,obj)=matchobjwith|AtomicObjecto->Libobject.load_objecti(name,o)|ModuleObjectsobjs->do_module'falseload_objectsi(name,sobjs)|ModuleTypeObjectsobjs->let(sp,kn)=nameinload_modtypeisp(mp_of_knkn)sobjs|IncludeObjectaobjs->load_includei(name,aobjs)|ExportObject_->()|KeepObjectobjs->load_keepi(name,objs)andload_objectsiprefixobjs=List.iter(fun(id,obj)->load_objecti(Lib.make_onameprefixid,obj))objsandload_includei((sp,kn),aobjs)=letobj_dir=Libnames.dirpathspinletobj_mp=KerName.modpathkninletprefix=Nametab.{obj_dir;obj_mp;}inleto=expand_aobjsaobjsinload_objectsiprefixoandload_keepi((sp,kn),kobjs)=(* Invariant : seg isn't empty *)letobj_dir=dir_of_spspandobj_mp=mp_of_knkninletprefix=Nametab.{obj_dir;obj_mp;}inletmodobjs=tryModObjs.getobj_mpwithNot_found->assertfalse(* a substobjs should already be loaded *)inassertNametab.(eq_opmodobjs.module_prefixprefix);assert(List.is_emptymodobjs.module_keep_objects);ModObjs.setobj_mp{modobjswithmodule_keep_objects=kobjs};load_objectsiprefixkobjs(** {6 Implementation of Import and Export commands} *)letmark_objectfobj(exports,acc)=(exports,(f,obj)::acc)letreccollect_modulesmplacc=List.fold_left(funaccfmp->collect_modulefmpacc)acc(List.revmpl)andcollect_module(f,mp)acc=(* May raise Not_found for unknown module and for functors *)letmodobjs=ModObjs.getmpinletprefix=modobjs.module_prefixinletacc=collect_objectsf1prefixmodobjs.module_keep_objectsaccincollect_objectsf1prefixmodobjs.module_substituted_objectsaccandcollect_objectfi(name,objaso)acc=matchobjwith|ExportObject{mpl}->collect_exportsfimplacc|AtomicObject_|IncludeObject_|KeepObject_|ModuleObject_|ModuleTypeObject_->mark_objectfoaccandcollect_objectsfiprefixobjsacc=List.fold_left(funacc(id,obj)->collect_objectfi(Lib.make_onameprefixid,obj)acc)acc(List.revobjs)andcollect_exportf(f',mp)(exports,objsasacc)=matchfilter_andff'with|None->acc|Somef->letexports'=MPmap.updatemp(function|None->Somef|Somef0->Some(filter_orff0))exportsin(* If the map doesn't change there is nothing new to export.
It's possible that [filter_and] or [filter_or] mangled precise
filters such that we repeat uselessly, but the important
[Unfiltered] case is handled correctly.
*)ifexports==exports'thenaccelsecollect_module(f,mp)(exports',objs)andcollect_exportsfimplacc=ifInt.equali1thenList.fold_left(funaccfmp->collect_exportffmpacc)acc(List.revmpl)elseaccletopen_modtypei((sp,kn),_)=letmp=mp_of_knkninletmp'=tryNametab.locate_modtype(qualid_of_pathsp)withNot_found->anomaly(pr_pathsp++str" should already exist!");inassert(ModPath.equalmpmp');Nametab.push_modtype(Nametab.Exactlyi)spmpletrecopen_objectfi(name,obj)=matchobjwith|AtomicObjecto->Libobject.open_objectfi(name,o)|ModuleObjectsobjs->letdir=dir_of_sp(fstname)inletmp=mp_of_kn(sndname)inopen_modulefidirmpsobjs|ModuleTypeObjectsobjs->open_modtypei(name,sobjs)|IncludeObjectaobjs->open_includefi(name,aobjs)|ExportObject{mpl}->open_exportfimpl|KeepObjectobjs->open_keepfi(name,objs)andopen_modulefiobj_dirobj_mpsobjs=letprefix=Nametab.{obj_dir;obj_mp;}inletdirinfo=Nametab.GlobDirRef.DirModuleprefixinconsistency_checkstrueobj_dirdirinfo;(matchfwith|Unfiltered->Nametab.push_dir(Nametab.Exactlyi)obj_dirdirinfo|Names_->());(* If we're not a functor, let's iter on the internal components *)ifsobjs_no_functorsobjsthenbeginletmodobjs=ModObjs.getobj_mpinopen_objectsf(i+1)modobjs.module_prefixmodobjs.module_substituted_objectsendandopen_objectsfiprefixobjs=List.iter(fun(id,obj)->open_objectfi(Lib.make_onameprefixid,obj))objsandopen_includefi((sp,kn),aobjs)=letobj_dir=Libnames.dirpathspinletobj_mp=KerName.modpathkninletprefix=Nametab.{obj_dir;obj_mp;}inleto=expand_aobjsaobjsinopen_objectsfiprefixoandopen_exportfimpl=let_,objs=collect_exportsfimpl(MPmap.empty,[])inList.iter(fun(f,o)->open_objectf1o)objsandopen_keepfi((sp,kn),kobjs)=letobj_dir=dir_of_spspandobj_mp=mp_of_knkninletprefix=Nametab.{obj_dir;obj_mp;}inopen_objectsfiprefixkobjsletreccache_object(name,obj)=matchobjwith|AtomicObjecto->Libobject.cache_object(name,o)|ModuleObjectsobjs->do_module'falseload_objects1(name,sobjs)|ModuleTypeObjectsobjs->let(sp,kn)=nameinload_modtype0sp(mp_of_knkn)sobjs|IncludeObjectaobjs->cache_include(name,aobjs)|ExportObject{mpl}->anomalyPp.(str"Export should not be cached")|KeepObjectobjs->cache_keep(name,objs)andcache_include((sp,kn),aobjs)=letobj_dir=Libnames.dirpathspinletobj_mp=KerName.modpathkninletprefix=Nametab.{obj_dir;obj_mp;}inleto=expand_aobjsaobjsinload_objects1prefixo;open_objectsUnfiltered1prefixoandcache_keep((sp,kn),kobjs)=anomaly(Pp.str"This module should not be cached!")(* Adding operations with containers *)letadd_leafidobj=ifModPath.equal(Lib.current_mp())ModPath.initialthenuser_errPp.(str"No session module started (use -top dir)");letoname=Lib.make_fonameidincache_object(oname,obj);Lib.add_entryoname(Lib.Leafobj);onameletadd_leavesidobjs=letoname=Lib.make_fonameidinletadd_objobj=Lib.add_entryoname(Lib.Leafobj);load_object1(oname,obj)inList.iteradd_objobjs;oname(** {6 Handler for missing entries in ModSubstObjs} *)(** Since the inner of Module Types are not added by default to
the ModSubstObjs table, we compensate this by explicit traversal
of Module Types inner objects when needed. Quite a hack... *)letmp_idmpid=MPdot(mp,Label.of_idid)letrecregister_mod_objsmp(id,obj)=matchobjwith|ModuleObjectsobjs->ModSubstObjs.set(mp_idmpid)sobjs|ModuleTypeObjectsobjs->ModSubstObjs.set(mp_idmpid)sobjs|IncludeObjectaobjs->List.iter(register_mod_objsmp)(expand_aobjsaobjs)|_->()lethandle_missing_substobjsmp=matchmpwith|MPdot(mp',l)->letobjs=expand_sobjs(ModSubstObjs.getmp')inList.iter(register_mod_objsmp')objs;ModSubstObjs.getmp|_->assertfalse(* Only inner parts of module types should be missing *)let()=ModSubstObjs.set_missing_handlerhandle_missing_substobjs(** {6 From module expression to substitutive objects} *)(** Turn a chain of [MSEapply] into the head ModPath.t and the
list of ModPath.t parameters (deepest param coming first).
The left part of a [MSEapply] must be either [MSEident] or
another [MSEapply]. *)letget_applicationsmexpr=letrecgetparams=function|MEidentmp->mp,params|MEapply(fexpr,mp)->get(mp::params)fexpr|MEwith_->user_errPp.(str"Non-atomic functor application.")inget[]mexpr(** Create the substitution corresponding to some functor applications *)letreccompute_substenvmbidssignmp_linl=matchmbids,mp_lwith|_,[]->mbids,empty_subst|[],r->user_errPp.(str"Application of a functor with too few arguments.")|mbid::mbids,mp::mp_l->letfarg_id,farg_b,fbody_b=Modops.destr_functorsigninletmb=Environ.lookup_modulempenvinletmbid_left,subst=compute_substenvmbidsfbody_bmp_linlinletresolver=ifModops.is_functormb.mod_typethenempty_delta_resolverelseModops.inline_delta_resolverenvinlmpfarg_idfarg_bmb.mod_deltainmbid_left,join(map_mbidmbidmpresolver)subst(** Create the objects of a "with Module" structure. *)letrecreplace_module_objectidlmp0objs0mp1objs1=matchidl,objs0with|_,[]->[]|id::idl,(id',obj)::tailwhenId.equalidid'->beginmatchobjwith|ModuleObjectsobjs->letmp_id=MPdot(mp0,Label.of_idid)inletobjs=matchidlwith|[]->subst_objects(map_mpmp1mp_idempty_delta_resolver)objs1|_->letobjs_id=expand_sobjssobjsinreplace_module_objectidlmp_idobjs_idmp1objs1in(id,ModuleObject([],Objsobjs))::tail|_->assertfalseend|idl,lobj::tail->lobj::replace_module_objectidlmp0tailmp1objs1lettype_of_modmpenv=function|true->(Environ.lookup_modulempenv).mod_type|false->(Environ.lookup_modtypempenv).mod_typeletrecget_module_path=function|MEidentmp->mp|MEwith(me,_)->get_module_pathme|MEapply(me,_)->get_module_pathme(** Substitutive objects of a module expression (or module type) *)letrecget_module_sobjsis_modenvinl=function|MEidentmp->beginmatchModSubstObjs.getmpwith|(mbids,Objs_)whennot(ModPath.is_boundmp)->(mbids,Ref(mp,empty_subst))(* we create an alias *)|sobjs->sobjsend|MEwith(mty,WithDef_)->get_module_sobjsis_modenvinlmty|MEwith(mty,WithMod(idl,mp1))->assert(notis_mod);letsobjs0=get_module_sobjsis_modenvinlmtyinassert(sobjs_no_functorsobjs0);(* For now, we expanse everything, to be safe *)letmp0=get_module_pathmtyinletobjs0=expand_sobjssobjs0inletobjs1=expand_sobjs(ModSubstObjs.getmp1)in([],Objs(replace_module_objectidlmp0objs0mp1objs1))|MEapply_asme->letmp1,mp_l=get_applicationsmeinletmbids,aobjs=get_module_sobjsis_modenvinl(MEidentmp1)inlettyp=type_of_modmp1envis_modinletmbids_left,subst=compute_substenvmbidstypmp_linlin(mbids_left,subst_aobjssubstaobjs)letget_functor_sobjsis_modenvinl(params,mexpr)=let(mbids,aobjs)=get_module_sobjsis_modenvinlmexprin(List.mapfstparams@mbids,aobjs)(** {6 Handling of module parameters} *)(** For printing modules, [process_module_binding] adds names of
bound module (and its components) to Nametab. It also loads
objects associated to it. *)letprocess_module_bindingmbidme=letdir=DirPath.make[MBId.to_idmbid]inletmp=MPboundmbidinletsobjs=get_module_sobjsfalse(Global.env())(default_inline())meinletsubst=map_mp(get_module_pathme)mpempty_delta_resolverinletsobjs=subst_sobjssubstsobjsindo_modulefalseload_objects1dirmpsobjs[](** Process a declaration of functor parameter(s) (Id1 .. Idn : Typ)
i.e. possibly multiple names with the same module type.
Global environment is updated on the fly.
Objects in these parameters are also loaded.
Output is accumulated on top of [acc] (in reverse order). *)letintern_arg(acc,cst)(idl,(typ,ann))=letinl=inl2intoptanninletlib_dir=Lib.library_dp()inletenv=Global.env()inlet(mty,_,cst')=Modintern.interp_module_astenvModintern.ModTypetypinlet()=Global.push_context_set~strict:truecst'inletenv=Global.env()inletsobjs=get_module_sobjsfalseenvinlmtyinletmp0=get_module_pathmtyinletfoldacc{CAst.v=id}=letdir=DirPath.make[id]inletmbid=MBId.makelib_diridinletmp=MPboundmbidinletresolver=Global.add_module_parametermbidmtyinlinletsobjs=subst_sobjs(map_mpmp0mpresolver)sobjsindo_modulefalseload_objects1dirmpsobjs[];(mbid,mty,inl)::accinletacc=List.fold_leftfoldaccidlin(acc,Univ.ContextSet.unioncstcst')(** Process a list of declarations of functor parameters
(Id11 .. Id1n : Typ1)..(Idk1 .. Idkm : Typk)
Global environment is updated on the fly.
The calls to [interp_modast] should be interleaved with these
env updates, otherwise some "with Definition" could be rejected.
Returns a list of mbids and entries (in reversed order).
This used to be a [List.concat (List.map ...)], but this should
be more efficient and independent of [List.map] eval order.
*)letintern_argsparams=List.fold_leftintern_arg([],Univ.ContextSet.empty)params(** {6 Auxiliary functions concerning subtyping checks} *)letcheck_submtbsub_mtb_l=(* The constraints are checked and forgot immediately : *)ignore(List.fold_right(funsub_mtbenv->Environ.add_constraints(Subtyping.check_subtypesenvmtbsub_mtb)env)sub_mtb_l(Global.env()))(** This function checks if the type calculated for the module [mp] is
a subtype of all signatures in [sub_mtb_l]. Uses only the global
environment. *)letcheck_subtypesmpsub_mtb_l=letmb=tryGlobal.lookup_modulempwithNot_found->assertfalseinletmtb=Modops.module_type_of_modulembincheck_submtbsub_mtb_l(** Same for module type [mp] *)letcheck_subtypes_mtmpsub_mtb_l=letmtb=tryGlobal.lookup_modtypempwithNot_found->assertfalseincheck_submtbsub_mtb_l(** Create a params entry.
In [args], the youngest module param now comes first. *)letmk_params_entryargs=List.rev_map(fun(mbid,arg_t,_)->(mbid,arg_t))args(** Create a functor type struct.
In [args], the youngest module param now comes first. *)letmk_funct_typeenvargsseb0=List.fold_left(fun(seb,cst)(arg_id,arg_t,arg_inl)->letmp=MPboundarg_idinletarg_t,cst'=Mod_typing.translate_modtypeenvmparg_inl([],arg_t)inMoreFunctor(arg_id,arg_t,seb),Univ.Constraint.unioncstcst')seb0args(** Prepare the module type list for check of subtypes *)letbuild_subtypesenvmpargsmtys=let(ctx,ans)=List.fold_left_map(functx(m,ann)->letinl=inl2intoptanninletmte,_,ctx'=Modintern.interp_module_astenvModintern.ModTypeminletenv=Environ.push_context_set~strict:truectx'envinletctx=Univ.ContextSet.unionctxctx'inletmtb,cst=Mod_typing.translate_modtypeenvmpinl([],mte)inletmod_type,cst=mk_funct_typeenvargs(mtb.mod_type,cst)inletctx=Univ.ContextSet.add_constraintscstctxinctx,{mtbwithmod_type})Univ.ContextSet.emptymtysin(ans,ctx)(** {6 Current module information}
This information is stored by each [start_module] for use
in a later [end_module]. *)typecurrent_module_info={cur_typ:(module_struct_entry*intoption)option;(** type via ":" *)cur_typs:module_type_bodylist(** types via "<:" *)}letdefault_module_info={cur_typ=None;cur_typs=[]}letopenmod_info=Summary.refdefault_module_info~name:"MODULE-INFO"(** {6 Current module type information}
This information is stored by each [start_modtype] for use
in a later [end_modtype]. *)letopenmodtype_info=Summary.ref([]:module_type_bodylist)~name:"MODTYPE-INFO"(** {6 Modules : start, end, declare} *)moduleRawModOps=structletstart_moduleexportidargsresfs=letmp=Global.start_moduleidinletarg_entries_r,ctx=intern_argsargsinlet()=Global.push_context_set~strict:truectxinletenv=Global.env()inletres_entry_o,subtyps,ctx=matchreswith|Enforce(res,ann)->letinl=inl2intoptanninlet(mte,_,ctx)=Modintern.interp_module_astenvModintern.ModTyperesinletenv=Environ.push_context_set~strict:truectxenvin(* We check immediately that mte is well-formed *)let_,_,_,cst=Mod_typing.translate_mseenvNoneinlmteinletctx=Univ.ContextSet.add_constraintscstctxinSome(mte,inl),[],ctx|Checkresl->lettyps,ctx=build_subtypesenvmparg_entries_rreslinNone,typs,ctxinlet()=Global.push_context_set~strict:truectxinopenmod_info:={cur_typ=res_entry_o;cur_typs=subtyps};letprefix=Lib.start_moduleexportidmpfsinNametab.(push_dir(Until1)(prefix.obj_dir)(GlobDirRef.DirOpenModuleprefix));mpletend_module()=letoldoname,oldprefix,fs,lib_stack=Lib.end_module()inletsubstitute,keep,special=Lib.classify_segmentlib_stackinletm_info=!openmod_infoin(* For sealed modules, we use the substitutive objects of their signatures *)letsobjs0,keep,special=matchm_info.cur_typwith|None->([],Objssubstitute),keep,special|Some(mty,inline)->get_module_sobjsfalse(Global.env())inlinemty,[],[]inletid=basename(fstoldoname)inletmp,mbids,resolver=Global.end_modulefsidm_info.cur_typinletsobjs=let(ms,objs)=sobjs0in(mbids@ms,objs)incheck_subtypesmpm_info.cur_typs;(* We substitute objects if the module is sealed by a signature *)letsobjs=matchm_info.cur_typwith|None->sobjs|Some(mty,_)->subst_sobjs(map_mp(get_module_pathmty)mpresolver)sobjsinletnode=ModuleObjectsobjsin(* We add the keep objects, if any, and if this isn't a functor *)letobjects=matchkeep,mbidswith|[],_|_,_::_->special@[node]|_->special@[node;KeepObjectkeep]inletnewoname=add_leavesidobjectsin(* Name consistency check : start_ vs. end_module, kernel vs. library *)assert(eq_full_path(fstnewoname)(fstoldoname));assert(ModPath.equal(mp_of_kn(sndnewoname))mp);mp(* TODO cleanup push universes directly to global env *)letdeclare_moduleidargsresmexpr_ofs=(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp=Global.start_moduleidinletarg_entries_r,ctx=intern_argsargsinletparams=mk_params_entryarg_entries_rinletenv=Global.env()inletenv=Environ.push_context_set~strict:truectxenvinletmty_entry_o,subs,inl_res,ctx'=matchreswith|Enforce(mty,ann)->letinl=inl2intoptanninlet(mte,_,ctx)=Modintern.interp_module_astenvModintern.ModTypemtyinletenv=Environ.push_context_set~strict:truectxenvin(* We check immediately that mte is well-formed *)let_,_,_,cst=Mod_typing.translate_mseenvNoneinlmteinletctx=Univ.ContextSet.add_constraintscstctxinSomemte,[],inl,ctx|Checkmtys->lettyps,ctx=build_subtypesenvmparg_entries_rmtysinNone,typs,default_inline(),ctxinletenv=Environ.push_context_set~strict:truectx'envinletctx=Univ.ContextSet.unionctxctx'inletmexpr_entry_o,inl_expr,ctx'=matchmexpr_owith|None->None,default_inline(),Univ.ContextSet.empty|Some(mexpr,ann)->let(mte,_,ctx)=Modintern.interp_module_astenvModintern.ModulemexprinSomemte,inl2intoptann,ctxinletenv=Environ.push_context_set~strict:truectx'envinletctx=Univ.ContextSet.unionctxctx'inletentry=matchmexpr_entry_o,mty_entry_owith|None,None->assertfalse(* No body, no type ... *)|None,Sometyp->MType(params,typ)|Somebody,otyp->MExpr(params,body,otyp)inletsobjs,mp0=matchentrywith|MType(_,mte)|MExpr(_,_,Somemte)->get_functor_sobjsfalseenvinl_res(params,mte),get_module_pathmte|MExpr(_,me,None)->get_functor_sobjstrueenvinl_expr(params,me),get_module_pathmein(* Undo the simulated interactive building of the module
and declare the module as a whole *)Summary.unfreeze_summariesfs;letinl=matchinl_exprwith|None->None|_->inl_resinlet()=Global.push_context_set~strict:truectxinletmp_env,resolver=Global.add_moduleidentryinlin(* Name consistency check : kernel vs. library *)assert(ModPath.equalmp(mp_of_kn(Lib.make_knid)));assert(ModPath.equalmpmp_env);check_subtypesmpsubs;letsobjs=subst_sobjs(map_mpmp0mpresolver)sobjsinignore(add_leafid(ModuleObjectsobjs));mpend(** {6 Module types : start, end, declare} *)moduleRawModTypeOps=structletstart_modtypeidargsmtysfs=letmp=Global.start_modtypeidinletarg_entries_r,cst=intern_argsargsinlet()=Global.push_context_set~strict:truecstinletenv=Global.env()inletsub_mty_l,cst=build_subtypesenvmparg_entries_rmtysinlet()=Global.push_context_set~strict:truecstinopenmodtype_info:=sub_mty_l;letprefix=Lib.start_modtypeidmpfsinNametab.(push_dir(Until1)(prefix.obj_dir)(GlobDirRef.DirOpenModtypeprefix));mpletend_modtype()=letoldoname,prefix,fs,lib_stack=Lib.end_modtype()inletid=basename(fstoldoname)inletsubstitute,_,special=Lib.classify_segmentlib_stackinletsub_mty_l=!openmodtype_infoinletmp,mbids=Global.end_modtypefsidinletmodtypeobjs=(mbids,Objssubstitute)incheck_subtypes_mtmpsub_mty_l;letoname=add_leavesid(special@[ModuleTypeObjectmodtypeobjs])in(* Check name consistence : start_ vs. end_modtype, kernel vs. library *)assert(eq_full_path(fstoname)(fstoldoname));assert(ModPath.equal(mp_of_kn(sndoname))mp);mpletdeclare_modtypeidargsmtys(mty,ann)fs=letinl=inl2intoptannin(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp=Global.start_modtypeidinletarg_entries_r,arg_ctx=intern_argsargsinlet()=Global.push_context_set~strict:truearg_ctxinletparams=mk_params_entryarg_entries_rinletenv=Global.env()inletmte,_,mte_ctx=Modintern.interp_module_astenvModintern.ModTypemtyinlet()=Global.push_context_set~strict:truemte_ctxinletenv=Global.env()in(* We check immediately that mte is well-formed *)let_,_,_,mte_cst=Mod_typing.translate_mseenvNoneinlmteinlet()=Global.push_context_set~strict:true(Univ.LSet.empty,mte_cst)inletenv=Global.env()inletentry=params,mteinletsub_mty_l,sub_mty_ctx=build_subtypesenvmparg_entries_rmtysinlet()=Global.push_context_set~strict:truesub_mty_ctxinletenv=Global.env()inletsobjs=get_functor_sobjsfalseenvinlentryinletsubst=map_mp(get_module_path(sndentry))mpempty_delta_resolverinletsobjs=subst_sobjssubstsobjsin(* Undo the simulated interactive building of the module type
and declare the module type as a whole *)Summary.unfreeze_summariesfs;(* We enrich the global environment *)let()=Global.push_context_set~strict:truearg_ctxinlet()=Global.push_context_set~strict:truemte_ctxinlet()=Global.push_context_set~strict:true(Univ.LSet.empty,mte_cst)inlet()=Global.push_context_set~strict:truesub_mty_ctxinletmp_env=Global.add_modtypeidentryinlin(* Name consistency check : kernel vs. library *)assert(ModPath.equalmp_envmp);(* Subtyping checks *)check_subtypes_mtmpsub_mty_l;ignore(add_leafid(ModuleTypeObjectsobjs));mpend(** {6 Include} *)moduleRawIncludeOps=structletrecinclude_substenvmpresombidssigninline=matchmbidswith|[]->empty_subst|mbid::mbids->letfarg_id,farg_b,fbody_b=Modops.destr_functorsigninletsubst=include_substenvmpresombidsfbody_binlineinletmp_delta=Modops.inline_delta_resolverenvinlinempfarg_idfarg_bresoinjoin(map_mbidmbidmpmp_delta)substletrecdecompose_functormpltyp=matchmpl,typwith|[],_->typ|_::mpl,MoreFunctor(_,_,str)->decompose_functormplstr|_->user_errPp.(str"Application of a functor with too much arguments.")exceptionNoIncludeSelflettype_of_inclenvis_mod=function|MEidentmp->type_of_modmpenvis_mod|MEapply_asme->letmp0,mp_l=get_applicationsmeindecompose_functormp_l(type_of_modmp0envis_mod)|MEwith_->raiseNoIncludeSelfletdeclare_one_include(me_ast,annot)=letenv=Global.env()inletme,kind,cst=Modintern.interp_module_astenvModintern.ModAnyme_astinlet()=Global.push_context_set~strict:truecstinletenv=Global.env()inletis_mod=(kind==Modintern.Module)inletcur_mp=Lib.current_mp()inletinl=inl2intoptannotinletmbids,aobjs=get_module_sobjsis_modenvinlmeinletsubst_self=tryifList.is_emptymbidsthenraiseNoIncludeSelf;lettyp=type_of_inclenvis_modmeinletreso,_=Safe_typing.delta_of_senv(Global.safe_env())ininclude_substenvcur_mpresombidstypinlwithNoIncludeSelf->empty_substinletbase_mp=get_module_pathmeinletresolver=Global.add_includemeis_modinlinletsubst=joinsubst_self(map_mpbase_mpcur_mpresolver)inletaobjs=subst_aobjssubstaobjsinignore(add_leaf(Lib.current_mod_id())(IncludeObjectaobjs))letdeclare_includeme_asts=List.iterdeclare_one_includeme_astsend(** {6 Module operations handling summary freeze/unfreeze} *)letprotect_summariesf=letfs=Summary.freeze_summaries~marshallable:falseintryffswithreraise->(* Something wrong: undo the whole process *)letreraise=Exninfo.capturereraiseinlet()=Summary.unfreeze_summariesfsinExninfo.iraisereraiseletstart_moduleexportidargsres=protect_summaries(RawModOps.start_moduleexportidargsres)letend_module=RawModOps.end_moduleletdeclare_moduleidargsmtysme_l=letdeclare_mefs=matchme_lwith|[]->RawModOps.declare_moduleidargsmtysNonefs|[me]->RawModOps.declare_moduleidargsmtys(Someme)fs|me_l->ignore(RawModOps.start_moduleNoneidargsmtysfs);RawIncludeOps.declare_includeme_l;RawModOps.end_module()inprotect_summariesdeclare_meletstart_modtypeidargsmtys=protect_summaries(RawModTypeOps.start_modtypeidargsmtys)letend_modtype=RawModTypeOps.end_modtypeletdeclare_modtypeidargsmtysmty_l=letdeclare_mtfs=matchmty_lwith|[]->assertfalse|[mty]->RawModTypeOps.declare_modtypeidargsmtysmtyfs|mty_l->ignore(RawModTypeOps.start_modtypeidargsmtysfs);RawIncludeOps.declare_includemty_l;RawModTypeOps.end_modtype()inprotect_summariesdeclare_mtletdeclare_includeme_asts=ifGlobal.sections_are_opened()thenuser_errPp.(str"Include is not allowed inside sections.");protect_summaries(fun_->RawIncludeOps.declare_includeme_asts)(** {6 Libraries} *)typelibrary_name=DirPath.t(** A library object is made of some substitutive objects
and some "keep" objects. *)typelibrary_objects=Lib.lib_objects*Lib.lib_objects(** For the native compiler, we cache the library values *)letregister_librarydircenv(objs:library_objects)digestuniv=letmp=MPfiledirinlet()=try(* Is this library already loaded ? *)ignore(Global.lookup_modulemp);withNot_found->(* If not, let's do it now ... *)letmp'=Global.importcenvunivdigestinifnot(ModPath.equalmpmp')thenanomaly(Pp.str"Unexpected disk module name.");inletsobjs,keepobjs=objsindo_modulefalseload_objects1dirmp([],Objssobjs)keepobjsletstart_librarydir=letmp=Global.start_librarydirinopenmod_info:=default_module_info;Lib.start_compilationdirmpletend_library_hook=refignoreletappend_end_library_hookf=letold_f=!end_library_hookinend_library_hook:=fun()->old_f();f()letend_library?except~output_native_objectsdir=!end_library_hook();letoname=Lib.end_compilation_checksdirinletmp,cenv,ast=Global.export?except~output_native_objectsdirinletprefix,lib_stack=Lib.end_compilationonameinassert(ModPath.equalmp(MPfiledir));letsubstitute,keep,_=Lib.classify_segmentlib_stackincenv,(substitute,keep),astletimport_modules~exportmpl=let_,objs=collect_modulesmpl(MPmap.empty,[])inList.iter(fun(f,o)->open_objectf1o)objs;ifexportthenLib.add_anonymous_entry(Lib.Leaf(ExportObject{mpl}))letimport_modulef~exportmp=import_modules~export[f,mp](** {6 Iterators} *)letiter_all_segmentsf=letrecapply_objprefix(id,obj)=matchobjwith|IncludeObjectaobjs->letobjs=expand_aobjsaobjsinList.iter(apply_objprefix)objs|_->f(Lib.make_onameprefixid)objinletapply_mod_obj_modobjs=letprefix=modobjs.module_prefixinList.iter(apply_objprefix)modobjs.module_substituted_objects;List.iter(apply_objprefix)modobjs.module_keep_objectsinletapply_node=function|sp,Lib.Leafo->fspo|_->()inMPmap.iterapply_mod_obj(ModObjs.all());List.iterapply_node(Lib.contents())(** {6 Some types used to shorten declaremods.mli} *)typemodule_params=(lidentlist*(Constrexpr.module_ast*inline))list(** {6 Debug} *)letdebug_print_modtab_=letpr_seg=function|[]->str"[]"|l->str"[."++int(List.lengthl)++str".]"inletpr_modinfompmodobjss=letobjs=modobjs.module_substituted_objects@modobjs.module_keep_objectsins++str(ModPath.to_stringmp)++(spc())++(pr_seg(Lib.segment_of_objectsmodobjs.module_prefixobjs))inletmodules=MPmap.foldpr_modinfo(ModObjs.all())(mt())inhov0modules