123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254(************************************************************************)(* * 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 *)openNamesopenNameopsopenDeclarationsopenConstropenUtil(**********************************************************************)(* 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_objectkey?(suff=key)f=let()=ifnot(Id.is_valid("ind_"^suff))thenCErrors.user_errPp.(str("Illegal induction scheme suffix: "^suff))inifHashtbl.memscheme_object_tablekeythenCErrors.user_errPp.(str"Scheme object "++strkey++str" already declared.")elsebeginHashtbl.addscheme_object_tablekey(suff,f);keyendletdeclare_mutual_scheme_objectkey?suff?depsf=declare_scheme_objectkey?suff(MutualSchemeFunction(f,deps))letdeclare_individual_scheme_objectkey?suff?depsf=declare_scheme_objectkey?suff(IndividualSchemeFunction(f,deps))letis_declared_scheme_objectkey=Hashtbl.memscheme_object_tablekeyletscheme_kind_name(key:_scheme_kind):string=key(**********************************************************************)(* 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~name?locc->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=List.iter(DeclareScheme.declare_schemekind)defsinString.Map.iteriterschemesletlocal_lookup_schemeeffkindind=matchlookup_schemekindindwith|Some_asans->ans|None->letexceptionFoundofConstant.tinletitercrole=matchrolewith|Evd.Schema(i,k)->ifString.equalkkind&&Ind.UserOrd.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)letdefine?locinternalroleidcpolyunivs=letid=compute_nameinternalidinletuctx=UState.minimizeunivsinletc=UState.nf_universesuctxcinletunivs=UState.univ_entry~polyuctxin!declare_definition_scheme~internal~univs~role~name:id?loccmoduleLocmap:sigtypetvaldefault:Loc.toption->tvalmake:?default:Loc.t->MutInd.t->Loc.toptionlist->tvallookup:locmap:t->Names.inductive->Loc.toptionend=structtypet={default:Loc.toption;ind_to_loc:Loc.tNames.Indmap.t;}letlookup~locmap:{ind_to_loc;default}x=Names.Indmap.find_optxind_to_loc|>funloc->Option.appendlocdefaultletdefaultdefault={default;ind_to_loc=Names.Indmap.empty}letmake?defaultmindlocs=letdefault,ind_to_loc=CList.fold_left_i(funi(default,m)loc->letm=matchlocwith|None->m|Someloc->Indmap.add(mind,i)locminletdefault=ifOption.has_somedefaultthendefaultelselocindefault,m)0(default,Names.Indmap.empty)locsin{default;ind_to_loc}end(* Assumes that dependencies are already defined *)letrecdefine_individual_scheme_base?lockindsufff~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_typename("_"^suff)inletrole=Evd.Schema(ind,kind)inletconst,neff=define?locinternalroleidc(Declareops.inductive_is_polymorphicmib)ctxinleteff=Evd.concat_side_effectsneffeffinconst,effanddefine_individual_scheme?lockind~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_base?lockindsf~internalnamesindeff(* Assumes that dependencies are already defined *)anddefine_mutual_scheme_base?(locmap=Locmap.defaultNone)kindsufff~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_typename("_"^suff))inletfoldieffsidcl=letrole=Evd.Schema((mind,i),kind)inletloc=Locmap.lookup~locmap(mind,i)inletcst,neff=define?locinternalroleidcl(Declareops.inductive_is_polymorphicmib)ctxin(Evd.concat_side_effectsneffeffs,cst)inlet(eff,consts)=Array.fold_left2_map_ifoldeffidsclinconsts,effanddefine_mutual_scheme?locmapkind~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_base?locmapkindsf~internalnamesmindeffanddeclare_scheme_dependenceeffsd=matchsdwith|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->trymatchHashtbl.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)withCoqlib.NotFoundRef_ase->lete,info=Exninfo.captureeinProofview.tclZERO~infoeletdefine_individual_scheme?lockindnamesind=let_,eff=define_individual_scheme?lockind~internal:falsenamesindinredeclare_schemeseffletdefine_mutual_scheme?locmapkindnamesmind=let_,eff=define_mutual_scheme?locmapkind~internal:falsenamesmindinredeclare_schemeseff