123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440(************************************************************************)(* * 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) *)(************************************************************************)openNamesopenModPathopenCErrorsopenUtilopenMinimlopenTableopenMlutil(*S Functions upon ML modules. *)(** Note: a syntax like [(F M) with ...] is actually legal, see for instance
bug #4720. Hence the code below tries to handle [MTsig], maybe not in
a perfect way, but that should be enough for the use of [se_iter] below. *)letrecmsid_of_mt=function|MTidentmp->mp|MTsig(mp,_)->mp|MTwith(mt,_)->msid_of_mtmt|MTfunsig_->assertfalse(* A functor cannot be inside a MTwith *)(*s Apply some functions upon all [ml_decl] and [ml_spec] found in a
[ml_structure]. *)letse_iterdo_decldo_specdo_mp=letrecmt_iter=function|MTidentmp->do_mpmp|MTfunsig(_,mt,mt')->mt_itermt;mt_itermt'|MTwith(mt,ML_With_type(rlv,idl,l,t))->letmp_mt=msid_of_mtmtinletl',idl'=List.sep_lastidlinletmp_w=List.fold_left(funmpl->MPdot(mp,Label.of_idl))mp_mtidl'inletr=GlobRef.ConstRef(Constant.make2mp_w(Label.of_idl'))inletr={glob=r;inst=rlv}inmt_itermt;do_spec(Stype(r,l,Somet))|MTwith(mt,ML_With_module(idl,mp))->letmp_mt=msid_of_mtmtinletmp_w=List.fold_left(funmpl->MPdot(mp,Label.of_idl))mp_mtidlinmt_itermt;do_mpmp_w;do_mpmp|MTsig(_,sign)->List.iterspec_itersignandspec_iter=function|(_,Specs)->do_specs|(_,Smodulemt)->mt_itermt|(_,Smodtypemt)->mt_itermtinletrecse_iter=function|(_,SEdecld)->do_decld|(_,SEmodulem)->me_iterm.ml_mod_expr;mt_iterm.ml_mod_type|(_,SEmodtypem)->mt_itermandme_iter=function|MEidentmp->do_mpmp|MEfunctor(_,mt,me)->me_iterme;mt_itermt|MEapply(me,me')->me_iterme;me_iterme'|MEstruct(msid,sel)->List.iterse_iterselinse_iterletstruct_iterdo_decldo_specdo_mps=List.iter(function(_,sel)->List.iter(se_iterdo_decldo_specdo_mp)sel)s(*s Apply some fonctions upon all references in [ml_type], [ml_ast],
[ml_decl], [ml_spec] and [ml_structure]. *)typedo_ref=global->unitletrecord_iter_referencesdo_term=function|Recordl->List.iter(Option.iterdo_term)l|_->()lettype_iter_referencesdo_typet=letreciter=function|Tglob(r,l)->do_typer;List.iteriterl|Tarr(a,b)->itera;iterb|_->()initertletpatt_iter_referencesdo_consp=letreciter=function|Pcons(r,l)->do_consr;List.iteriterl|Pusualr->do_consr|Ptuplel->List.iteriterl|Prel_|Pwild->()initerpletast_iter_referencesdo_termdo_consdo_typea=letrecitera=ast_iteritera;matchawith|MLglobr->do_termr|MLcons(_,r,_)->do_consr|MLcase(ty,_,v)->type_iter_referencesdo_typety;Array.iter(fun(_,p,_)->patt_iter_referencesdo_consp)v|MLrel_|MLlam_|MLapp_|MLletin_|MLtuple_|MLfix_|MLexn_|MLdummy_|MLaxiom_|MLmagic_|MLuint_|MLfloat_|MLstring_|MLparray_->()initeraletind_iter_referencesdo_termdo_consdo_typeind=lettype_iter=type_iter_referencesdo_typeinletcons_itercpl=do_conscp;List.itertype_iterlinletpacket_iterip=let()=do_typep.ip_typename_refinlet()=iflang()==Ocamlthenbeginletinst=ind.ind_packets.(0).ip_typename_ref.instin(matchind.ind_equivwith|Miniml.Equivkne->do_type{glob=(GlobRef.IndRef(MutInd.make1kne,i));inst};|_->())endinArray.iteri(funj->cons_iterp.ip_consnames_ref.(j))p.ip_typesinlet()=iflang()==Ocamlthenrecord_iter_referencesdo_termind.ind_kindinArray.iteri(funip->packet_iterip)ind.ind_packetsletdecl_iter_referencesdo_termdo_consdo_type=lettype_iter=type_iter_referencesdo_typeandast_iter=ast_iter_referencesdo_termdo_consdo_typeinfunction|Dindind->ind_iter_referencesdo_termdo_consdo_typeind|Dtype(r,_,t)->do_typer;type_itert|Dterm(r,a,t)->do_termr;ast_itera;type_itert|Dfix(rv,c,t)->Array.iterdo_termrv;Array.iterast_iterc;Array.itertype_itertletspec_iter_referencesdo_termdo_consdo_type=function|Sindind->ind_iter_referencesdo_termdo_consdo_typeind|Stype(r,_,ot)->do_typer;Option.iter(type_iter_referencesdo_type)ot|Sval(r,t)->do_termr;type_iter_referencesdo_typet(*s Searching occurrences of a particular term (no lifting done). *)exceptionFoundletrecast_searchfa=iffathenraiseFoundelseast_iter(ast_searchf)aletdecl_ast_searchf=function|Dterm(_,a,_)->ast_searchfa|Dfix(_,c,_)->Array.iter(ast_searchf)c|_->()letstruct_ast_searchfs=trystruct_iter(decl_ast_searchf)(fun_->())(fun_->())s;falsewithFound->trueletrectype_searchf=function|Tarr(a,b)->type_searchfa;type_searchfb|Tglob(r,l)->List.iter(type_searchf)l|u->iffuthenraiseFoundletdecl_type_searchf=function|Dind{ind_packets=p}->Array.iter(fun{ip_types=v}->Array.iter(List.iter(type_searchf))v)p|Dterm(_,_,u)->type_searchfu|Dfix(_,_,v)->Array.iter(type_searchf)v|Dtype(_,_,u)->type_searchfuletspec_type_searchf=function|Sind{ind_packets=p}->Array.iter(fun{ip_types=v}->Array.iter(List.iter(type_searchf))v)p|Stype(_,_,ot)->Option.iter(type_searchf)ot|Sval(_,u)->type_searchfuletstruct_type_searchfs=trystruct_iter(decl_type_searchf)(spec_type_searchf)(fun_->())s;falsewithFound->true(*s Generating the signature. *)letrecmsig_of_ms=function|[]->[]|(l,SEdecl(Dindi))::ms->(l,Spec(Sindi))::(msig_of_msms)|(l,SEdecl(Dterm(r,_,t)))::ms->(l,Spec(Sval(r,t)))::(msig_of_msms)|(l,SEdecl(Dtype(r,v,t)))::ms->(l,Spec(Stype(r,v,Somet)))::(msig_of_msms)|(l,SEdecl(Dfix(rv,_,tv)))::ms->letmsig=ref(msig_of_msms)infori=Array.lengthrv-1downto0domsig:=(l,Spec(Sval(rv.(i),tv.(i))))::!msigdone;!msig|(l,SEmodulem)::ms->(l,Smodulem.ml_mod_type)::(msig_of_msms)|(l,SEmodtypem)::ms->(l,Smodtypem)::(msig_of_msms)letsignature_of_structures=List.map(fun(mp,ms)->mp,msig_of_msms)sletrecmtyp_of_mexpr=function|MEfunctor(id,ty,e)->MTfunsig(id,ty,mtyp_of_mexpre)|MEstruct(mp,str)->MTsig(mp,msig_of_msstr)|_->assertfalse(*s Searching one [ml_decl] in a [ml_structure] by its [global_reference] *)letis_modular=function|SEdecl_->false|SEmodule_|SEmodtype_->trueletrecsearch_structurelm=function|[]->raiseNot_found|(lab,d)::_whenLabel.equallabl&&(is_modulard:bool)==m->d|_::fields->search_structurelmfieldsletget_decl_in_structurerstruc=tryletbase_mp,ll=labels_of_refrinifnot(at_toplevelbase_mp)thenerror_not_visibler;letsel=List.assoc_fModPath.equalbase_mpstrucinletrecgollsel=matchllwith|[]->assertfalse|l::ll->matchsearch_structurel(not(List.is_emptyll))selwith|SEdecld->d|SEmodtypem->assertfalse|SEmodulem->letrecaux=function|MEstruct(_,sel)->gollsel|MEfunctor(_,_,sel)->auxsel|MEident_|MEapply_->error_not_visiblerinauxm.ml_mod_expringollselwithNot_found->anomaly(Pp.str"reference not found in extracted structure.")(*s Optimization of a [ml_structure]. *)(* Some transformations of ML terms. [optimize_struct] simplify
all beta redexes (when the argument does not occur, it is just
thrown away; when it occurs exactly once it is substituted; otherwise
a let-in redex is created for clarity) and iota redexes, plus some other
optimizations. *)letdfix_to_mlfixrvavi=letrecmake_substns=ifn<0thenselsemake_subst(n-1)(Refmap'.addrv.(n)(n+1)s)inlets=make_subst(Array.lengthrv-1)Refmap'.emptyinletrecsubstnt=matchtwith|MLglobrefe->(tryMLrel(n+(Refmap'.findrefes))withNot_found->t)|_->ast_map_liftsubstntinletids=Array.map(funr->Label.to_id(label_of_rr))rvinletc=Array.map(subst0)avinMLfix(i,ids,c)(* [optim_se] applies the [normalize] function everywhere and does the
inlining of code. The inlined functions are kept for the moment in
order to preserve the global interface, later [depcheck_se] will get
rid of them if possible *)letrecoptim_setabletopto_appears=function|[]->[]|(l,SEdecl(Dterm(r,a,t)))::lse->leta=normalize(ast_glob_subst!sa)inleti=inlinetablerainifithens:=Refmap'.addra!s;letd=matchdump_unused_vars(optimize_fixa)with|MLfix(0,_,[|c|])->Dfix([|r|],[|ast_subst(MLglobr)c|],[|t|])|a->Dterm(r,a,t)in(l,SEdecld)::(optim_setabletopto_appearslse)|(l,SEdecl(Dfix(rv,av,tv)))::lse->letav=Array.map(funa->normalize(ast_glob_subst!sa))avin(* This fake body ensures that no fixpoint will be auto-inlined. *)letfake_body=MLfix(0,[||],[||])infori=0toArray.lengthrv-1doifinlinetablerv.(i)fake_bodythens:=Refmap'.addrv.(i)(dfix_to_mlfixrvavi)!sdone;letav'=Array.mapdump_unused_varsavin(l,SEdecl(Dfix(rv,av',tv)))::(optim_setabletopto_appearslse)|(l,SEmodulem)::lse->letm={mwithml_mod_expr=optim_metableto_appearsm.ml_mod_expr}in(l,SEmodulem)::(optim_setabletopto_appearslse)|se::lse->se::(optim_setabletopto_appearslse)andoptim_metableto_appears=function|MEstruct(msid,lse)->MEstruct(msid,optim_setablefalseto_appearslse)|MEidentmpasme->me|MEapply(me,me')->MEapply(optim_metableto_appearsme,optim_metableto_appearsme')|MEfunctor(mbid,mt,me)->MEfunctor(mbid,mt,optim_metableto_appearsme)(* After these optimisations, some dependencies may not be needed anymore.
For non-library extraction, we recompute a minimal set of dependencies
for first-level definitions (no module pruning yet). *)letbase_rr=letopenGlobRefinmatchr.globwith|ConstRef_->r|IndRef(kn,_)->{glob=IndRef(kn,0);inst=r.inst}|ConstructRef((kn,_),_)->{glob=IndRef(kn,0);inst=r.inst}|_->assertfalsetypeneeded={needed_mp:MPset.t;needed_rf:Refset'.t;}letadd_neededndr=nd:={!ndwithneeded_rf=Refset'.add(base_rr)!nd.needed_rf}letadd_needed_mpndmp=nd:={!ndwithneeded_mp=MPset.addmp!nd.needed_mp}letfound_neededndr=nd:={!ndwithneeded_rf=Refset'.remove(base_rr)!nd.needed_rf}letis_neededndr=letr=base_rrinRefset'.memrnd.needed_rf||MPset.mem(modpath_of_rr)nd.needed_mpletdeclared_refs=function|Dindp->[p.ind_packets.(0).ip_typename_ref]|Dtype(r,_,_)->[r]|Dterm(r,_,_)->[r]|Dfix(rv,_,_)->Array.to_listrv(* Computes the dependencies of a declaration, except in case
of custom extraction. *)letcompute_deps_declnddecl=letadd_neededr=add_neededndrinmatchdeclwith|Dindind->(* Todo Later : avoid dependencies when Extract Inductive *)ind_iter_referencesadd_neededadd_neededadd_neededind|Dtype(r,ids,t)->ifnot(is_customr)thentype_iter_referencesadd_neededt|Dterm(r,u,t)->type_iter_referencesadd_neededt;ifnot(is_customr)thenast_iter_referencesadd_neededadd_neededadd_neededu|Dfix_asd->decl_iter_referencesadd_neededadd_neededadd_neededdletcompute_deps_specndspc=letadd_neededr=add_neededndrinmatchspcwith|Sindind->(* Todo Later : avoid dependencies when Extract Inductive *)ind_iter_referencesadd_neededadd_neededadd_neededind|Stype(r,ids,t)->ifnot(is_customr)thenOption.iter(type_iter_referencesadd_needed)t|Sval(r,t)->type_iter_referencesadd_neededtletrecdepcheck_setablend=function|[]->[]|((l,SEdecld)ast)::se->letse'=depcheck_setablendseinletrefs=declared_refsdinletrefs'=List.filter(funr->is_needed!ndr)refsinifList.is_emptyrefs'then(List.iter(funr->remove_info_axiomtabler)refs;List.iter(funr->remove_opaquetabler)refs;se')elselet()=List.iter(funr->found_neededndr)refs'in(* Hack to avoid extracting unused part of a Dfix *)beginmatchdwith|Dfix(rv,trms,tys)when(List.for_allis_customrefs')->lettrms'=Array.make(Array.lengthrv)(MLexn"UNUSED")in((l,SEdecl(Dfix(rv,trms',tys)))::se')|_->let()=compute_deps_declnddint::se'end|t::se->letse'=depcheck_setablendseinletiter_decld=compute_deps_declnddinletiter_specs=compute_deps_specndsinletiter_mpmp=add_needed_mpndmpinlet()=se_iteriter_decliter_speciter_mptint::se'letrecdepcheck_structtablend=function|[]->[]|(mp,lse)::struc->letstruc'=depcheck_structtablendstrucinletlse'=depcheck_setablendlseinifList.is_emptylse'thenstruc'else(mp,lse')::struc'exceptionRemainingImplicitofkill_reasonletcheck_for_remaining_implicitsstruc=letcheck=function|MLdummy(Kimplicit_ask)->raise(RemainingImplicitk)|_->falseintryignore(struct_ast_searchcheckstruc)withRemainingImplicitk->err_or_warn_remaining_implicitkletoptimize_structtableto_appearstruc=letsubst=ref(Refmap'.empty:ml_astRefmap'.t)inletopt_struc=List.map(fun(mp,lse)->(mp,optim_se(Common.State.get_tabletable)true(fstto_appear)substlse))strucinletmini_struc=ifCommon.State.get_librarytablethenList.filter(fun(_,lse)->not(List.is_emptylse))opt_strucelseletnd=ref{needed_mp=MPset.empty;needed_rf=Refset'.empty}inlet()=List.iter(funr->add_neededndr)(fstto_appear)inlet()=List.iter(funmp->add_needed_mpndmp)(sndto_appear)indepcheck_struct(Common.State.get_tabletable)ndopt_strucinlet()=check_for_remaining_implicitsmini_strucinmini_struc