123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157(************************************************************************)(* * 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) *)(************************************************************************)openPpopenUtilopenRedexpropenConstrintern(* Commands of the interface: Constant definitions *)letred_constant_bodyred_optenvsigmabody=matchred_optwith|None->sigma,body|Somered->letred,_=reduction_of_red_exprenvredinredenvsigmabodyletwarn_implicits_in_term=CWarnings.create~name:"implicits-in-term"~category:"implicits"(fun()->strbrk"Implicit arguments declaration relies on type."++spc()++strbrk"Discarding incompatible declaration in term.")letcheck_imps~impsty~impsbody=letrecauximpstyimpsbody=matchimpsty,impsbodywith|a1::impsty,a2::impsbody->let()=matcha1.CAst.v,a2.CAst.vwith|None,None|Some_,None->()|Some(_,b1),Some(_,b2)->ifnot((b1:bool)=b2)thenwarn_implicits_in_term?loc:a2.CAst.loc()|None,Some_->warn_implicits_in_term?loc:a2.CAst.loc()inauximpstyimpsbody|_::_,[]|[],_::_->(* Information only on one side *)()|[],[]->()inauximpstyimpsbodyletprotect_pattern_in_binderblcctypopt=(* We turn "Definition d binders := body : typ" into *)(* "Definition d := fun binders => body:type" *)(* This is a hack while waiting for LocalPattern in regular environments *)ifList.exists(functionConstrexpr.CLocalPattern_->true|_->false)blthenlett=matchctypoptwith|None->CAst.make?loc:c.CAst.loc(Constrexpr.CHole(None,Namegen.IntroAnonymous,None))|Somet->tinletloc=Loc.merge_optc.CAst.loct.CAst.locinletc=CAst.make?loc@@Constrexpr.CCast(c,Constr.DEFAULTcast,t)inletloc=matchList.hdblwith|Constrexpr.CLocalAssum(a::_,_,_)|Constrexpr.CLocalDef(a,_,_)->a.CAst.loc|Constrexpr.CLocalPattern{CAst.loc}->loc|Constrexpr.CLocalAssum([],_,_)->assertfalseinletapply_under_bindersfenvevdc=letrecauxenvevdc=letopenConstrinletopenEConstrinletopenContext.Rel.Declarationinmatchkindevdcwith|Lambda(x,t,c)->letevd,c=aux(push_rel(LocalAssum(x,t))env)evdcinevd,mkLambda(x,t,c)|LetIn(x,b,t,c)->letevd,c=aux(push_rel(LocalDef(x,b,t))env)evdcinevd,mkLetIn(x,t,b,c)|Case(ci,u,pms,p,iv,a,bl)->let(ci,p,iv,a,bl)=EConstr.expand_caseenvevd(ci,u,pms,p,iv,a,bl)inletevd,bl=Array.fold_left_map(auxenv)evdblinevd,mkCase(EConstr.contract_caseenvevd(ci,p,iv,a,bl))|Cast(c,_,_)->fenvevdc(* we remove the cast we had set *)(* This last case may happen when reaching the proof of an
impossible case, as when pattern-matching on a vector of length 1 *)|_->(evd,c)inauxenvevdcin([],Constrexpr_ops.mkLambdaCN?loc:(Loc.merge_optlocc.CAst.loc)blc,None,apply_under_binders)else(bl,c,ctypopt,funfenvevdc->fenvevdc)letinterp_definition~program_modeenvevdimpl_envblred_optioncctypopt=letflags=Pretyping.{all_no_fail_flagswithprogram_mode}inlet(bl,c,ctypopt,apply_under_binders)=protect_pattern_in_binderblcctypoptin(* Build the parameters *)letevd,(impls,((env_bl,ctx),imps1))=interp_context_evars~program_mode~impl_envenvevdblin(* Build the type *)letevd,tyopt=Option.fold_left_map(interp_type_evars_impls~flags~implsenv_bl)evdctypoptin(* Build the body, and merge implicits from parameters and from type/body *)letevd,c,imps,tyopt=matchtyoptwith|None->letevd,(c,impsbody)=interp_constr_evars_impls~program_mode~implsenv_blevdcinevd,c,imps1@impsbody,None|Some(ty,impsty)->letevd,(c,impsbody)=interp_casted_constr_evars_impls~program_mode~implsenv_blevdctyincheck_imps~impsty~impsbody;evd,c,imps1@impsty,Sometyin(* Do the reduction *)letevd,c=apply_under_binders(red_constant_bodyred_option)env_blevdcin(* Declare the definition *)letc=EConstr.it_mkLambda_or_LetIncctxinlettyopt=Option.map(funty->EConstr.it_mkProd_or_LetIntyctx)tyoptinevd,(c,tyopt),impsletdefinition_usingenvevd~body~types~using=letterms=Option.List.constypes[body]inOption.map(funusing->Proof_using.definition_usingenvevd~using~terms)usingletdo_definition?hook~name?scope~poly?typing_flags~kind?usingudeclblred_optioncctypopt=letprogram_mode=falseinletenv=Global.env()inletenv=Environ.update_typing_flags?typing_flagsenvin(* Explicitly bound universes and constraints *)letevd,udecl=interp_univ_decl_optenvudeclinletevd,(body,types),impargs=interp_definition~program_modeenvevdempty_internalization_envblred_optioncctypoptinletusing=definition_usingenvevd~body~types~usinginletkind=Decls.IsDefinitionkindinletcinfo=Declare.CInfo.make~name~impargs~typ:types?using()inletinfo=Declare.Info.make?scope~kind?hook~udecl~poly?typing_flags()inlet_:Names.GlobRef.t=Declare.declare_definition~info~cinfo~opaque:false~bodyevdin()letdo_definition_program?hook~pm~name~scope~poly?typing_flags~kind?usingudeclblred_optioncctypopt=let()=ifnotpolythenudecl|>Option.iter(funudecl->ifnotudecl.UState.univdecl_extensible_instance||notudecl.UState.univdecl_extensible_constraintsthenCErrors.user_errPp.(str"Non extensible universe declaration not supported \
with monomorphic Program Definition."))inletenv=Global.env()inletenv=Environ.update_typing_flags?typing_flagsenvin(* Explicitly bound universes and constraints *)letevd,udecl=interp_univ_decl_optenvudeclinletevd,(body,types),impargs=interp_definition~program_mode:trueenvevdempty_internalization_envblred_optioncctypoptinletusing=definition_usingenvevd~body~types~usinginletterm,typ,uctx,obls=Declare.Obls.prepare_obligation~name~body~typesevdinletpm,_=letcinfo=Declare.CInfo.make~name~typ~impargs?using()inletinfo=Declare.Info.make~udecl~scope~poly~kind?hook?typing_flags()inDeclare.Obls.add_definition~pm~cinfo~info~term~uctxoblsinpm