123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenNamesopenEConstropenVarsopenContext.Named.Declaration(** Characterization of the head of a term *)(* We only compute an approximation to ensure the computation is not
arbitrary long (e.g. the head constant of [h] defined to be
[g (fun x -> phi(x))] where [g] is [fun f => g O] does not launch
the evaluation of [phi(0)] and the head of [h] is declared unknown). *)typerigid_head_kind=|RigidParameterofConstant.t(* a Const without body. Module substitution may instantiate it with something else. *)|RigidOther(* a Var without body, inductive, product, sort, projection *)typehead_approximation=|RigidHeadofrigid_head_kind|ConstructorHead|FlexibleHeadofint*int*int*bool(* [true] if a surrounding case *)|NotImmediatelyComputableHeadletreccompute_head_constenvsigmacst=letbody=Environ.constant_opt_value_inenv(cst,UVars.Instance.empty)inmatchbodywith|None->RigidHead(RigidParametercst)|Somec->kind_of_headenvsigma(EConstr.of_constrc)andcompute_head_varenvsigmaid=matchlookup_namedidenvwith|LocalDef(_,c,_)->kind_of_headenvsigmac|_->RigidHeadRigidOtherandkind_of_headenvsigmat=letrecauxkltb=matchEConstr.kindsigma(Reductionops.clos_whd_flagsRedFlags.betaiotazetaenvsigmat)with|Relnwhenn>k->NotImmediatelyComputableHead|Reln->FlexibleHead(k,k+1-n,List.lengthl,b)|Varid->(tryon_subtermklb(compute_head_varenvsigmaid)withNot_found->(* a goal variable *)matchlookup_namedidenvwith|LocalDef(_,c,_)->auxklcb|LocalAssum_->NotImmediatelyComputableHead)|Const(cst,_)->(tryon_subtermklb(compute_head_constenvsigmacst)withNot_found->CErrors.anomalyPp.(str"constant not found in kind_of_head: "++Names.Constant.printcst++str"."))|Construct_|CoFix_->ifbthenNotImmediatelyComputableHeadelseConstructorHead|Sort_|Ind_|Prod_->RigidHeadRigidOther|Cast(c,_,_)->auxklcb|Lambda(_,_,c)->beginmatchlwith|[]->let()=assert(notb)inaux(k+1)[]cb|h::l->auxkl(subst1hc)bend|LetIn_->assertfalse|Meta_|Evar_->NotImmediatelyComputableHead|App(c,al)->auxk(Array.to_listal@l)cb|Proj(p,_,c)->RigidHeadRigidOther|Case(_,_,_,_,_,c,_)->auxk[]ctrue|Int_|Float_|String_|Array_->ConstructorHead|Fix((i,j),_)->letn=i.(j)intryauxk[](List.nthln)truewithFailure_->FlexibleHead(k+n+1,k+n+1,0,true)andon_subtermklwith_case=function|FlexibleHead(n,i,q,with_subcase)->letm=List.lengthlinletk',rest,a=ifn>mthen(* eta-expansion *)leta=ifi<=mthen(* we pick the head in the existing arguments *)lift(n-m)(List.nthl(i-1))else(* we pick the head in the added arguments *)mkRel(n-i+1)ink+n-m,[],aelse(* enough arguments to [cst] *)k,List.skipnnl,List.nthl(i-1)inletl'=List.makeq(mkMeta0)@restinauxk'l'a(with_subcase||with_case)|ConstructorHeadwhenwith_case->NotImmediatelyComputableHead|x->xinaux0[]tfalseletis_rigidenvsigmat=matchkind_of_headenvsigmatwith|RigidHead_|ConstructorHead->true|_->false