(************************************************************************) (* * 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) *) (************************************************************************)
open Util open Pp open CErrors open Names open Environ open EConstr open Evarutil open Termops open Vars open Ltac_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
*)
type t = {
static_env : env; (** For locating indices *)
renamed_env : env; (** For name management *)
extra : ext_named_context Lazy.t; (** Delay the computation of the evar extended environment *)
lvar : ltac_var_map;
}
let make ~hypnaming env sigma lvar = let get_extra env sigma = let avoid = Environ.ids_of_named_context_val (Environ.named_context_val env) in
Context.Rel.fold_outside (fun d acc -> push_rel_decl_to_named_context ~hypnaming sigma d acc)
(rel_context env) ~init:(empty_csubst, avoid, named_context_val env) in
{
static_env = env;
renamed_env = env;
extra = lazy (get_extra env sigma);
lvar = lvar;
}
let env env = env.static_env let renamed_env env = env.renamed_env let lfun env = env.lvar.ltac_genargs
let vars_of_env env =
Id.Set.union (Id.Map.domain env.lvar.ltac_genargs) (vars_of_env env.static_env)
let ltac_interp_id { ltac_idents ; ltac_genargs } id = try Id.Map.find id ltac_idents with Not_found -> if Id.Map.mem id ltac_genargs then
user_err (str "Ltac variable" ++ spc () ++ Id.print id ++
spc () ++ str "is not bound to an identifier." ++
spc () ++str "It cannot be used in a binder.") else id
let ltac_interp_name lvar = Nameops.Name.map (ltac_interp_id lvar)
let push_rel ~hypnaming sigma d env = letopen Context.Rel.Declaration in let d' = map_name (ltac_interp_name env.lvar) d in let env = {
static_env = push_rel d env.static_env;
renamed_env = push_rel d' env.renamed_env;
extra = lazy (push_rel_decl_to_named_context ~hypnaming:hypnaming sigma d' (Lazy.force env.extra));
lvar = env.lvar;
} in
d', env
let push_rel_context ~hypnaming ?(force_names=false) sigma ctx env = letopen Context.Rel.Declaration in let ctx' = List.Smart.map (map_name (ltac_interp_name env.lvar)) ctx in let ctx' = if force_names then Namegen.name_context env.renamed_env sigma ctx'else ctx' in let env = {
static_env = push_rel_context ctx env.static_env;
renamed_env = push_rel_context ctx' env.renamed_env;
extra = lazy (List.fold_right (fun d acc -> push_rel_decl_to_named_context ~hypnaming:hypnaming sigma d acc) ctx' (Lazy.force env.extra));
lvar = env.lvar;
} in
ctx', env
let push_rec_types ~hypnaming sigma (lna,typarray) env = letopen Context.Rel.Declaration in let ctxt = Array.map2_i (fun i na t -> Context.Rel.Declaration.LocalAssum (na, lift i t)) lna typarray in let env,ctx = Array.fold_left_map (fun e assum -> let (d,e) = push_rel sigma assum e ~hypnaming in (e,d)) env ctxt in
Array.map get_annot ctx, env
let new_evar env sigma ?src ?(naming = Namegen.IntroAnonymous) ?relevance typ = let (subst, _, sign) as ext = Lazy.force env.extra in let instance = Evarutil.default_ext_instance ext in let typ' = csubst_subst sigma subst typ in let name = Evarutil.next_evar_name sigma naming in let relevance = match relevance with
| Some r -> r
| None -> Retyping.relevance_of_type env.static_env sigma typ in let typeclass_candidate = Typeclasses.is_maybe_class_type sigma typ' in let (sigma, evk) = new_pure_evar ~typeclass_candidate sign sigma typ' ?src ~relevance ?name in
(sigma, mkEvar (evk, instance))
let new_type_evar env sigma ~src = let sigma, s = Evd.new_sort_variable Evd.univ_flexible_alg sigma in
new_evar env sigma ~src (EConstr.mkSort s) ~relevance:ERelevance.relevant
let hide_variable env id = let lvar = env.lvar in if Id.Map.mem id lvar.ltac_genargs then let 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. *)
{ lvar with
ltac_uconstrs = Id.Map.remove id lvar.ltac_uconstrs;
ltac_constrs = Id.Map.remove id lvar.ltac_constrs;
ltac_genargs = Id.Map.remove id lvar.ltac_genargs } in
{ env with lvar } else
env
let invert_ltac_bound_name env id0 id = try mkRel (pi1 (lookup_rel_id id (rel_context env.static_env))) with Not_found ->
user_err (str "Ltac variable " ++ Id.print id0 ++
str " depends on pattern variable name " ++ Id.print id ++
str " which is not bound in current context.")
let interp_ltac_variable ?loc typing_fun env sigma id : Evd.evar_map * unsafe_judgment = (* Check if [id] is an ltac variable *) match Id.Map.find_opt id env.lvar.ltac_constrs with
| Some (ids, c) -> let subst = List.map (invert_ltac_bound_name env id) ids in let c = substl subst c in
sigma, { uj_val = c; uj_type = Retyping.reinterpret_get_type_of ~src:id env.renamed_env sigma c }
| None -> match Id.Map.find_opt id env.lvar.ltac_uconstrs with
| Some {closure;term} -> let lvar = {
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 {env with lvar; static_env = env.renamed_env} term
| None -> (* Check if [id] is a ltac variable not bound to a term *) (* and build a nice error message *) if Id.Map.mem id env.lvar.ltac_idents thenbegin let bnd = Id.Map.find id env.lvar.ltac_idents in
user_err ?loc
(str "Variable " ++ Id.print id ++ str " should be bound to a term but is \
bound to the identifier " ++ quote (Id.print bnd) ++ str ".") end; if Id.Map.mem id env.lvar.ltac_genargs thenbegin let Geninterp.Val.Dyn (typ, _) = Id.Map.find id env.lvar.ltac_genargs in
user_err ?loc
(str "Variable " ++ Id.print id ++ str " should be bound to a term but is \
bound to a " ++ Geninterp.Val.pr typ ++ str ".") end; raise Not_found
let interp_ltac_id env id = ltac_interp_id env.lvar id
let lookup_renamed globenv id = let env = renamed_env globenv in (* optimization: if id is in the original named context it will
be the same in the extended context *) match EConstr.lookup_named id env with
| d -> EConstr.mkVar id
| exception Not_found -> let (_, _, sign) as ext = Lazy.force globenv.extra in
Evarutil.ext_rev_subst ext id
type'a obj_interp_fun =
?loc:Loc.t -> poly:bool -> t -> Evd.evar_map -> Evardefine.type_constraint -> 'a -> unsafe_judgment * Evd.evar_map
module ConstrInterpObj = struct type ('r, 'g, 't) obj = 'g obj_interp_fun let name = "constr_interp" let default _ = None end
let register_constr_interp0 = ConstrInterp.register0
let interp_glob_genarg ?loc ~poly env sigma ty arg = letopen Genarg in let GenArg (Glbwit tag, arg) = arg in let interp = ConstrInterp.obj tag in
interp ?loc ~poly env sigma ty arg
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.