123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212(************************************************************************)(* * 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) *)(************************************************************************)openNamesopenEntries(** Declaration of inductive blocks *)letdeclare_inductive_argument_scopesknmie=List.iteri(funi{mind_entry_consnames=lc}->Notation.declare_ref_arguments_scope(GlobRef.IndRef(kn,i));forj=1toList.lengthlcdoNotation.declare_ref_arguments_scope(GlobRef.ConstructRef((kn,i),j));done)mie.mind_entry_indstypeinductive_obj={ind_names:(Id.t*Id.tlist)list(* For each block, name of the type + name of constructors *)}letinductive_namesspknobj=let(dp,_)=Libnames.repr_pathspinletkn=Global.mind_of_delta_knkninletnames,_=List.fold_left(fun(names,n)(typename,consnames)->letind_p=(kn,n)inletnames,_=List.fold_left(fun(names,p)l->letsp=Libnames.make_pathdplin((sp,GlobRef.ConstructRef(ind_p,p))::names,p+1))(names,1)consnamesinletsp=Libnames.make_pathdptypenamein((sp,GlobRef.IndRefind_p)::names,n+1))([],0)obj.ind_namesinnamesletload_inductivei((sp,kn),names)=letnames=inductive_namesspknnamesinList.iter(fun(sp,ref)->Nametab.push(Nametab.Untili)spref)namesletopen_inductivei((sp,kn),names)=letnames=inductive_namesspknnamesinList.iter(fun(sp,ref)->Nametab.push(Nametab.Exactlyi)spref)namesletcache_inductive((sp,kn),names)=letnames=inductive_namesspknnamesinList.iter(fun(sp,ref)->Nametab.push(Nametab.Until1)spref)namesletdischarge_inductivenames=SomenamesletobjInductive:(Id.t*inductive_obj)Libobject.Dyn.tag=letopenLibobjectindeclare_named_object_full{(default_object"INDUCTIVE")withcache_function=cache_inductive;load_function=load_inductive;open_function=simple_openopen_inductive;classify_function=(funa->Substitute);subst_function=ident_subst_function;discharge_function=discharge_inductive;}letinInductivev=Libobject.Dyn.Easy.injvobjInductiveletcache_prim(p,c)=Structures.PrimitiveProjections.registerpcletload_prim_p=cache_primpletsubst_prim(subst,(p,c))=Mod_subst.subst_proj_reprsubstp,Mod_subst.subst_constantsubstcletdischarge_prim(p,c)=Some(Lib.discharge_proj_reprp,c)letinPrim:(Projection.Repr.t*Constant.t)->Libobject.obj=letopenLibobjectindeclare_object{(default_object"PRIMPROJS")withcache_function=cache_prim;load_function=load_prim;subst_function=subst_prim;classify_function=(funx->Substitute);discharge_function=discharge_prim}letdeclare_primitive_projectionpc=Lib.add_leaf(inPrim(p,c))letfeedback_axiom()=Feedback.(feedbackAddedAxiom)letis_unsafe_typing_flags()=letopenDeclarationsinletflags=Environ.typing_flags(Global.env())innot(flags.check_universes&&flags.check_guarded&&flags.check_positive)(* for initial declaration *)letdeclare_mind?typing_flagsmie=letid=matchmie.mind_entry_indswith|ind::_->ind.mind_entry_typename|[]->CErrors.anomaly(Pp.str"cannot declare an empty list of inductives.")inletmap_namesmip=(mip.mind_entry_typename,mip.mind_entry_consnames)inletnames=List.mapmap_namesmie.mind_entry_indsinList.iter(fun(typ,cons)->Declare.check_existstyp;List.iterDeclare.check_existscons)names;letmind=Global.add_mind?typing_flagsidmieinlet()=Lib.add_leaf(inInductive(id,{ind_names=names}))inifis_unsafe_typing_flags()thenfeedback_axiom();letisprim=Inductive.is_primitive_record(Inductive.lookup_mind_specif(Global.env())(mind,0))inImpargs.declare_mib_implicitsmind;declare_inductive_argument_scopesmindmie;mind,isprimletis_recursivemie=letopenConstrinletrecis_recursive_constructorliftntyp=matchConstr.kindtypwith|Prod(_,arg,rest)->not(Vars.noccur_betweenliftnarg)||is_recursive_constructor(lift+1)nrest|LetIn(na,b,t,rest)->is_recursive_constructor(lift+1)nrest|_->falseinletnind=List.lengthmie.mind_entry_indsinletnparams=List.lengthmie.mind_entry_paramsinList.exists(funind->List.exists(funt->is_recursive_constructor(nparams+1)nindt)ind.mind_entry_lc)mie.mind_entry_indsletwarn_non_primitive_record=CWarnings.create~name:"non-primitive-record"~category:CWarnings.CoreCategories.records(funindsp->Pp.(hov0(str"The record "++Nametab.pr_global_envId.Set.empty(GlobRef.IndRefindsp)++strbrk" could not be defined as a primitive record.")))letminductive_message=function|[]->CErrors.user_errPp.(str"No inductive definition.")|[x]->Pp.(Id.printx++str" is defined")|l->Pp.(hov0(prlist_with_seppr_commaId.printl++spc()++str"are defined"))typeone_inductive_impls=Impargs.manual_implicits(* for inds *)*Impargs.manual_implicitslist(* for constrs *)let{Goptions.get=default_prop_dep_elim}=Goptions.declare_bool_option_and_ref~key:["Dependent";"Proposition";"Eliminators"]~value:false()typedefault_dep_elim=DefaultElim|PropButDepElimletdeclare_mutual_inductive_with_eliminations?(primitive_expected=false)?typing_flags?(indlocs=[])?default_dep_elimmieubindersimpls=(* spiwack: raises an error if the structure is supposed to be non-recursive,
but isn't *)beginmatchmie.mind_entry_finitewith|Declarations.BiFinite->ifis_recursivemiethenifOption.has_somemie.mind_entry_recordthenCErrors.user_errPp.(strbrk"Records declared with the keywords Record or Structure cannot be recursive. You can, however, define recursive records using the Inductive or CoInductive command.")elseCErrors.user_errPp.(strbrk"Types declared with the keyword Variant cannot be recursive. Recursive types are defined with the Inductive and CoInductive command.");ifnot(Int.equal(List.lengthmie.mind_entry_inds)1)thenifOption.has_somemie.mind_entry_recordthenCErrors.user_errPp.(strbrk"Keywords Record and Structure are to define a single type at once.")elseCErrors.user_errPp.(strbrk"Keyword Variant is to define a single type at once.")|_->()end;letnames=List.map(fune->e.mind_entry_typename)mie.mind_entry_indsinletmind,prim=declare_mind?typing_flagsmieinifprimitive_expected&¬primthenwarn_non_primitive_record(mind,0);DeclareUniv.declare_univ_binders(GlobRef.IndRef(mind,0))ubinders;List.iteri(funi(indimpls,constrimpls)->letind=(mind,i)inletgr=GlobRef.IndRefindinImpargs.maybe_declare_manual_implicitsfalsegrindimpls;List.iteri(funjimpls->Impargs.maybe_declare_manual_implicitsfalse(GlobRef.ConstructRef(ind,succj))impls)constrimpls)impls;let()=matchdefault_dep_elimwith|None->()|Somedefaults->List.iteri(funidefault->letind=(mind,i)inletprop_but_default_dep_elim=matchdefaultwith|PropButDepElim->true|DefaultElim->default_prop_dep_elim()&&let_,mip=Global.lookup_inductiveindinmatchmip.mind_aritywith|RegularArityar->Sorts.is_propar.mind_sort|TemplateArity_->falseinifprop_but_default_dep_elimthenIndrec.declare_prop_but_default_dependent_elimind)defaultsinFlags.if_verboseFeedback.msg_info(minductive_messagenames);letlocmap=Ind_tables.Locmap.makemindindlocsinifmie.mind_entry_private==NonethenIndschemes.declare_default_schemesmind~locmap;mindmoduleInternal=structtypenonrecinductive_obj=inductive_objletobjInductive=objInductiveend