123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenNamesopenDeclarationsopenDeclareopsopenMod_substtype(_,'v)when_mod_body=|ModBodyVal:'v->(mod_body,'v)when_mod_body|ModTypeNul:(mod_type,'v)when_mod_bodytypestructure_field_body=(module_body,module_type_body)Declarations.structure_field_bodyandstructure_body=(module_body,module_type_body)Declarations.structure_body(** A module signature is a structure, with possibly functors on top of it *)andmodule_signature=(module_type_body,structure_body)functorizeandmodule_implementation=|Abstract(** no accessible implementation *)|Algebraicofmodule_expression(** non-interactive algebraic expression *)|Structofstructure_body(** interactive body living in the parameter context of [mod_type] *)|FullStruct(** special case of [Struct] : the body is exactly [mod_type] *)and'ageneric_module_body={mod_expr:('a,module_implementation)when_mod_body;(** implementation *)mod_type:module_signature;(** expanded type *)mod_type_alg:module_expressionoption;(** algebraic type *)mod_delta:Mod_subst.delta_resolver;(**
quotiented set of equivalent constants and inductive names *)mod_retroknowledge:('a,Retroknowledge.actionlist)when_mod_body}(** For a module, there are five possible situations:
- [Declare Module M : T] then [mod_expr = Abstract; mod_type_alg = Some T]
- [Module M := E] then [mod_expr = Algebraic E; mod_type_alg = None]
- [Module M : T := E] then [mod_expr = Algebraic E; mod_type_alg = Some T]
- [Module M. ... End M] then [mod_expr = FullStruct; mod_type_alg = None]
- [Module M : T. ... End M] then [mod_expr = Struct; mod_type_alg = Some T]
And of course, all these situations may be functors or not. *)andmodule_body=mod_bodygeneric_module_body(** A [module_type_body] is just a [module_body] with no implementation and
also an empty [mod_retroknowledge]. Its [mod_type_alg] contains
the algebraic definition of this module type, or [None]
if it has been built interactively. *)andmodule_type_body=mod_typegeneric_module_bodytype'amodule_retroknowledge=('a,Retroknowledge.actionlist)when_mod_body(** Extra invariants :
- No [MEwith] inside a [mod_expr] implementation : the 'with' syntax
is only supported for module types
- A module application is atomic, for instance ((M N) P) :
* the head of [MEapply] can only be another [MEapply] or a [MEident]
* the argument of [MEapply] is now directly forced to be a [ModPath.t].
*)(** Builders *)letmake_module_bodytypdeltaretro={mod_expr=ModBodyValFullStruct;mod_type=typ;mod_type_alg=None;mod_delta=delta;mod_retroknowledge=ModBodyValretro;}letmake_module_typetypdelta={mod_expr=ModTypeNul;mod_type=typ;mod_type_alg=None;mod_delta=delta;mod_retroknowledge=ModTypeNul;}letstrengthen_module_body~srctypdeltamb={mbwithmod_expr=ModBodyVal(Algebraic(MENoFunctor(MEidentsrc)));mod_type=typ;mod_delta=delta;}letstrengthen_module_typestrucdeltamtb={mtbwithmod_type=NoFunctorstruc;mod_delta=delta}letreplace_module_bodystrucdeltamb=(* This is only used by "with Module", we should try to inherit the algebraic type *)let()=matchmb.mod_exprwithModBodyValAbstract->()|_->assertfalseinlet()=matchmb.mod_typewithNoFunctor_->()|MoreFunctor_->assertfalsein{mbwithmod_type=NoFunctorstruc;mod_type_alg=None;mod_delta=delta}letmodule_type_of_modulemb={mbwithmod_expr=ModTypeNul;mod_type_alg=None;mod_retroknowledge=ModTypeNul;}letmodule_body_of_typemtb={mtbwithmod_expr=ModBodyValAbstract;mod_retroknowledge=ModBodyVal[];}(** Setters *)letset_implementationemb={mbwithmod_expr=ModBodyVale}letset_algebraic_typembalg={mbwithmod_type_alg=Somealg}letset_retroknowledgembrk={mbwithmod_retroknowledge=ModBodyValrk}(** Accessors *)letmod_expr{mod_expr=ModBodyValv;_}=vletmod_typem=m.mod_typeletmod_type_algm=m.mod_type_algletmod_deltam=m.mod_deltaletmod_retroknowledge{mod_retroknowledge=ModBodyValrk;_}=rkletmod_global_deltam=matchm.mod_typewith|MoreFunctor_->None|NoFunctor_->Somem.mod_delta(** Hashconsing of modules *)lethcons_when_mod_body(typeab)(f:b->b):(a,b)when_mod_body->(a,b)when_mod_body=function|ModBodyValvasarg->letv'=fvinifv==v'thenargelseModBodyValv'|ModTypeNul->ModTypeNullethcons_functorizehtyhehselff=matchfwith|NoFunctore->lete'=heeinife==e'thenfelseNoFunctore'|MoreFunctor(mid,ty,nf)->(** FIXME *)letmid'=midinletty'=htytyinletnf'=hselfnfinifmid==mid'&&ty==ty'&&nf==nf'thenfelseMoreFunctor(mid,ty',nf')lethcons_module_alg_exprme=meletrechcons_module_expressionme=matchmewith|MENoFunctormalg->letmalg'=hcons_module_alg_exprmalginifmalg==malg'thenmeelseMENoFunctormalg'|MEMoreFunctormf->letmf'=hcons_module_expressionmfinifmf'==mfthenmeelseMEMoreFunctormf'letrechcons_structure_field_bodysb=matchsbwith|SFBconstcb->letcb'=hcons_const_bodycbinifcb==cb'thensbelseSFBconstcb'|SFBmindmib->letmib'=hcons_mindmibinifmib==mib'thensbelseSFBmindmib'|SFBmodulemb->letmb'=hcons_generic_module_bodymbinifmb==mb'thensbelseSFBmodulemb'|SFBmodtypemb->letmb'=hcons_generic_module_bodymbinifmb==mb'thensbelseSFBmodtypemb'|SFBrules_->sb(* TODO? *)andhcons_structure_bodysb=(** FIXME *)letmap(l,sfbasfb)=let_,l'=Names.Label.hconslinletsfb'=hcons_structure_field_bodysfbinifl==l'&&sfb==sfb'thenfbelse(l',sfb')inList.Smart.mapmapsbandhcons_module_signaturems=hcons_functorizehcons_generic_module_bodyhcons_structure_bodyhcons_module_signaturemsandhcons_module_implementationmip=matchmipwith|Abstract->Abstract|Algebraicme->letme'=hcons_module_expressionmeinifme==me'thenmipelseAlgebraicme'|Structms->letms'=hcons_structure_bodymsinifms==ms'thenmipelseStructms|FullStruct->FullStructandhcons_generic_module_body:'a.'ageneric_module_body->'ageneric_module_body=funmb->letexpr'=hcons_when_mod_bodyhcons_module_implementationmb.mod_exprinlettype'=hcons_module_signaturemb.mod_typeinlettype_alg'=mb.mod_type_alginletdelta'=mb.mod_deltainletretroknowledge'=mb.mod_retroknowledgeinifmb.mod_expr==expr'&&mb.mod_type==type'&&mb.mod_type_alg==type_alg'&&mb.mod_delta==delta'&&mb.mod_retroknowledge==retroknowledge'thenmbelse{mod_expr=expr';mod_type=type';mod_type_alg=type_alg';mod_delta=delta';mod_retroknowledge=retroknowledge';}lethcons_module_body=hcons_generic_module_bodylethcons_module_type=hcons_generic_module_body(** Operators *)letrecfunctor_smart_mapftyf0funct=matchfunctwith|MoreFunctor(mbid,ty,e)->letty'=ftymbidtyinlete'=functor_smart_mapftyf0einifty==ty'&&e==e'thenfunctelseMoreFunctor(mbid,ty',e')|NoFunctora->leta'=f0ainifa==a'thenfunctelseNoFunctora'letimplem_smart_map(typea)fsfa(expr:(a,_)when_mod_body):(a,_)when_mod_body=matchexprwith|ModTypeNul->ModTypeNul|ModBodyValimpl->matchimplwith|Structe->lete'=fseinife==e'thenexprelseModBodyVal(Structe')|Algebraica->leta'=faainifa==a'thenexprelseModBodyVal(Algebraica')|Abstract|FullStruct->exprletfunctorizeparamsinit=List.fold_left(fune(mbid,mt)->MoreFunctor(mbid,mt,e))initparamsletfunctorize_moduleparamsmb=letfx=functorizeparamsxinletfex=iterate(fune->MEMoreFunctore)(List.lengthparams)xin{mbwithmod_expr=implem_smart_map(funx->x)femb.mod_expr;mod_type=fmb.mod_type;mod_type_alg=Option.mapfemb.mod_type_alg}(** Substitutions of modular structures *)typesubst_kind=Dom|Codom|Both|Neither|ShallowofMod_subst.substitutionletsubst_dom=Domletsubst_codom=Codomletsubst_dom_codom=Bothletsubst_shallow_dom_codoms=Shallowsletapply_substskindsubstdelta=matchskindwith|Dom->subst_dom_delta_resolversubstdelta|Codom->subst_codom_delta_resolversubstdelta|Both->subst_dom_codom_delta_resolversubstdelta|Neither->delta|Shallowsubst'->subst_dom_codom_delta_resolversubst'delta(* ignore subst *)letis_functor=function|NoFunctor_->false|MoreFunctor_->trueletsubst_with_bodysubst=function|WithMod(id,mp)asorig->letmp'=subst_mpsubstmpinifmp==mp'thenorigelseWithMod(id,mp')|WithDef(id,(c,ctx))asorig->letc'=subst_mpssubstcinifc==c'thenorigelseWithDef(id,(c',ctx))letsubst_retro:typea.Mod_subst.substitution->amodule_retroknowledge->amodule_retroknowledge=funsubstretro->matchretrowith|ModTypeNulasr->r|ModBodyVallasr->letl'=List.Smart.map(subst_retro_actionsubst)linifl==l'thenrelseModBodyVallletrecsubst_structureskindsubstmpsign=letsubst_field((l,body)asorig)=matchbodywith|SFBconstcb->letcb'=subst_const_bodysubstcbinifcb==cb'thenorigelse(l,SFBconstcb')|SFBmindmib->letmib'=subst_mind_bodysubstmibinifmib==mib'thenorigelse(l,SFBmindmib')|SFBrulesrrb->letrrb'=subst_rewrite_rulessubstrrbinifrrb==rrb'thenorigelse(l,SFBrulesrrb')|SFBmodulemb->letmb'=subst_moduleskindsubst(MPdot(mp,l))mbinifmb==mb'thenorigelse(l,SFBmodulemb')|SFBmodtypemtb->letmtb'=subst_modtypeskindsubst(MPdot(mp,l))mtbinifmtb==mtb'thenorigelse(l,SFBmodtypemtb')inList.Smart.mapsubst_fieldsignandsubst_module_body:typea._->_->_->_->ageneric_module_body->ageneric_module_body=funis_modskindsubstmpmb->let{mod_expr=me;mod_type=ty;mod_type_alg=aty;mod_retroknowledge=retro;_}=mbinletmp'=subst_mpsubstmpinletsubst=ifModPath.equalmpmp'thensubstelseifis_mod&¬(is_functorty)thensubstelseadd_mpmpmp'(empty_delta_resolvermp')substinletty'=subst_signatureskindsubstmptyinletme'=subst_implsubstmpmeinletaty'=Option.Smart.map(subst_expressionsubst)atyinletretro'=subst_retrosubstretroinletdelta'=apply_substskindsubstmb.mod_deltainifmp==mp'&&me==me'&&ty==ty'&&aty==aty'&&retro==retro'&&delta'==mb.mod_deltathenmbelse{mod_expr=me';mod_type=ty';mod_type_alg=aty';mod_retroknowledge=retro';mod_delta=delta';}andsubst_moduleskindsubstmpmb=subst_module_bodytrueskindsubstmpmbandsubst_impl:typea._->_->(a,_)when_mod_body->(a,_)when_mod_body=funsubstmpme->implem_smart_map(funsign->subst_structureNeithersubstmpsign)(subst_expressionsubst)meandsubst_modtypeskindsubstmpmtb=subst_module_bodyfalseskindsubstmpmtbandsubst_exprsubstseb=matchsebwith|MEidentmp->letmp'=subst_mpsubstmpinifmp==mp'thensebelseMEidentmp'|MEapply(meb1,mp2)->letmeb1'=subst_exprsubstmeb1inletmp2'=subst_mpsubstmp2inifmeb1==meb1'&&mp2==mp2'thensebelseMEapply(meb1',mp2')|MEwith(meb,wdb)->letmeb'=subst_exprsubstmebinletwdb'=subst_with_bodysubstwdbinifmeb==meb'&&wdb==wdb'thensebelseMEwith(meb',wdb')andsubst_expressionsubstme=matchmewith|MENoFunctormalg->letmalg'=subst_exprsubstmalginifmalg==malg'thenmeelseMENoFunctormalg'|MEMoreFunctormf->letmf'=subst_expressionsubstmfinifmf==mf'thenmeelseMEMoreFunctormf'andsubst_signatureskindsubstmp=functor_smart_map(funmbidmtb->subst_modtypeskindsubst(MPboundmbid)mtb)(funsign->subst_structureskindsubstmpsign)(** Cleaning a module expression from bounded parts
For instance:
functor(X:T)->struct module M:=X end)
becomes:
functor(X:T)->struct module M:=<content of T> end)
*)type'amod_expr=('a,module_implementation)when_mod_bodyletrecis_bounded_exprl=function|MEident(MPboundmbid)->MBIset.memmbidl|MEapply(fexpr,mp)->is_bounded_exprl(MEidentmp)||is_bounded_exprlfexpr|_->falseletrecclean_module_body:typea._->ageneric_module_body->ageneric_module_body=funlmb->lettyp=mb.mod_typeinlettyp'=clean_signatureltypinletexpr'=clean_mod_exprlmb.mod_expriniftyp==typ'&&mb.mod_expr==expr'thenmbelse{mbwithmod_type=typ';mod_expr=expr'}andclean_fieldlfield=matchfieldwith|(lab,SFBmodulemb)->letmb'=clean_module_bodylmbinifmb==mb'thenfieldelse(lab,SFBmodulemb')|_->fieldandclean_structurel=List.Smart.map(clean_fieldl)andclean_signaturel=functor_smart_map(fun_mb->clean_module_bodylmb)(clean_structurel)andclean_expression_me=meandclean_mod_expr:typea._->amod_expr->amod_expr=funlme->matchmewith|ModBodyVal(Algebraic(MENoFunctorm))whenis_bounded_exprlm->ModBodyValFullStruct|_->letme'=implem_smart_map(clean_structurel)(clean_expressionl)meinifme==me'thenmeelseme'