123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenPpopenCErrorsopenNamesopenEnvironopenEConstropenEvarutilopenTermopsopenVarsopenLtac_pretype(** This files provides a level of abstraction for the kind of
environment used for type inference (so-called pretyping); in
particular:
- it supports that term variables can be interpreted as Ltac
variables pointing to the effective expected name
- it incrementally and lazily computes the renaming of rel
variables used to build purely-named evar contexts
*)typet={static_env:env;(** For locating indices *)renamed_env:env;(** For name management *)extra:ext_named_contextLazy.t;(** Delay the computation of the evar extended environment *)lvar:ltac_var_map;}letmake~hypnamingenvsigmalvar=letget_extraenvsigma=letavoid=Environ.ids_of_named_context_val(Environ.named_context_valenv)inContext.Rel.fold_outside(fundacc->push_rel_decl_to_named_context~hypnamingsigmadacc)(rel_contextenv)~init:(empty_csubst,avoid,named_context_valenv)in{static_env=env;renamed_env=env;extra=lazy(get_extraenvsigma);lvar=lvar;}letenvenv=env.static_envletrenamed_envenv=env.renamed_envletlfunenv=env.lvar.ltac_genargsletvars_of_envenv=Id.Set.union(Id.Map.domainenv.lvar.ltac_genargs)(vars_of_envenv.static_env)letltac_interp_id{ltac_idents;ltac_genargs}id=tryId.Map.findidltac_identswithNot_found->ifId.Map.memidltac_genargsthenuser_err(str"Ltac variable"++spc()++Id.printid++spc()++str"is not bound to an identifier."++spc()++str"It cannot be used in a binder.")elseidletltac_interp_namelvar=Nameops.Name.map(ltac_interp_idlvar)letpush_rel~hypnamingsigmadenv=letopenContext.Rel.Declarationinletd'=map_name(ltac_interp_nameenv.lvar)dinletenv={static_env=push_reldenv.static_env;renamed_env=push_reld'env.renamed_env;extra=lazy(push_rel_decl_to_named_context~hypnaming:hypnamingsigmad'(Lazy.forceenv.extra));lvar=env.lvar;}ind',envletpush_rel_context~hypnaming?(force_names=false)sigmactxenv=letopenContext.Rel.Declarationinletctx'=List.Smart.map(map_name(ltac_interp_nameenv.lvar))ctxinletctx'=ifforce_namesthenNamegen.name_contextenv.renamed_envsigmactx'elsectx'inletenv={static_env=push_rel_contextctxenv.static_env;renamed_env=push_rel_contextctx'env.renamed_env;extra=lazy(List.fold_right(fundacc->push_rel_decl_to_named_context~hypnaming:hypnamingsigmadacc)ctx'(Lazy.forceenv.extra));lvar=env.lvar;}inctx',envletpush_rec_types~hypnamingsigma(lna,typarray)env=letopenContext.Rel.Declarationinletctxt=Array.map2_i(funinat->Context.Rel.Declaration.LocalAssum(na,liftit))lnatyparrayinletenv,ctx=Array.fold_left_map(funeassum->let(d,e)=push_relsigmaassume~hypnamingin(e,d))envctxtinArray.mapget_annotctx,envletnew_evarenvsigma?src?(naming=Namegen.IntroAnonymous)typ=let(subst,_,sign)asext=Lazy.forceenv.extrainletinstance=Evarutil.default_ext_instanceextinlettyp'=csubst_substsigmasubsttypinletname=Evarutil.next_evar_namesigmanaminginlet(sigma,evk)=new_pure_evarsignsigmatyp'?src?namein(sigma,mkEvar(evk,instance))letnew_type_evarenvsigma~src=letsigma,s=Evd.new_sort_variableEvd.univ_flexible_algsigmainnew_evarenvsigma~src(EConstr.mkSorts)lethide_variableenvexpansionid=letlvar=env.lvarinifId.Map.memidlvar.ltac_genargsthenletlvar=matchexpansionwith|Nameid'->(* We are typically in a situation [match id return P with ... end]
which we interpret as [match id' as id' return P with ... end],
with [P] interpreted in an environment where [id] is bound to [id'].
The variable is already bound to [id'], so nothing to do *)lvar|_->(* We are typically in a situation [match id return P with ... end]
with [id] bound to a non-variable term [c]. We interpret as
[match c as id return P with ... end], and hides [id] while
interpreting [P], since it has become a binder and cannot be anymore be
substituted by a variable coming from the Ltac substitution. *){lvarwithltac_uconstrs=Id.Map.removeidlvar.ltac_uconstrs;ltac_constrs=Id.Map.removeidlvar.ltac_constrs;ltac_genargs=Id.Map.removeidlvar.ltac_genargs}in{envwithlvar}elseenvletinvert_ltac_bound_nameenvid0id=trymkRel(pi1(lookup_rel_idid(rel_contextenv.static_env)))withNot_found->user_err(str"Ltac variable "++Id.printid0++str" depends on pattern variable name "++Id.printid++str" which is not bound in current context.")letinterp_ltac_variable?loctyping_funenvsigmaid:Evd.evar_map*unsafe_judgment=(* Check if [id] is an ltac variable *)trylet(ids,c)=Id.Map.findidenv.lvar.ltac_constrsinletsubst=List.map(invert_ltac_bound_nameenvid)idsinletc=substlsubstcinsigma,{uj_val=c;uj_type=Retyping.reinterpret_get_type_of~src:idenv.renamed_envsigmac}withNot_found->trylet{closure;term}=Id.Map.findidenv.lvar.ltac_uconstrsinletlvar={ltac_constrs=closure.typed;ltac_uconstrs=closure.untyped;ltac_idents=closure.idents;ltac_genargs=closure.genargs;}in(* spiwack: I'm catching [Not_found] potentially too eagerly
here, as the call to the main pretyping function is caught
inside the try but I want to avoid refactoring this function
too much for now. *)typing_fun{envwithlvar;static_env=env.renamed_env}termwithNot_found->(* Check if [id] is a ltac variable not bound to a term *)(* and build a nice error message *)ifId.Map.memidenv.lvar.ltac_genargsthenbeginletGeninterp.Val.Dyn(typ,_)=Id.Map.findidenv.lvar.ltac_genargsinuser_err?loc(str"Variable "++Id.printid++str" should be bound to a term but is \
bound to a "++Geninterp.Val.prtyp++str".")end;ifId.Map.memidenv.lvar.ltac_identsthenbeginletbnd=Id.Map.findidenv.lvar.ltac_identsinuser_err?loc(str"Variable "++Id.printid++str" should be bound to a term but is \
bound to the identifier "++quote(Id.printbnd)++str".")end;raiseNot_foundletinterp_ltac_idenvid=ltac_interp_idenv.lvaridtype'aobj_interp_fun=?loc:Loc.t->poly:bool->t->Evd.evar_map->Evardefine.type_constraint->'a->unsafe_judgment*Evd.evar_mapmoduleConstrInterpObj=structtype('r,'g,'t)obj='gobj_interp_funletname="constr_interp"letdefault_=NoneendmoduleConstrInterp=Genarg.Register(ConstrInterpObj)letregister_constr_interp0=ConstrInterp.register0letinterp_glob_genarg?loc~polyenvsigmatyarg=letopenGenarginletGenArg(Glbwittag,arg)=arginletinterp=ConstrInterp.objtagininterp?loc~polyenvsigmatyarg