123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216(************************************************************************)(* * 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) *)(************************************************************************)(* File created by Vincent Siles, Oct 2007, extended into a generic
support for generation of inductive schemes by Hugo Herbelin, Nov 2009 *)(* This file provides support for registering inductive scheme builders,
declaring schemes and generating schemes on demand *)openNamesopenNameopsopenDeclarationsopenConstropenCErrorsopenUtilopenPp(**********************************************************************)(* Registering schemes in the environment *)typehandle=Evd.side_effectstypemutual_scheme_object_function=Environ.env->handle->MutInd.t->constrarrayEvd.in_evar_universe_contexttypeindividual_scheme_object_function=Environ.env->handle->inductive->constrEvd.in_evar_universe_contexttype'ascheme_kind=stringletpr_scheme_kind=Pp.str(**********************************************************************)(* The table of scheme building functions *)typeindividualtypemutualtypescheme_dependency=|SchemeMutualDepofMutInd.t*mutualscheme_kind|SchemeIndividualDepofinductive*individualscheme_kindtypescheme_object_function=|MutualSchemeFunctionofmutual_scheme_object_function*(Environ.env->MutInd.t->scheme_dependencylist)option|IndividualSchemeFunctionofindividual_scheme_object_function*(Environ.env->inductive->scheme_dependencylist)optionletscheme_object_table=(Hashtbl.create17:(string,string*scheme_object_function)Hashtbl.t)letdeclare_scheme_objectsauxf=let()=ifnot(Id.is_valid("ind"^s))thenuser_errPp.(str("Illegal induction scheme suffix: "^s))inletkey=ifString.is_emptyauxthenselseauxintrylet_=Hashtbl.findscheme_object_tablekeyin(* let aux_msg = if aux="" then "" else " (with key "^aux^")" in*)user_err(str"Scheme object "++strkey++str" already declared.")withNot_found->Hashtbl.addscheme_object_tablekey(s,f);keyletdeclare_mutual_scheme_objects?deps?(aux="")f=declare_scheme_objectsaux(MutualSchemeFunction(f,deps))letdeclare_individual_scheme_objects?deps?(aux="")f=declare_scheme_objectsaux(IndividualSchemeFunction(f,deps))(**********************************************************************)(* Defining/retrieving schemes *)letis_visible_nameid=tryignore(Nametab.locate(Libnames.qualid_of_identid));truewithNot_found->falseletcompute_nameinternalid=ifinternalthenNamegen.next_ident_away_from(add_prefix"internal_"id)is_visible_nameelseidletdeclare_definition_scheme=ref(fun~internal~univs~role~namec->CErrors.anomaly(Pp.str"scheme declaration not registered"))letlookup_schemekindind=trySome(DeclareScheme.lookup_schemekindind)withNot_found->Noneletredeclare_schemeseff=letfoldcroleaccu=matchrolewith|Evd.Schema(ind,kind)->trylet_=DeclareScheme.lookup_schemekindindinaccuwithNot_found->letold=tryString.Map.findkindaccuwithNot_found->[]inString.Map.addkind((ind,c)::old)accuinletschemes=Cmap.foldfoldeff.Evd.seff_rolesString.Map.emptyinletiterkinddefs=letdefs=Array.of_listdefsinDeclareScheme.declare_schemekinddefsinString.Map.iteriterschemesletlocal_lookup_schemeeffkindind=matchlookup_schemekindindwith|Some_asans->ans|None->letexceptionFoundofConstant.tinletitercrole=matchrolewith|Evd.Schema(i,k)->ifString.equalkkind&&Ind.CanOrd.equaliindthenraise(Foundc)in(* Inefficient O(n), but the number of locally declared schemes is small and
this is very rarely called *)trylet_=Cmap.iteritereff.Evd.seff_rolesinNonewithFoundc->Somecletlocal_check_schemekindindeff=Option.has_some(local_lookup_schemeeffkindind)letdefineinternalroleidcpolyunivs=letid=compute_nameinternalidinletuctx=UState.minimizeunivsinletc=UState.nf_universesuctxcinletunivs=UState.univ_entry~polyuctxin!declare_definition_scheme~internal~univs~role~name:idc(* Assumes that dependencies are already defined *)letrecdefine_individual_scheme_basekindsufff~internalidopt(mind,iasind)eff=(* FIXME: do not rely on the imperative modification of the global environment *)let(c,ctx)=f(Global.env())effindinletmib=Global.lookup_mindmindinletid=matchidoptwith|Someid->id|None->add_suffixmib.mind_packets.(i).mind_typenamesuffinletrole=Evd.Schema(ind,kind)inletconst,neff=defineinternalroleidc(Declareops.inductive_is_polymorphicmib)ctxinleteff=Evd.concat_side_effectsneffeffinconst,effanddefine_individual_schemekind~internalnames(mind,iasind)=matchHashtbl.findscheme_object_tablekindwith|_,MutualSchemeFunction_->assertfalse|s,IndividualSchemeFunction(f,deps)->letdeps=matchdepswithNone->[]|Somedeps->deps(Global.env())indinleteff=List.fold_left(funeffdep->declare_scheme_dependenceeffdep)Evd.empty_side_effectsdepsindefine_individual_scheme_basekindsf~internalnamesindeff(* Assumes that dependencies are already defined *)anddefine_mutual_scheme_basekindsufff~internalnamesmindeff=(* FIXME: do not rely on the imperative modification of the global environment *)let(cl,ctx)=f(Global.env())effmindinletmib=Global.lookup_mindmindinletids=Array.init(Array.lengthmib.mind_packets)(funi->tryInt.List.associnameswithNot_found->add_suffixmib.mind_packets.(i).mind_typenamesuff)inletfoldieffsidcl=letrole=Evd.Schema((mind,i),kind)inletcst,neff=defineinternalroleidcl(Declareops.inductive_is_polymorphicmib)ctxin(Evd.concat_side_effectsneffeffs,cst)inlet(eff,consts)=Array.fold_left2_map_ifoldeffidsclinconsts,effanddefine_mutual_schemekind~internalnamesmind=matchHashtbl.findscheme_object_tablekindwith|_,IndividualSchemeFunction_->assertfalse|s,MutualSchemeFunction(f,deps)->letdeps=matchdepswithNone->[]|Somedeps->deps(Global.env())mindinleteff=List.fold_left(funeffdep->declare_scheme_dependenceeffdep)Evd.empty_side_effectsdepsindefine_mutual_scheme_basekindsf~internalnamesmindeffanddeclare_scheme_dependenceeff=function|SchemeIndividualDep(ind,kind)->iflocal_check_schemekindindefftheneffelselet_,eff'=define_individual_schemekind~internal:trueNoneindinEvd.concat_side_effectseff'eff|SchemeMutualDep(mind,kind)->iflocal_check_schemekind(mind,0)efftheneffelselet_,eff'=define_mutual_schemekind~internal:true[]mindinEvd.concat_side_effectseff'effletfind_schemekind(mind,iasind)=letopenProofview.NotationsinProofview.tclEVARMAP>>=funsigma->matchlocal_lookup_scheme(Evd.eval_side_effectssigma)kindindwith|Somes->Proofview.tclUNITs|None->matchHashtbl.findscheme_object_tablekindwith|s,IndividualSchemeFunction(f,deps)->letdeps=matchdepswithNone->[]|Somedeps->deps(Global.env())indinleteff=List.fold_left(funeffdep->declare_scheme_dependenceeffdep)Evd.empty_side_effectsdepsinletc,eff=define_individual_scheme_basekindsf~internal:trueNoneindeffinProofview.tclEFFECTSeff<*>Proofview.tclUNITc|s,MutualSchemeFunction(f,deps)->letdeps=matchdepswithNone->[]|Somedeps->deps(Global.env())mindinleteff=List.fold_left(funeffdep->declare_scheme_dependenceeffdep)Evd.empty_side_effectsdepsinletca,eff=define_mutual_scheme_basekindsf~internal:true[]mindeffinProofview.tclEFFECTSeff<*>Proofview.tclUNITca.(i)letdefine_individual_schemekindnamesind=let_,eff=define_individual_schemekind~internal:falsenamesindinredeclare_schemeseffletdefine_mutual_schemekindnamesmind=let_,eff=define_mutual_schemekind~internal:falsenamesmindinredeclare_schemeseff