1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738(************************************************************************)(* * The Rocq Prover / The Rocq 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenDeclarationsopenMod_declarationsopenEntriesopenLibnamesopenLibobjectopenMod_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_level=100let{Goptions.get=default_inline_level}=Goptions.declare_int_option_and_ref~key:["Inline";"Level"]~value:default_inline_level()letdefault_inline_level()=Some(default_inline_level())letinl2intopt=function|NoInline->None|InlineAti->Somei|DefaultInline->default_inline_level()(** These functions register the visibility of the module and iterates
through its components. They are called by plenty of module functions *)letconsistency_checksexistsdir=ifexiststhenlet_=tryNametab.locate_module(qualid_of_pathdir)withNot_found->user_err(pr_pathdir++str" should already exist!")in()elseifNametab.exists_moduledirthenuser_err(pr_pathdir++str" already exists.")letrecget_module_path=function|MEidentmp->mp|MEwith(me,_)->get_module_pathme|MEapply(me,_)->get_module_pathmelettype_of_modmpenv=function|true->mod_type(Environ.lookup_modulempenv)|false->mod_type(Environ.lookup_modtypempenv)(** {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)letpop_pathsp=path_pop_suffixsp,basenamespletpath_of_filedp=matchDirPath.reprdpwith|x::dp->make_path(DirPath.makedp)x|[]->CErrors.anomalyPp.(str"Cannot start library with empty dirpath")(* Avoid generating a KeepObject for nothing *)letkeep_objectsidkeep=matchkeep.keep_objectswith|[]->[]|_::_->[KeepObject(id,keep)]letescape_objectsidescape=matchescape.escape_objectswith|[]->[]|_::_->[EscapeObject(id,escape)](** The [ModActions] abstraction represent operations on modules
that are specific to a given stage. Two instances are defined below,
for Synterp and Interp. *)moduletypeModActions=sigtypetypexprtypeenvvalstage:Summary.Stage.tvalsubstobjs_table_name:stringvalmodobjs_table_name:stringvalenter_module:ModPath.t->full_path->int->unitvalenter_modtype:ModPath.t->full_path->int->unitvalopen_module:open_filter->ModPath.t->full_path->int->unitmoduleLib:Lib.StagedLibS(** Create the substitution corresponding to some functor applications *)valcompute_subst:is_mod:bool->env->MBId.tlist->ModPath.t->ModPath.tlist->Entries.inline->MBId.tlist*substitutionendmoduleSynterpActions:ModActionswithtypeenv=unitwithtypetypexpr=Constrexpr.universe_decl_exproption*Constrexpr.constr_expr=structtypetypexpr=Constrexpr.universe_decl_exproption*Constrexpr.constr_exprtypeenv=unitletstage=Summary.Stage.Synterpletsubstobjs_table_name="MODULE-SYNTAX-SUBSTOBJS"letmodobjs_table_name="MODULE-SYNTAX-OBJS"letenter_moduleobj_mpobj_pathi=consistency_checksfalseobj_path;Nametab.push_module(Untili)obj_pathobj_mpletenter_modtypempspi=ifNametab.exists_modtypespthenanomaly(pr_pathsp++str" already exists.");Nametab.push_modtype(Nametab.Untili)spmpletopen_modulefobj_mpobj_pathi=consistency_checkstrueobj_path;ifin_filter~cat:NonefthenNametab.push_module(Nametab.Exactlyi)obj_pathobj_mpmoduleLib=Lib.Synterpletreccompute_subst()mbidsmp_linl=matchmbids,mp_lwith|_,[]->mbids,empty_subst|[],r->user_errPp.(str"Application of a functor with too few arguments.")|mbid::mbids,mp::mp_l->letmbid_left,subst=compute_subst()mbidsmp_linlinmbid_left,join(map_mbidmbidmp(empty_delta_resolvermp))substletcompute_subst~is_mod()mbidsmp1mp_linl=compute_subst()mbidsmp_linlendmoduleInterpActions:ModActionswithtypeenv=Environ.envwithtypetypexpr=Constr.t*UVars.AbstractContext.toption=structtypetypexpr=Constr.t*UVars.AbstractContext.toptiontypeenv=Environ.envletstage=Summary.Stage.Interpletsubstobjs_table_name="MODULE-SUBSTOBJS"letmodobjs_table_name="MODULE-OBJS"(** {6 Current module type information}
This information is stored by each [start_modtype] for use
in a later [end_modtype]. *)letenter_moduleobj_mpobj_pathi=()letenter_modtypempspi=()letopen_modulefobj_mpobj_pathi=()moduleLib=Lib.Interpletreccompute_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=matchmod_global_deltambwith|None->empty_delta_resolvermp|Somedelta->Modops.inline_delta_resolverenvinlmpfarg_idfarg_bdeltainmbid_left,join(map_mbidmbidmpresolver)substletcompute_subst~is_modenvmbidsmp1mp_linl=lettyp=type_of_modmp1envis_modincompute_substenvmbidstypmp_linlendtypeexp_substituted_object=(substitutive_objects,exp_algebraic_objects,Empty.t,Empty.t)object_viewandexp_algebraic_objects={exp_algebraic_objects:exp_substituted_objectlist}(* and exp_substitutive_objects = Names.MBId.t list * exp_algebraic_objects *)typemodule_objects={module_prefix:object_prefix;module_substituted_objects:exp_substituted_objectlist;module_keep_objects:keep_objects;module_escape_objects:escape_objects;}(** The [StagedModS] abstraction describes module operations at a given stage. *)moduletypeStagedModS=sigtypetypexprtypeenvvalget_module_sobjs:bool->env->Entries.inline->typexprmodule_alg_expr->substitutive_objectsvalload_keep:int->full_path->ModPath.t->keep_objects->unitvalload_escape:int->full_path->ModPath.t->escape_objects->unitvalload_module:int->full_path->ModPath.t->substitutive_objects->unitvalimport_modules:export:Lib.export_flag->(open_filter*ModPath.t)list->unitvaladd_leaf:Libobject.t->unitvaladd_leaves:Libobject.tlist->unitvalexpand_aobjs:Libobject.algebraic_objects->Libobject.tlistvalget_applications:typexprmodule_alg_expr->ModPath.t*ModPath.tlistvaldebug_print_modtab:unit->Pp.tmoduleModObjs:sigvalall:unit->module_objectsModPath.Map.tendvalclose_section:unit->unitend(** Some utilities about substitutive objects :
substitution, expansion *)letsobjs_no_functor(mbids,_)=List.is_emptymbidsletsubst_filteredsub(f,mpasx)=letmp'=subst_mpsubmpinifmp==mp'thenxelsef,mp'letrecsubst_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_onenode=matchnodewith|AtomicObjectobj->letobj'=Libobject.subst_object(subst,obj)inifobj'==objthennodeelseAtomicObjectobj'|ModuleObject(id,sobjs)->letsobjs'=subst_sobjssubstsobjsinifsobjs'==sobjsthennodeelseModuleObject(id,sobjs')|ModuleTypeObject(id,sobjs)->letsobjs'=subst_sobjssubstsobjsinifsobjs'==sobjsthennodeelseModuleTypeObject(id,sobjs')|IncludeObjectaobjs->letaobjs'=subst_aobjssubstaobjsinifaobjs'==aobjsthennodeelseIncludeObjectaobjs'|ExportObject{mpl}->letmpl'=List.Smart.map(subst_filteredsubst)mplinifmpl'==mplthennodeelseExportObject{mpl=mpl'}|KeepObject_|EscapeObject_->assertfalseinList.Smart.mapsubst_oneseg(** The [StagedMod] abstraction factors out the code dealing with modules
that is common to all stages. *)moduleStagedMod(Actions:ModActions)=structtypetypexpr=Actions.typexprtypeenv=Actions.env(** 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~stage:Actions.stage(ModPath.Map.empty:substitutive_objectsModPath.Map.t)~name:Actions.substobjs_table_nameletmissing_handler=ref(funmp->assertfalse)letset_missing_handlerf=(missing_handler:=f)letsetmpobjs=(table:=ModPath.Map.addmpobjs!table)letgetmp=tryModPath.Map.findmp!tablewithNot_found->!missing_handlermpendletexpand_aobjs=function|Objso->o|Ref(mp,sub)->matchModSubstObjs.getmpwith|(_,Objso)->subst_objectssubo|_->assertfalse(* Invariant : any alias points to concrete objs *)letexpand_sobjs(_,aobjs)=expand_aobjsaobjsmoduleExpand=structtypeexp_object=(substitutive_objects,exp_algebraic_objects,keep_objects,escape_objects)object_viewletexp_substituted_view(obj:exp_substituted_object):exp_object=matchobjwith|(AtomicObject_|ModuleObject_|ModuleTypeObject_|IncludeObject_|ExportObject_)aso->o|EscapeObject(_,o)|KeepObject(_,o)->Empty.abortoletkeep_view(obj:Libobject.t):exp_object=matchobjwith|(AtomicObject_|KeepObject_)aso->o|ModuleObject_|ModuleTypeObject_|IncludeObject_|ExportObject_|EscapeObject_->assertfalse(** keep objects only contain atomic / keep *)letescape_view(obj:Libobject.t):exp_object=matchobjwith|(AtomicObject_|EscapeObject_)aso->o|ModuleObject_|ModuleTypeObject_|IncludeObject_|ExportObject_|KeepObject_->assertfalse(** escape objects only contain atomic / escape *)letrecsubstituted_object_view(obj:Libobject.t):exp_substituted_object=matchobjwith|(AtomicObject_|ModuleObject_|ModuleTypeObject_|ExportObject_)aso->o|IncludeObjectaobjs->letaobjs=expand_aobjsaobjsinIncludeObject{exp_algebraic_objects=List.mapsubstituted_object_viewaobjs}|EscapeObject_|KeepObject_->(* forbidden in substitutive objects *)assertfalseletobject_view(obj:Libobject.t):exp_object=matchobjwith|(AtomicObject_|EscapeObject_|ModuleObject_|ModuleTypeObject_|ExportObject_|KeepObject_)aso->o|IncludeObjectaobjs->letaobjs=expand_aobjsaobjsinIncludeObject{exp_algebraic_objects=List.mapsubstituted_object_viewaobjs}end(** {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.
*)moduleModObjs:sigvalset:ModPath.t->module_objects->unitvalget:ModPath.t->module_objects(* may raise Not_found *)valall:unit->module_objectsModPath.Map.tend=structlettable=Summary.ref~stage:Actions.stage(ModPath.Map.empty:module_objectsModPath.Map.t)~name:Actions.modobjs_table_nameletsetmpobjs=(table:=ModPath.Map.addmpobjs!table)letgetmp=ModPath.Map.findmp!tableletall()=!tableendopenExpand(** {6 Declaration of module substitutive objects} *)(** 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=Actions.enter_modtypempspi;ModSubstObjs.setmpsobjs(** {6 Declaration of substitutive objects for Include} *)letrecload_object:typea.(a->exp_object)->int->object_prefix*a->unit=funviewi(prefix,obj)->matchviewobjwith|AtomicObjecto->Libobject.load_objecti(prefix,o)|ModuleObject(id,sobjs)->letsp,kn=Lib.make_onameprefixidinload_moduleisp(mp_of_knkn)sobjs|ModuleTypeObject(id,sobjs)->letname=Lib.make_onameprefixidinlet(sp,kn)=nameinload_modtypeisp(mp_of_knkn)sobjs|IncludeObjectaobjs->load_includei(prefix,aobjs)|ExportObject_->()|KeepObject(id,objs)->letsp,kn=Lib.make_onameprefixidinload_keepisp(mp_of_knkn)objs|EscapeObject(id,objs)->letsp,kn=Lib.make_onameprefixidinload_escapeisp(mp_of_knkn)objsandload_objects:typea.(a->exp_object)->int->object_prefix->alist->unit=funviewiprefixobjs->List.iter(funobj->load_objectviewi(prefix,obj))objsandload_includei(prefix,aobjs)=load_objectsexp_substituted_viewiprefixaobjs.exp_algebraic_objectsandload_keepiobj_pathobj_mpkobjs=(* Invariant : seg isn't empty *)letprefix={obj_path;obj_mp;}inletmodobjs=tryModObjs.getobj_mpwithNot_found->assertfalse(* a substobjs should already be loaded *)inassert(eq_object_prefixmodobjs.module_prefixprefix);assert(List.is_emptymodobjs.module_keep_objects.keep_objects);ModObjs.setobj_mp{modobjswithmodule_keep_objects=kobjs};load_objectskeep_view(i+1)prefixkobjs.keep_objectsandload_escapeiobj_pathobj_mpeobjs=(* Invariant : seg isn't empty *)letprefix={obj_path;obj_mp;}inletmodobjs=tryModObjs.getobj_mpwithNot_found->(* escape objects can exist even if there is no corresponding real module *){module_prefix=prefix;module_substituted_objects=[];module_keep_objects={keep_objects=[]};module_escape_objects={escape_objects=[]};}inassert(eq_object_prefixmodobjs.module_prefixprefix);assert(List.is_emptymodobjs.module_escape_objects.escape_objects);ModObjs.setobj_mp{modobjswithmodule_escape_objects=eobjs};load_objectsescape_view(i+1)prefixeobjs.escape_objectsandload_moduleiobj_pathobj_mpsobjs=letprefix={obj_path;obj_mp;}inActions.enter_moduleobj_mpobj_pathi;ModSubstObjs.setobj_mpsobjs;(* If we're not a functor, let's iter on the internal components *)ifsobjs_no_functorsobjsthenbeginletobjs=expand_sobjssobjsinletobjs=List.mapsubstituted_object_viewobjsinletmodule_objects={module_prefix=prefix;module_substituted_objects=objs;module_keep_objects={keep_objects=[]};module_escape_objects={escape_objects=[]};}inModObjs.setobj_mpmodule_objects;load_objectsexp_substituted_view(i+1)prefixobjsend(** {6 Implementation of Import and Export commands} *)letmark_objectfobj(exports,acc)=(exports,(f,obj)::acc)letreccollect_module(f,mp)acc=try(* May raise Not_found for unknown module and for functors *)letmodobjs=ModObjs.getmpinletprefix=modobjs.module_prefixinletacc=collect_objectsescape_viewf1prefixmodobjs.module_escape_objects.escape_objectsaccinletacc=collect_objectskeep_viewf1prefixmodobjs.module_keep_objects.keep_objectsaccincollect_objectsexp_substituted_viewf1prefixmodobjs.module_substituted_objectsaccwithNot_foundwhenActions.stage=Summary.Stage.Synterp->accandcollect_object:typea.(a->exp_object)->_->_->_->a->_->_=funviewfiprefixobjacc->matchviewobjwith|ExportObject{mpl}->collect_exportsfimplacc|(AtomicObject_|IncludeObject_|KeepObject_|EscapeObject_|ModuleObject_|ModuleTypeObject_)asobj->mark_objectf(prefix,obj)accandcollect_objects:typea.(a->exp_object)->_->_->_->alist->_=funviewfiprefixobjsacc->List.fold_left(funaccobj->collect_objectviewfiprefixobjacc)acc(List.revobjs)andcollect_exportf(f',mp)(exports,objsasacc)=matchfilter_andff'with|None->acc|Somef->letexports'=ModPath.Map.updatemp(function|None->Somef|Somef0->letf'=filter_orff0iniffilter_eqf'f0thenSomef0elseSomef')exportsin(* If the map doesn't change there is nothing new to export. *)ifexports==exports'thenaccelsecollect_module(f,mp)(exports',objs)andcollect_exportsfimplacc=ifInt.equali1thenList.fold_left(funaccfmp->collect_exportffmpacc)acc(List.revmpl)elseaccletcollect_modulesmpl=List.fold_left(funaccfmp->collect_modulefmpacc)(ModPath.Map.empty,[])(List.revmpl)letopen_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_object:typea.(a->exp_object)->_->_->_*a->_=funviewfi(prefix,obj)->matchviewobjwith|AtomicObjecto->Libobject.open_objectfi(prefix,o)|ModuleObject(id,sobjs)->letsp,kn=Lib.make_onameprefixidinletmp=mp_of_knkninopen_modulefispmpsobjs|ModuleTypeObject(id,sobjs)->letname=Lib.make_onameprefixidinopen_modtypei(name,sobjs)|IncludeObjectaobjs->open_includefi(prefix,aobjs)|ExportObject{mpl}->open_exportfimpl|KeepObject(id,objs)->letname=Lib.make_onameprefixidinopen_keepfi(name,objs)|EscapeObject(id,objs)->letname=Lib.make_onameprefixidinopen_escapefi(name,objs)andopen_modulefiobj_pathobj_mpsobjs=Actions.open_modulefobj_mpobj_pathi;(* If we're not a functor, let's iter on the internal components *)ifsobjs_no_functorsobjsthenbeginletmodobjs=ModObjs.getobj_mpinopen_objectsexp_substituted_viewf(i+1)modobjs.module_prefixmodobjs.module_substituted_objectsendandopen_objects:typea.(a->exp_object)->_->_->_->alist->_=funviewfiprefixobjs->List.iter(funobj->open_objectviewfi(prefix,obj))objsandopen_includefi(prefix,aobjs)=open_objectsexp_substituted_viewfiprefixaobjs.exp_algebraic_objectsandopen_exportfimpl=let_,objs=collect_exportsfimpl(ModPath.Map.empty,[])inList.iter(fun(f,o)->open_object(funx->x)f1o)objsandopen_keepfi((sp,kn),kobjs)=letobj_mp=mp_of_knkninletprefix={obj_path=sp;obj_mp;}inopen_objectskeep_viewf(i+1)prefixkobjs.keep_objectsandopen_escapefi((sp,kn),kobjs)=letobj_mp=mp_of_knkninletprefix={obj_path=sp;obj_mp;}inopen_objectsescape_viewf(i+1)prefixkobjs.escape_objectsletcache_include(prefix,aobjs)=leto=expand_aobjsaobjsinleto=List.mapsubstituted_object_viewoinload_objectsexp_substituted_view1prefixo;open_objectsexp_substituted_viewunfiltered1prefixoletcache_object(prefix,obj)=matchobjwith|AtomicObjecto->Libobject.cache_object(prefix,o)|ModuleObject_->load_objectobject_view1(prefix,obj)|ModuleTypeObject_->load_objectobject_view0(prefix,obj)|IncludeObjectaobjs->cache_include(prefix,aobjs)|ExportObject{mpl}->anomalyPp.(str"Export should not be cached")|KeepObject_|EscapeObject_->anomaly(Pp.str"This module should not be cached!")(* Adding operations with containers *)letadd_leaf_entry=matchActions.stagewith|Summary.Stage.Synterp->Lib.Synterp.add_leaf_entry|Summary.Stage.Interp->Lib.Interp.add_leaf_entryletadd_leafobj=cache_object(Lib.prefix(),obj);add_leaf_entryobjletadd_leavesobjs=letadd_objobj=add_leaf_entryobj;load_objectobject_view1(Lib.prefix(),obj)inList.iteradd_objobjsletimport_modules~exportmpl=let_,objs=collect_modulesmplinList.iter(fun(f,o)->open_object(funx->x)f1o)objs;matchexportwith|Lib.Import->()|Lib.Export->letentry=ExportObject{mpl}inadd_leaf_entryentry(** {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,id)letrecregister_mod_objsmpobj=matchobjwith|ModuleObject(id,sobjs)->ModSubstObjs.set(mp_idmpid)sobjs|ModuleTypeObject(id,sobjs)->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 objects of a "with Module" structure. *)letrecreplace_module_objectidlmp0objs0mp1objs1=matchidl,objs0with|_,[]->[]|id::idl,(ModuleObject(id',sobjs))::tailwhenId.equalidid'->beginletmp_id=MPdot(mp0,id)inletobjs=matchidlwith|[]->subst_objects(map_mpmp1mp_id(empty_delta_resolvermp_id))objs1|_->letobjs_id=expand_sobjssobjsinreplace_module_objectidlmp_idobjs_idmp1objs1in(ModuleObject(id,([],Objsobjs)))::tailend|idl,lobj::tail->lobj::replace_module_objectidlmp0tailmp1objs1(** 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_modenvinlmtyinifnot(sobjs_no_functorsobjs0)thenuser_errPp.(str"Illegal use of a functor.");(* For now, we expand 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)inletmbids_left,subst=Actions.compute_subst~is_modenvmbidsmp1mp_linlin(mbids_left,subst_aobjssubstaobjs)letdebug_print_modtab()=letpr_seg=function|0->str"[]"|l->str"[."++intl++str".]"inletpr_modinfompmodobjss=letobjs=List.lengthmodobjs.module_substituted_objects+List.lengthmodobjs.module_keep_objects.keep_objectsins++str(ModPath.to_stringmp)++spc()++pr_segobjsinletmodules=ModPath.Map.foldpr_modinfo(ModObjs.all())(mt())inhov0modulesletadd_discharged_item:Lib.discharged_item->unit=function|DischargedExport{mpl}->import_modules~export:Exportmpl|DischargedLeafo->Lib.add_discharged_leafoletclose_section()=letobjs=Actions.Lib.close_section()inList.iteradd_discharged_itemobjsendmoduleSynterpVisitor:StagedModSwithtypeenv=SynterpActions.envwithtypetypexpr=Constrexpr.universe_decl_exproption*Constrexpr.constr_expr=StagedMod(SynterpActions)moduleInterpVisitor:StagedModSwithtypeenv=InterpActions.envwithtypetypexpr=Constr.t*UVars.AbstractContext.toption=StagedMod(InterpActions)(** {6 Modules : start, end, declare} *)typecurrent_module_syntax_info={cur_mp:ModPath.t;cur_typ:((Constrexpr.universe_decl_exproption*Constrexpr.constr_expr)module_alg_expr*intoption)option;cur_mbids:MBId.tlist;}letdefault_module_syntax_infomp={cur_mp=mp;cur_typ=None;cur_mbids=[]}letopenmod_syntax_info=Summary.refNone~stage:Summary.Stage.Synterp~name:"MODULE-SYNTAX-INFO"(** {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"letstart_librarydir=letmp=Global.start_librarydirinopenmod_info:=default_module_info;openmod_syntax_info:=Some(default_module_syntax_infomp);Lib.start_compilationdirmpletset_openmod_syntax_infoinfo=match!openmod_syntax_infowith|None->anomalyPp.(str"bad init of openmod_syntax_info")|Some_->openmod_syntax_info:=Someinfoletopenmod_syntax_info()=match!openmod_syntax_infowith|None->anomalyPp.(str"missing init of openmod_syntax_info")|Somev->vletvm_state=(* VM bytecode is not needed here *)letvm_handler___()=(),Nonein((),{Mod_typing.vm_handler})moduleRawModOps=structmoduleSynterp=structletbuild_subtypesmtys=List.map(fun(m,ann)->letinl=inl2intoptanninletmte,base,kind=Modintern.intern_module_astModintern.ModTypemin(mte,base,kind,inl))mtysletintern_arg(idl,(typ,ann))=letinl=inl2intoptanninletlib_dir=Lib.library_dp()inlet(mty,base,kind)=Modintern.intern_module_astModintern.ModTypetypinletsobjs=SynterpVisitor.get_module_sobjsfalse()inlmtyinletmp0=get_module_pathmtyinletmap{CAst.v=id}=letsp=Libnames.make_pathDirPath.emptyidinletmbid=MBId.makelib_diridinletmp=MPboundmbidin(* We can use an empty delta resolver because we load only syntax objects *)letsobjs=subst_sobjs(map_mpmp0mp(empty_delta_resolvermp))sobjsinSynterpVisitor.load_module1spmpsobjs;mbidinList.mapmapidl,(mty,base,kind,inl)letintern_argsparams=List.mapintern_argparamsletstart_module_coreidargsres=(* Loads the parsing objects in arguments *)letargs=intern_argsargsinletmbids=List.flatten@@List.map(fun(mbidl,_)->mbidl)argsinletres_entry_o,sign=matchreswith|Enforce(res,ann)->letinl=inl2intoptanninlet(mte,base,kind)=Modintern.intern_module_astModintern.ModTyperesinSome(mte,inl),Enforce(mte,base,kind,inl)|Checkresl->None,Check(build_subtypesresl)inletmp=ModPath.MPdot((openmod_syntax_info()).cur_mp,id)inmp,res_entry_o,mbids,sign,argsletstart_moduleexportidargsres=let()=ifOption.has_someexport&¬(CList.is_emptyargs)thenuser_errPp.(str"Cannot import functors.")inletfs=Summary.Synterp.freeze_summaries()inletmp,res_entry_o,mbids,sign,args=start_module_coreidargsresinset_openmod_syntax_info{cur_mp=mp;cur_typ=res_entry_o;cur_mbids=mbids};letprefix=Lib.Synterp.start_moduleexportidmpfsinNametab.(push_dir(Until1)(prefix.obj_path)(GlobDirRef.DirOpenModuleprefix.obj_mp));mp,args,signletend_module_coreid(m_info:current_module_syntax_info)objectsfs=let{Lib.substobjs=substitute;keepobjs=keep;escapeobjs=escape;anticipateobjs=special;}=objectsin(* For sealed modules, we use the substitutive objects of their signatures *)letsobjs0,keep=matchm_info.cur_typwith|None->([],Objssubstitute),keep|Some(mty,inline)->SynterpVisitor.get_module_sobjsfalse()inlinemty,{keep_objects=[]}inSummary.Synterp.unfreeze_summariesfs;letsobjs=let(ms,objs)=sobjs0in(m_info.cur_mbids@ms,objs)in(* 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)m_info.cur_mp(empty_delta_resolverm_info.cur_mp))sobjsinletnode=ModuleObject(id,sobjs)in(* We add the keep objects, if any, and if this isn't a functor *)letkeep=ifnot(CList.is_emptym_info.cur_mbids)then[]elsekeep_objectsidkeepinletescape=escape_objectsidescapeinletobjects=special@[node]@keep@escapeinm_info.cur_mp,objectsletend_module()=letoldprefix,fs,objects=Lib.Synterp.end_module()inletm_info=openmod_syntax_info()inletolddp,id=pop_patholdprefix.obj_pathinletmp,objects=end_module_coreidm_infoobjectsfsinlet()=SynterpVisitor.add_leavesobjectsinassert(eq_full_path(Lib.prefix()).obj_patholddp);mpletget_functor_sobjsis_modinl(mbids,mexpr)=let(mbids0,aobjs)=SynterpVisitor.get_module_sobjsis_mod()inlmexprin(mbids@mbids0,aobjs)letdeclare_moduleidargsresmexpr_o=letfs=Summary.Synterp.freeze_summaries()in(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp=ModPath.MPdot((openmod_syntax_info()).cur_mp,id)inletargs=intern_argsargsinletmbids=List.flatten@@List.mapfstargsinletmty_entry_o=matchreswith|Enforce(mty,ann)->letinl=inl2intoptanninlet(mte,base,kind)=Modintern.intern_module_astModintern.ModTypemtyinEnforce(mte,base,kind,inl)|Checkmtys->Check(build_subtypesmtys)inletmexpr_entry_o=matchmexpr_owith|None->None|Some(mexpr,ann)->let(mte,base,kind)=Modintern.intern_module_astModintern.ModulemexprinSome(mte,base,kind,inl2intoptann)inletsobjs,mp0=matchmexpr_entry_o,mty_entry_owith|None,Check_->assertfalse(* No body, no type ... *)|_,Enforce(typ,_,_,inl_res)->get_functor_sobjsfalseinl_res(mbids,typ),get_module_pathtyp|Some(body,_,_,inl_expr),Check_->get_functor_sobjstrueinl_expr(mbids,body),get_module_pathbodyin(* Undo the simulated interactive building of the module
and declare the module as a whole *)Summary.Synterp.unfreeze_summariesfs;(* We can use an empty delta resolver on syntax objects *)letsobjs=subst_sobjs(map_mpmp0mp(empty_delta_resolvermp))sobjsinignore(SynterpVisitor.add_leaf(ModuleObject(id,sobjs)));mp,args,mexpr_entry_o,mty_entry_oendmoduleInterp=struct(** {6 Auxiliary functions concerning subtyping checks} *)letcheck_subenvmpsub_mtb_l=letfoldsub_mtb(cst,env)=letstate=((Environ.universesenv,cst),Reductionops.inferred_universes)inletugraph,cst=Subtyping.check_subtypesstateenvmpmpsub_mtbin(cst,Environ.set_universesugraphenv)inletcst,_=List.fold_rightfoldsub_mtb_l(Univ.UnivConstraints.empty,env)inGlobal.add_univ_constraintscst(** This function checks if the type calculated for the module [mp] is
a "<:"-like subtype of all signatures in [sub_mtb_l]. Uses only
the global environment. *)letcheck_subtypesmpsub_mtb_l=check_sub(Global.env())mpsub_mtb_l(** Same for module type [mp] *)letcheck_subtypes_mtmpsub_mtb_l=letmtb=tryGlobal.lookup_modtypempwithNot_found->assertfalseinletenv=Modops.add_modulemp(module_body_of_typemtb)(Global.env())incheck_subenvmpsub_mtb_lletcurrent_modresolver()=Safe_typing.delta_of_senv@@Global.safe_env()letcurrent_struct()=letstruc=Safe_typing.structure_body_of_safe_env@@Global.safe_env()inNoFunctor(List.revstruc)(** Prepare the module type list for check of subtypes *)letbuild_subtypesenvmpargsmtys=let(ctx,ans)=List.fold_left_map(functx(mte,base,kind,inl)->letmte,ctx'=Modintern.interp_module_astenvModintern.ModTypebasemteinletenv=Environ.push_context_set~strict:truectx'envinletctx=Univ.ContextSet.unionctxctx'inletstate=((Environ.universesenv,Univ.UnivConstraints.empty),Reductionops.inferred_universes)in(* functor arguments are already part of the env, we compute the type
and requantify over them *)letmtb,(_,cst),_=Mod_typing.translate_modtypestatevm_stateenvmpinl([],mte)inletfold(mbid,mtb,_,_)accu=MoreFunctor(mbid,mtb,accu)in(* XXX: parameters will be rechecked for subtyping, even though we
statically know they are the same as the ones of the ambient
module *)letsign=List.fold_rightfoldargs(mod_typemtb)inletmtb=make_module_typesign(mod_deltamtb)inletctx=Univ.ContextSet.add_constraintscstctxinctx,mtb)Univ.ContextSet.emptymtysin(ans,ctx)(** 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)(mbidl,(mty,base,kind,inl))=letenv=Global.env()inlet(mty,cst')=Modintern.interp_module_astenvkindbasemtyinlet()=Global.push_context_setcst'inlet()=letstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)inlet_,(_,cst),_=Mod_typing.translate_modtypestatevm_state(Global.env())baseinl([],mty)inGlobal.add_univ_constraintscstinletenv=Global.env()inletsobjs=InterpVisitor.get_module_sobjsfalseenvinlmtyinletmp0=get_module_pathmtyinletfoldaccmbid=letid=MBId.to_idmbidinletsp=Libnames.make_pathDirPath.emptyidinletmp=MPboundmbidinletmtb=Global.add_module_parametermbidmtyinlinletresolver=mod_deltamtbinletsobjs=subst_sobjs(map_mpmp0mpresolver)sobjsinInterpVisitor.load_module1spmpsobjs;(mbid,mtb,mty,inl)::accinletacc=List.fold_leftfoldaccmbidlin(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=letargs,ctx=List.fold_leftintern_arg([],Univ.ContextSet.empty)paramsinList.revargs,ctxletstart_module_coreidargsres=letmp=Global.start_moduleidinletparams,ctx=intern_argsargsinlet()=Global.push_context_setctxinletenv=Global.env()inletres_entry_o,subtyps,ctx'=matchreswith|Enforce(mte,base,kind,inl)->let(mte,ctx)=Modintern.interp_module_astenvkindbasemteinletenv=Environ.push_context_setctxenvin(* We check immediately that mte is well-formed *)letstate=((Environ.universesenv,Univ.UnivConstraints.empty),Reductionops.inferred_universes)inlet_,(_,cst),_=Mod_typing.translate_modtypestatevm_stateenvmpinl([],mte)inletctx=Univ.ContextSet.add_constraintscstctxinSome(mte,inl),[],ctx|Checkresl->lettyps,ctx=build_subtypesenvmpparamsreslinNone,typs,ctxinlet()=Global.push_context_setctx'inmp,res_entry_o,subtyps,params,Univ.ContextSet.unionctxctx'letstart_moduleexportidargsres=letfs=Summary.Interp.freeze_summaries()inletmp,res_entry_o,subtyps,_,_=start_module_coreidargsresinopenmod_info:={cur_typ=res_entry_o;cur_typs=subtyps};let_:object_prefix=Lib.Interp.start_moduleexportidmpfsinmpletend_module_coreidm_infoobjectsfs=let{Lib.substobjs=substitute;keepobjs=keep;escapeobjs=escape;anticipateobjs=special;}=objectsin(* For sealed modules, we use the substitutive objects of their signatures *)letsobjs0,keep=matchm_info.cur_typwith|None->([],Objssubstitute),keep|Some(mty,inline)->InterpVisitor.get_module_sobjsfalse(Global.env())inlinemty,{keep_objects=[]}inletstruc=current_struct()inletrestype'=Option.map(fun(ty,inl)->(([],ty),inl))m_info.cur_typinletstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)inlet_,(_,cst),_=Mod_typing.finalize_modulestatevm_state(Global.env())(Global.current_modpath())(struc,current_modresolver())restype'inlet()=Global.add_univ_constraintscstinletmp,mbids,resolver=Global.end_modulefsidm_info.cur_typinletsobjs=let(ms,objs)=sobjs0in(mbids@ms,objs)inlet()=check_subtypesmpm_info.cur_typsin(* 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=ModuleObject(id,sobjs)in(* We add the keep objects, if any, and if this isn't a functor *)letkeep=ifnot(CList.is_emptymbids)then[]elsekeep_objectsidkeepin(* NB: escape objects are added even for sealed modules, not sure if want *)letescape=escape_objectsidescapeinletobjects=special@[node]@keep@escapeinmp,objectsletend_module()=letoldprefix,fs,objects=Lib.Interp.end_module()inletm_info=!openmod_infoinlet_olddp,id=pop_patholdprefix.obj_pathinletmp,objects=end_module_coreidm_infoobjectsfsinlet()=InterpVisitor.add_leavesobjectsin(* Name consistency check : kernel vs. library *)assert(ModPath.equaloldprefix.obj_mpmp);mpletget_functor_sobjsis_modenvinl(params,mexpr)=let(mbids,aobjs)=InterpVisitor.get_module_sobjsis_modenvinlmexprin(List.mappi1params@mbids,aobjs)(* TODO cleanup push universes directly to global env *)letdeclare_moduleidargsresmexpr_o=letfs=Summary.Interp.freeze_summaries()in(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp,mty_entry_o,subs,params,ctx=start_module_coreidargsresinletenv=Global.env()inletmexpr_entry_o,inl_expr,ctx'=matchmexpr_owith|None->None,default_inline_level(),Univ.ContextSet.empty|Some(mte,base,kind,inl)->let(mte,ctx)=Modintern.interp_module_astenvkindbasemteinSomemte,inl,ctxinletenv=Environ.push_context_setctx'envinletctx=Univ.ContextSet.unionctxctx'inletparams=List.map(fun(mbid,_,mte,b)->(mbid,mte,b))paramsinletentry,inl_res=matchmexpr_entry_o,mty_entry_owith|None,None->assertfalse(* No body, no type ... *)|None,Some(typ,inl)->MType(params,typ),inl|Somebody,otyp->MExpr(params,body,Option.mapfstotyp),Option.catasnd(default_inline_level())otypinletsobjs,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.Interp.unfreeze_summariesfs;letinl=matchinl_exprwith|None->None|_->inl_resinlet()=Global.push_context_setctxinletstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)inlet_,(_,cst),_=Mod_typing.translate_modulestatevm_state(Global.env())mpinlentryinlet()=Global.add_univ_constraintscstinletmp_env,resolver=Global.add_moduleidentryinlin(* Name consistency check : kernel vs. library *)assert(ModPath.equalmp(mp_of_kn(Lib.make_knid)));assert(ModPath.equalmpmp_env);let()=check_subtypesmpsubsinletsobjs=subst_sobjs(map_mpmp0mpresolver)sobjsinInterpVisitor.add_leaf(ModuleObject(id,sobjs));mpendend(** {6 Module types : start, end, declare} *)moduleRawModTypeOps=structmoduleSynterp=structletstart_modtype_coreidcur_mpargsmtys=letmp=ModPath.MPdot(cur_mp,id)inletargs=RawModOps.Synterp.intern_argsargsinletmbids=List.flatten@@List.map(fun(mbidl,_)->mbidl)argsinletsub_mty_l=RawModOps.Synterp.build_subtypesmtysinmp,mbids,args,sub_mty_lletstart_modtypeidargsmtys=letfs=Summary.Synterp.freeze_summaries()inletmp,mbids,args,sub_mty_l=start_modtype_coreid(openmod_syntax_info()).cur_mpargsmtysinset_openmod_syntax_info{cur_mp=mp;cur_typ=None;cur_mbids=mbids};letprefix=Lib.Synterp.start_modtypeidmpfsinNametab.(push_dir(Until1)(prefix.obj_path)(GlobDirRef.DirOpenModtypeprefix.obj_mp));mp,args,sub_mty_lletend_modtype_coreidmbidsobjectsfs=let{Lib.substobjs=substitute;keepobjs=_;escapeobjs=escape;anticipateobjs=special;}=objectsinSummary.Synterp.unfreeze_summariesfs;letmodtypeobjs=(mbids,Objssubstitute)inspecial@[ModuleTypeObject(id,modtypeobjs)]@(escape_objectsidescape)letend_modtype()=letoldprefix,fs,objects=Lib.Synterp.end_modtype()inlet_olddp,id=pop_patholdprefix.obj_pathinletobjects=end_modtype_coreid(openmod_syntax_info()).cur_mbidsobjectsfsinSynterpVisitor.add_leavesobjects;(openmod_syntax_info()).cur_mpletdeclare_modtypeidargsmtys(mty,ann)=letfs=Summary.Synterp.freeze_summaries()inletinl=inl2intoptannin(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp,mbids,args,sub_mty_l=start_modtype_coreid(openmod_syntax_info()).cur_mpargsmtysinletmte,base,kind=Modintern.intern_module_astModintern.ModTypemtyinletentry=mbids,mteinletsobjs=RawModOps.Synterp.get_functor_sobjsfalseinlentryinletsubst=map_mp(get_module_path(sndentry))mp(empty_delta_resolvermp)inletsobjs=subst_sobjssubstsobjsin(* Undo the simulated interactive building of the module type
and declare the module type as a whole *)Summary.Synterp.unfreeze_summariesfs;ignore(SynterpVisitor.add_leaf(ModuleTypeObject(id,sobjs)));mp,args,(mte,base,kind,inl),sub_mty_lendmoduleInterp=structletopenmodtype_info=Summary.ref([]:module_type_bodylist)~name:"MODTYPE-INFO"letstart_modtype_coreidargsmtys=letmp=Global.start_modtypeidinletparams,params_ctx=RawModOps.Interp.intern_argsargsinlet()=Global.push_context_setparams_ctxinletenv=Global.env()inletsub_mty_l,sub_mty_ctx=RawModOps.Interp.build_subtypesenvmpparamsmtysinlet()=Global.push_context_setsub_mty_ctxinmp,params,sub_mty_l,Univ.ContextSet.unionparams_ctxsub_mty_ctxletstart_modtypeidargsmtys=letfs=Summary.Interp.freeze_summaries()inletmp,_,sub_mty_l,_=start_modtype_coreidargsmtysinopenmodtype_info:=sub_mty_l;letprefix=Lib.Interp.start_modtypeidmpfsinNametab.(push_dir(Until1)(prefix.obj_path)(GlobDirRef.DirOpenModtypemp));mpletend_modtype_coreidsub_mty_lobjectsfs=let{Lib.substobjs=substitute;keepobjs=_;escapeobjs=escape;anticipateobjs=special;}=objectsinletmp,mbids=Global.end_modtypefsidinlet()=RawModOps.Interp.check_subtypes_mtmpsub_mty_linletmodtypeobjs=(mbids,Objssubstitute)inletobjects=special@[ModuleTypeObject(id,modtypeobjs)]@(escape_objectsidescape)inmp,objectsletend_modtype()=letoldprefix,fs,objects=Lib.Interp.end_modtype()inletolddp,id=pop_patholdprefix.obj_pathinletsub_mty_l=!openmodtype_infoinletmp,objects=end_modtype_coreidsub_mty_lobjectsfsinlet()=InterpVisitor.add_leavesobjectsin(* Check name consistence : start_ vs. end_modtype, kernel vs. library *)assert(eq_full_path(Lib.prefix()).obj_patholddp);assert(ModPath.equaloldprefix.obj_mpmp);mpletdeclare_modtypeidargsmtys(mte,base,kind,inl)=letfs=Summary.Interp.freeze_summaries()in(* We simulate the beginning of an interactive module,
then we adds the module parameters to the global env. *)letmp,params,sub_mty_l,ctx=start_modtype_coreidargsmtysinletenv=Global.env()inletmte,mte_ctx=Modintern.interp_module_astenvkindbasemteinlet()=Global.push_context_setmte_ctxinletenv=Global.env()in(* We check immediately that mte is well-formed *)letstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)inlet_,(_,mte_cst),_=Mod_typing.translate_modtypestatevm_stateenvmpinl([],mte)inlet()=Global.push_context_set(Univ.Level.Set.empty,mte_cst)inletparams=List.map(fun(mbid,_,mte,b)->(mbid,mte,b))paramsinletentry=params,mteinletenv=Global.env()inletsobjs=RawModOps.Interp.get_functor_sobjsfalseenvinlentryinletsubst=map_mp(get_module_path(sndentry))mp(empty_delta_resolvermp)inletsobjs=subst_sobjssubstsobjsin(* Undo the simulated interactive building of the module type
and declare the module type as a whole *)Summary.Interp.unfreeze_summariesfs;(* We enrich the global environment *)let()=Global.push_context_setctxinlet()=Global.push_context_setmte_ctxinlet()=Global.push_context_set(Univ.Level.Set.empty,mte_cst)inletmp_env=Global.add_modtypeidentryinlin(* Name consistency check : kernel vs. library *)assert(ModPath.equalmp_envmp);(* Subtyping checks *)let()=RawModOps.Interp.check_subtypes_mtmpsub_mty_linInterpVisitor.add_leaf(ModuleTypeObject(id,sobjs));mpendend(** {6 Include} *)moduleRawIncludeOps=structexceptionNoIncludeSelfmoduleSynterp=structletrecinclude_substmpmbids=matchmbidswith|[]->empty_subst|mbid::mbids->letsubst=include_substmpmbidsinjoin(map_mbidmbidmp(empty_delta_resolvermp))substletdeclare_one_include_corecur_mp(me_ast,annot)=letme,base,kind=Modintern.intern_module_astModintern.ModAnyme_astinletis_mod=(kind==Modintern.Module)inletinl=inl2intoptannotinletmbids,aobjs=SynterpVisitor.get_module_sobjsis_mod()inlmeinletsubst_self=tryifList.is_emptymbidsthenraiseNoIncludeSelf;include_substcur_mpmbidswithNoIncludeSelf->empty_substinletbase_mp=get_module_pathmein(* We can use an empty delta resolver on syntax objects *)letsubst=joinsubst_self(map_mpbase_mpcur_mp(empty_delta_resolvercur_mp))inletaobjs=subst_aobjssubstaobjsin(me,base,kind,inl),aobjsletdeclare_one_include(me_ast,annot)=letres,aobjs=declare_one_include_core(openmod_syntax_info()).cur_mp(me_ast,annot)inSynterpVisitor.add_leaf(IncludeObjectaobjs);resletdeclare_includeme_asts=List.mapdeclare_one_includeme_astsendmoduleInterp=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.")lettype_of_inclenvis_mod=function|MEidentmp->type_of_modmpenvis_mod|MEapply_asme->letmp0,mp_l=InterpVisitor.get_applicationsmeindecompose_functormp_l(type_of_modmp0envis_mod)|MEwith_->raiseNoIncludeSelf(** Implements [Include F] where [F] has parameters [mbids] to be
instantiated by fields of the current "self" module, i.e. using
subtyping, by the current module itself. *)letdeclare_one_include_core(me,base,kind,inl)=letenv=Global.env()inletme,cst=Modintern.interp_module_astenvkindbasemeinlet()=Global.push_context_setcstinletenv=Global.env()inletis_mod=(kind==Modintern.Module)inletcur_mp=Global.current_modpath()inletmbids,aobjs=InterpVisitor.get_module_sobjsis_modenvinlmeinletsubst_self=tryifList.is_emptymbidsthenraiseNoIncludeSelf;lettyp=type_of_inclenvis_modmeinletreso=RawModOps.Interp.current_modresolver()ininclude_substenvcur_mpresombidstypinlwithNoIncludeSelf->empty_substinletbase_mp=get_module_pathmeinletstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)inletsign,(),resolver,(_,cst),_=Mod_typing.translate_mse_includeis_modstatevm_state(Global.env())(Global.current_modpath())inlmeinlet()=Global.add_univ_constraintscstinlet()=assert(ModPath.equalcur_mp(Global.current_modpath()))in(* Include Self support *)letmb=make_module_body(RawModOps.Interp.current_struct())(RawModOps.Interp.current_modresolver())[]inletreccompute_signsign=matchsignwith|MoreFunctor(mbid,mtb,str)->letstate=((Global.universes(),Univ.UnivConstraints.empty),Reductionops.inferred_universes)in(* Module subcomponents are already part of env at this point *)letenv=Environ.shallow_add_modulecur_mpmb(Global.env())inlet(_,cst)=Subtyping.check_subtypesstateenvcur_mp(MPboundmbid)mtbinlet()=Global.add_univ_constraintscstinletmpsup_delta=matchmod_global_deltambwith|None->assertfalse(* mb is guaranteed not to be a functor here *)|Somedelta->Modops.inline_delta_resolver(Global.env())inlcur_mpmbidmtbdeltainletsubst=Mod_subst.map_mbidmbidcur_mpmpsup_deltaincompute_sign(Modops.subst_signaturesubstcur_mpstr)|NoFunctorstr->()inlet()=compute_signsigninletresolver=Global.add_includemeis_modinlinletsubst=joinsubst_self(map_mpbase_mpcur_mpresolver)insubst_aobjssubstaobjsletdeclare_one_include(me,base,kind,inl)=letaobjs=declare_one_include_core(me,base,kind,inl)inInterpVisitor.add_leaf(IncludeObjectaobjs)letdeclare_includeme_asts=List.iterdeclare_one_includeme_astsendend(** {6 Libraries} *)typelibrary_name=DirPath.t(** A library object is made of some substitutive objects
and some "keep" and "escape" objects. *)typelibrary_objects=Libobject.tlist*keep_objects*escape_objectsmoduleSynterp=structletstart_moduleexportidargsres=RawModOps.Synterp.start_moduleexportidargsresletend_module=RawModOps.Synterp.end_module(** Declare a module in terms of a list of module bodies, by including them.
Typically used for `Module M := N <+ P`.
*)letdeclare_module_includesidargsresmexpr_l=letfs=Summary.Synterp.freeze_summaries()inletmp,res_entry_o,mbids,sign,args=RawModOps.Synterp.start_module_coreidargsresinletmod_info={cur_mp=mp;cur_typ=res_entry_o;cur_mbids=mbids}inletincludes=List.map_left(RawIncludeOps.Synterp.declare_one_include_coremp)mexpr_linletbodies,incl_objs=List.splitincludesinletincl_objs=List.map(funx->IncludeObjectx)incl_objsinletobjects={Lib.substobjs=incl_objs;keepobjs={keep_objects=[]};escapeobjs={escape_objects=[]};anticipateobjs=[];}inletmp,objects=RawModOps.Synterp.end_module_coreidmod_infoobjectsfsinSynterpVisitor.add_leavesobjects;mp,args,bodies,sign(** Declare a module type in terms of a list of module bodies, by including them.
Typically used for `Module Type M := N <+ P`.
*)letdeclare_modtype_includesidargsresmexpr_l=letfs=Summary.Synterp.freeze_summaries()inletmp,mbids,args,subtyps=RawModTypeOps.Synterp.start_modtype_coreid(openmod_syntax_info()).cur_mpargsresinletincludes=List.map_left(RawIncludeOps.Synterp.declare_one_include_coremp)mexpr_linletbodies,incl_objs=List.splitincludesinletincl_objs=List.map(funx->IncludeObjectx)incl_objsinletobjects={Lib.substobjs=incl_objs;keepobjs={keep_objects=[]};escapeobjs={escape_objects=[]};anticipateobjs=[];}inletobjects=RawModTypeOps.Synterp.end_modtype_coreidmbidsobjectsfsinSynterpVisitor.add_leavesobjects;mp,args,bodies,subtypsletdeclare_moduleidargsmtysme_l=matchme_lwith|[]->letmp,args,body,sign=RawModOps.Synterp.declare_moduleidargsmtysNoneinassert(Option.is_emptybody);mp,args,[],sign|[me]->letmp,args,body,sign=RawModOps.Synterp.declare_moduleidargsmtys(Someme)inmp,args,[Option.getbody],sign|me_l->declare_module_includesidargsmtysme_lletstart_modtypeidargsmtys=RawModTypeOps.Synterp.start_modtypeidargsmtysletend_modtype=RawModTypeOps.Synterp.end_modtypeletdeclare_modtypeidargsmtysmty_l=matchmty_lwith|[]->assertfalse|[mty]->letmp,args,body,sign=RawModTypeOps.Synterp.declare_modtypeidargsmtysmtyinmp,args,[body],sign|mty_l->declare_modtype_includesidargsmtysmty_lletdeclare_include=RawIncludeOps.Synterp.declare_includeletregister_librarydir(objs:library_objects)=letmp=MPfiledirinletsp=path_of_filedirinletsobjs,keepobjs,escapeobjs=objsinSynterpVisitor.load_module1spmp([],Objssobjs);SynterpVisitor.load_escape2spmpescapeobjs;SynterpVisitor.load_keep2spmpkeepobjsletimport_modules=SynterpVisitor.import_modulesletimport_modulef~exportmp=import_modules~export[f,mp]letclose_section=SynterpVisitor.close_sectionendmoduleInterp=structletstart_module=RawModOps.Interp.start_moduleletend_module=RawModOps.Interp.end_module(** Declare a module in terms of a list of module bodies, by including them.
Typically used for `Module M := N <+ P`.
*)letdeclare_module_includesidargsresmexpr_l=letfs=Summary.Interp.freeze_summaries()inletmp,res_entry_o,subtyps,_,_=RawModOps.Interp.start_module_coreidargsresinletmod_info={cur_typ=res_entry_o;cur_typs=subtyps}inletincl_objs=List.map_left(funx->IncludeObject(RawIncludeOps.Interp.declare_one_include_corex))mexpr_linletobjects={Lib.substobjs=incl_objs;keepobjs={keep_objects=[]};escapeobjs={escape_objects=[]};anticipateobjs=[];}inletmp,objects=RawModOps.Interp.end_module_coreidmod_infoobjectsfsinInterpVisitor.add_leavesobjects;mp(** Declare a module type in terms of a list of module bodies, by including them.
Typically used for `Module Type M := N <+ P`.
*)letdeclare_modtype_includesidargsresmexpr_l=letfs=Summary.Interp.freeze_summaries()inletmp,_,subtyps,_=RawModTypeOps.Interp.start_modtype_coreidargsresinletincl_objs=List.map_left(funx->IncludeObject(RawIncludeOps.Interp.declare_one_include_corex))mexpr_linletobjects={Lib.substobjs=incl_objs;keepobjs={keep_objects=[]};escapeobjs={escape_objects=[]};anticipateobjs=[];}inletmp,objects=RawModTypeOps.Interp.end_modtype_coreidsubtypsobjectsfsinInterpVisitor.add_leavesobjects;mpletdeclare_moduleidargsmtysme_l=matchme_lwith|[]->RawModOps.Interp.declare_moduleidargsmtysNone|[me]->RawModOps.Interp.declare_moduleidargsmtys(Someme)|me_l->declare_module_includesidargsmtysme_lletstart_modtype=RawModTypeOps.Interp.start_modtypeletend_modtype=RawModTypeOps.Interp.end_modtypeletdeclare_modtypeidargsmtysmty_l=matchmty_lwith|[]->assertfalse|[mty]->RawModTypeOps.Interp.declare_modtypeidargsmtysmty|mty_l->declare_modtype_includesidargsmtysmty_lletdeclare_includeme_asts=ifLib.sections_are_opened()thenuser_errPp.(str"Include is not allowed inside sections.");RawIncludeOps.Interp.declare_includeme_astsletregister_librarydircenv(objs:library_objects)digestvmtab=letmp=MPfiledirinletsp=path_of_filedirinlet()=try(* If the library was loaded inside a module or section, the
end_segment will replay the library object for non-kernel
effects but the kernel did not forget the library. *)ignore(Global.lookup_modulemp);withNot_found->beginletmp'=Global.importcenvvmtabdigestinifnot(ModPath.equalmpmp')thenanomaly(Pp.str"Unexpected disk module name.")endinletsobjs,keepobjs,escapeobjs=objsinInterpVisitor.load_module1spmp([],Objssobjs);InterpVisitor.load_escape1spmpescapeobjs;InterpVisitor.load_keep1spmpkeepobjsletimport_modules=InterpVisitor.import_modulesletimport_modulef~exportmp=import_modules~export[f,mp]letclose_section=InterpVisitor.close_sectionendletend_library_hook=ref[]letappend_end_library_hookf=end_library_hook:=f::!end_library_hookletend_library_hook()=List.iter(funf->f())(List.rev!end_library_hook)letend_library~output_native_objectsdir=end_library_hook();let{Lib.info;interp_objects=lib_stack;synterp_objects=lib_stack_syntax;}=Lib.end_compilationdirinletmp,cenv,vmlib,ast=Global.export~output_native_objectsdirinassert(ModPath.equalmp(MPfiledir));letdrop_anticipate{Lib.substobjs;keepobjs;escapeobjs;anticipateobjs=_}=(substobjs,keepobjs,escapeobjs)incenv,(drop_anticipatelib_stack),(drop_anticipatelib_stack_syntax),vmlib,ast,info(** {6 Iterators} *)letiter_all_interp_segmentsf=letrecapply_objprefixobj=matchobjwith|IncludeObjectaobjs->letobjs=InterpVisitor.expand_aobjsaobjsinList.iter(apply_objprefix)objs|_->fprefixobjinletrecsubst_view(obj:exp_substituted_object):Libobject.t=matchobjwith|KeepObject(_,o)|EscapeObject(_,o)->Empty.aborto|(AtomicObject_|ExportObject_|ModuleObject_|ModuleTypeObject_)aso->o|IncludeObjectaobjs->letaobjs=aobjs.exp_algebraic_objectsinIncludeObject(Objs(List.mapsubst_viewaobjs))inletapply_mod_obj_modobjs=letprefix=modobjs.module_prefixinList.iter(funobj->apply_objprefix(subst_viewobj))modobjs.module_substituted_objects;List.iter(funobj->apply_objprefixobj)modobjs.module_keep_objects.keep_objectsinletapply_nodes(node,os)=List.iter(funo->apply_obj(Lib.node_prefixnode)o)osinModPath.Map.iterapply_mod_obj(InterpVisitor.ModObjs.all());List.iterapply_nodes(Lib.contents())(** {6 Some types used to shorten declaremods.mli} *)typemodule_params=(lidentlist*(Constrexpr.module_ast*inline))listtypemodule_expr=(Modintern.module_struct_expr*ModPath.t*Modintern.module_kind*Entries.inline)typemodule_params_expr=(MBId.tlist*module_expr)list(** {6 Debug} *)letdebug_print_modtab()=InterpVisitor.debug_print_modtab()(** 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=letsp=Libnames.make_pathDirPath.empty(MBId.to_idmbid)inletmp=MPboundmbidinletsobjs=InterpVisitor.get_module_sobjsfalse(Global.env())(default_inline_level())meinletsubst=map_mp(get_module_pathme)mp(empty_delta_resolvermp)inletsobjs=subst_sobjssubstsobjsinSynterpVisitor.load_module1spmpsobjs;InterpVisitor.load_module1spmpsobjslet()=append_end_library_hookProfile_tactic.do_print_results_at_close