(************************************************************************) (* * 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) *) (************************************************************************)
(* Created by Jean-Christophe Filliâtre out of V6.3 file constants.ml aspartoftherebuildingofCoqaroundapurelyfunctional
abstract type-checker, Nov 1999 *)
(* This module implements kernel-level discharching of local
declarations over global constants and inductive types *)
open Util open Names open Term open Constr open UVars open Context
module NamedDecl = Context.Named.Declaration
(** {6 Data needed to abstract over the section variables and section universes } *)
(** The generalization to be done on a specific judgment: [a:T,b:U,c:V(a)⊢w(a,c):W(a,c) ~~> ⊢λxz.w(a,c)[a,c:=x,z]:(Πx:T.z:T(a).W(a,c))[a,c:=x,z]] so,anabstr_infoisboththecontextx:T,z:V(x)togeneralize (skippingywhichdoesnotoccur),andthesubstitution[a↦x,c↦z] whereinpractice,xandzarecanonical(henceimplicit)de
Bruijn indices, that is, only the instantiation [a,c] is kept *)
type abstr_info = {
abstr_ctx : Constr.named_context; (** Context over which to generalize (e.g. x:T,z:V(x)) *)
abstr_auctx : UVars.AbstractContext.t; (** Universe context over which to generalize *)
abstr_ausubst : Instance.t; (** Universe substitution represented as an instance *)
}
(** The instantiation to apply to generalized declarations so that theybehaveasifnotgeneralized:thisisthea1..aninstanceto applytoadeclarationcinthefollowingtransformation: [a1:T1..an:Tn,C:U(a1..an)⊢v(a1..an,C):V(a1..an,C) ~~> C:Πx1..xn.U(x1..xn),a1:T1..an:Tn⊢v(a1..an,Ca1..an):V(a1..an,Ca1..an)] notethatthedatalooksclosetotheoneforsubstitutionabove (becausethesubstitutionarerepresentedbytheirdomain)but
here, local definitions of the context have been dropped *)
type abstr_inst_info = {
abstr_rev_inst : Id.t list; (** The variables to reapply (excluding "let"s of the context), in reverse order *)
abstr_uinst : UVars.Instance.t; (** Abstracted universe variables to reapply *)
}
(** The collection of instantiations to apply to generalized declarationssothattheybehaveasifnotgeneralized. Thisaccountsforthepermutation(lambda-lifting)ofglobaland localdeclarations. Usingthenotationsabove,aexpand_infoisamap[c↦a1..an]
over all generalized global declarations of the section *)
type'a entry_map = 'a Cmap_env.t * 'a Mindmap_env.t type expand_info = abstr_inst_info entry_map
(** The collection of instantiations to be done on generalized declarations+thegeneralizationtobedoneonaspecific judgment: [a1:T1,a2:T2,C:U(a1)⊢v(a1,a2,C):V(a1,a2,C) ~~> c:Πx.U(x)⊢λx1x2.(v(a1,a2,cx1)[a1,a2:=x1,x2]):Πx1x2.(V(a1,a2,ca1)[a1,a2:=x1,x2])] so,acooking_infoisthemap[c↦x1..xn],
the context x:T,y:U to generalize, and the substitution [x,y] *)
type my_global_reference =
| ConstRef of Constant.t
| IndRef of inductive
| ConstructRef of constructor
module RefHash = struct type t = my_global_reference let equal gr1 gr2 = match gr1, gr2 with
| ConstRef c1, ConstRef c2 -> Constant.SyntacticOrd.equal c1 c2
| IndRef i1, IndRef i2 -> Ind.SyntacticOrd.equal i1 i2
| ConstructRef c1, ConstructRef c2 -> Construct.SyntacticOrd.equal c1 c2
| _ -> false open Hashset.Combine let hash = function
| ConstRef c -> combinesmall 1 (Constant.SyntacticOrd.hash c)
| IndRef i -> combinesmall 2 (Ind.SyntacticOrd.hash i)
| ConstructRef c -> combinesmall 3 (Construct.SyntacticOrd.hash c) end
module RefTable = Hashtbl.Make(RefHash) type internal_abstr_inst_info = UVars.Instance.t * int list * int
type cooking_cache = {
cache : internal_abstr_inst_info RefTable.t;
info : cooking_info;
rel_ctx : rel_context Lazy.t;
}
let instantiate_my_gr gr u = match gr with
| ConstRef c -> mkConstU (c, u)
| IndRef i -> mkIndU (i, u)
| ConstructRef c -> mkConstructU (c, u)
let discharge_inst top_abst_subst sub_abst_rev_inst = let rec aux k relargs top_abst_subst sub_abst_rev_inst = match top_abst_subst, sub_abst_rev_inst with
| decl :: top_abst_subst, id' :: sub_abst_rev_inst' -> if Id.equal (NamedDecl.get_id decl) id' then
aux (k+1) (k :: relargs) top_abst_subst sub_abst_rev_inst' else
aux (k+1) relargs top_abst_subst sub_abst_rev_inst
| _, [] -> relargs
| [], _ -> assert falsein
aux 1 [] top_abst_subst sub_abst_rev_inst
let rec find_var k id = function
| [] -> raise Not_found
| decl :: subst -> if Id.equal id (NamedDecl.get_id decl) then k+1 else find_var (k+1) id subst
let share cache top_abst_subst r (cstl,knl) = try RefTable.find cache r with Not_found -> let {abstr_uinst;abstr_rev_inst} = match r with
| IndRef (kn,_i) -> Mindmap_env.find kn knl
| ConstructRef ((kn,_i),_j) -> Mindmap_env.find kn knl
| ConstRef cst -> Cmap_env.find cst cstl in let inst = (abstr_uinst, discharge_inst top_abst_subst abstr_rev_inst, List.length abstr_rev_inst) in
RefTable.add cache r inst;
inst
let make_inst k abstr_inst_rel =
Array.map_of_list (fun n -> mkRel (k+n)) abstr_inst_rel
let share_univs cache top_abst_subst k r u l = let (abstr_uinst,abstr_inst_rel,_) = share cache top_abst_subst r l in
mkApp (instantiate_my_gr r (Instance.append abstr_uinst u), make_inst k abstr_inst_rel)
let discharge_proj_repr r p = (* To merge with discharge_proj *) let nnewpars = List.count NamedDecl.is_local_assum r.abstr_info.abstr_ctx in letmap npars = npars + nnewpars in
Projection.Repr.map_npars map p
let discharge_proj (_,_,abstr_inst_length) p = letmap npars = npars + abstr_inst_length in
Projection.map_npars map p
let is_empty_modlist (cm, mm) =
Cmap_env.is_empty cm && Mindmap_env.is_empty mm
let expand_constr cache modlist top_abst_subst c = let share_univs = share_univs cache top_abst_subst in let rec substrec k c = match kind c with
| Case (ci, u, pms, p, iv, t, br) -> beginmatch share cache top_abst_subst (IndRef ci.ci_ind) modlist with
| (abstr_uinst, abstr_inst_rel, abstr_inst_length) -> let u = Instance.append abstr_uinst u in let pms = Array.append (make_inst k abstr_inst_rel) pms in let ci = { ci with ci_npar = ci.ci_npar + abstr_inst_length } in
Constr.map_with_binders succ substrec k (mkCase (ci,u,pms,p,iv,t,br))
| exception Not_found ->
Constr.map_with_binders succ substrec k c end
| Ind (ind,u) ->
(try
share_univs k (IndRef ind) u modlist with
| Not_found -> Constr.map_with_binders succ substrec k c)
| Construct (cstr,u) ->
(try
share_univs k (ConstructRef cstr) u modlist with
| Not_found -> Constr.map_with_binders succ substrec k c)
| Const (cst,u) ->
(try
share_univs k (ConstRef cst) u modlist with
| Not_found -> Constr.map_with_binders succ substrec k c)
| Proj (p, r, c') -> let ind = Names.Projection.inductive p in let p' = try let exp = share cache top_abst_subst (IndRef ind) modlist in
discharge_proj exp p with Not_found -> p in let c'' = substrec k c' in if p == p' && c' == c''then c else mkProj (p', r, c'')
| Var id ->
(try
mkRel (find_var k id top_abst_subst) with Not_found -> c)
| _ -> Constr.map_with_binders succ substrec k c
in if is_empty_modlist modlist && List.is_empty top_abst_subst then c else substrec 0 c
(** Cooking is made of 4 steps: 1.expansionofglobalconstantsbyapplyingthemtothesection subcontexttheydependon 2.substitutionofnameduniversevariablesbydeBruijnuniversevariables 3.substitutionofnamedtermvariablesbydeBruijntermvariables 3.generalizationoftermsoverthesectionsubcontexttheydependon
(note that the generalization over universe variable is implicit) *)
(** The main expanding/substitution functions, performing the three first steps *) let expand_subst0 cache expand_info abstr_ctx abstr_ausubst c = let c = expand_constr cache expand_info abstr_ctx c in let c = Vars.subst_univs_level_constr (make_instance_subst abstr_ausubst) c in
c
let expand_subst cache c =
expand_subst0 cache.cache cache.info.expand_info cache.info.abstr_info.abstr_ctx cache.info.abstr_info.abstr_ausubst c
(** Adding the final abstraction step, term case *) let abstract_as_type cache t = let ctx = Lazy.force cache.rel_ctx in
it_mkProd_wo_LetIn (expand_subst cache t) ctx
(** Adding the final abstraction step, type case *) let abstract_as_body cache c = let ctx = Lazy.force cache.rel_ctx in
it_mkLambda_or_LetIn (expand_subst cache c) ctx
(** Adding the final abstraction step, sort case (for universes) *) let abstract_as_sort cache s =
destSort (expand_subst cache (mkSort s))
(** Absorb a named context in the transformation which turns a judgment[G,Δ⊢ΠΩ.J]into[⊢ΠG.ΠΔ.((ΠΩ.J)[σ][τ])],thatis, producesthecontext[Δ(Ω[σ][τ])]andsubstitutions[σ']and[τ] thatturnsajudgment[G,Δ,Ω[σ][τ]⊢J]into[⊢ΠG.ΠΔ.((ΠΩ.J)[σ][τ])]
via [⊢ ΠG.ΠΔ.Π(Ω[σ][τ]).(J[σ'][τ])] *) let abstract_named_context expand_info abstr_ausubst hyps = let fold decl abstr_ctx = let cache = RefTable.create 13in let decl = match decl with
| NamedDecl.LocalDef (id, b, t) -> let id = Context.map_annot_relevance (UVars.subst_sort_level_relevance (make_instance_subst abstr_ausubst)) id in let b = expand_subst0 cache expand_info abstr_ctx abstr_ausubst b in let t = expand_subst0 cache expand_info abstr_ctx abstr_ausubst t in
NamedDecl.LocalDef (id, b, t)
| NamedDecl.LocalAssum (id, t) -> let id = Context.map_annot_relevance (UVars.subst_sort_level_relevance (make_instance_subst abstr_ausubst)) id in let t = expand_subst0 cache expand_info abstr_ctx abstr_ausubst t in
NamedDecl.LocalAssum (id, t) in
decl :: abstr_ctx in
Context.Named.fold_outside fold hyps ~init:[]
let create_cache info = let cache = RefTable.create 13in let abstr_info = info.abstr_info in let named_ctx = lazy (abstract_named_context info.expand_info abstr_info.abstr_ausubst abstr_info.abstr_ctx) in let rel_ctx = lazy (List.map NamedDecl.to_rel_decl (Lazy.force named_ctx)) in
{ cache; info; rel_ctx }
(** Turn a named context [Δ] (hyps) and a universe named context [G](uctx)intoarelcontextandabstractuniversecontext respectively;computingalsothesubstitution[σ]anduniverse substitution[τ]suchthatif[G,Δ⊢J]isvalidthen [⊢ΠG.ΠΔ.(J[σ][τ])]istoo,thatis,itproducesthesubstitutions whichturnsnamedbindersintodeBruijnbinders;computingalso theinstancetoapplytotakethegeneralizationintoaccount; collectingtheinformationneededtodosuchasatransformation
of judgment into a [cooking_info] *) let make_cooking_info ~recursive expand_info hyps uctx = let abstr_rev_inst = List.rev (Named.instance_list (fun id -> id) hyps) in let abstr_ausubst, abstr_auctx = abstract_universes uctx in let abstr_info = { abstr_ctx = hyps; abstr_auctx; abstr_ausubst } in let abstr_inst_info = {
abstr_rev_inst = abstr_rev_inst;
abstr_uinst = abstr_ausubst;
} in let info = { expand_info; abstr_info } in let info = match recursive with
| None -> info
| Some ind -> let (cmap, imap) = info.expand_info in
{ info with expand_info = (cmap, Mindmap_env.add ind abstr_inst_info imap) } in
info, abstr_inst_info
let names_info info = let fold accu id = Id.Set.add (NamedDecl.get_id id) accu in List.fold_left fold Id.Set.empty info.abstr_info.abstr_ctx
let rel_context_of_cooking_cache cache =
Lazy.force cache.rel_ctx
let universe_context_of_cooking_info info =
info.abstr_info.abstr_auctx
let instance_of_cooking_info info =
Named.instance mkVar info.abstr_info.abstr_ctx
let instance_of_cooking_cache { info; _ } =
instance_of_cooking_info info
let discharge_abstract_universe_context abstr auctx = (** Given a substitution [abstr.abstr_ausubst := u₀ ... uₙ₋₁] together with an abstract context[abstr.abstr_ctx:=0...n-1|=C{0,...,n-1}]ofthesamelength, andanotherabstractcontextrelativetotheformercontext [auctx:=0...m-1|=C'{u₀,...,uₙ₋₁,0,...,m-1}], constructtheliftedabstractuniversecontext [0...n-1n...n+m-1|= C{0,...n-1}∪ C'{0,...,n-1,n,...,n+m-1}] togetherwiththesubstitution [u₀↦Var(0),...,uₙ₋₁↦Var(n-1),Var(0)↦Var(n),...,Var(m-1)↦Var(n+m-1)].
*) let n = AbstractContext.size abstr.abstr_auctx in if (UVars.eq_sizes n (0,0)) then (** Optimization: still need to take the union for the constraints between globals *)
abstr, n, AbstractContext.union abstr.abstr_auctx auctx else let subst = abstr.abstr_ausubst in let suff = UVars.make_abstract_instance auctx in let ainst = Instance.append subst suff in let substf = make_instance_subst ainst in let auctx = UVars.subst_univs_level_abstract_universe_context (snd substf) auctx in let auctx' = AbstractContext.union abstr.abstr_auctx auctx in
{ abstr with abstr_ausubst = ainst }, n, auctx'
let lift_mono_univs info ctx =
assert (AbstractContext.is_empty info.abstr_info.abstr_auctx); (* No monorphic constants in a polymorphic section *)
info, ctx
let lift_poly_univs info auctx = (** The constant under consideration is quantified over a universecontext[auctx];ithastobequantifiedfurtherover [abstr.abstr_auctx]leadingtoanewabstractionrecipevalid underthequantification;thatisifwehadajudgment [G,Δ⊢ΠG'.J]tobeturned,thanksto[abstr]= [{ctx:=Δ;uctx:=G;subst:=σ;usubst:=τ}],into [⊢ΠG.ΠΔ.(ΠG'.J)[σ][τ])],webuildthenew [{ctx:=Δ;uctx:=G(G'[ττ']);subst:=σ;usubst:=ττ'}],forsome[τ'] builtby[discharge_abstract_universe_context],thatworkson [J],thatis,thatallowstoturn[GG'[ττ'],Δ⊢J]into
[⊢ ΠG.ΠΔ.(ΠG'.J)[σ][τ]] via [⊢ ΠG(G'[ττ']).ΠΔ.(J[σ][ττ'])] *) let abstr_info, n, auctx = discharge_abstract_universe_context info.abstr_info auctx in
{ info with abstr_info }, n, auctx
let lift_private_mono_univs info a = let () = assert (AbstractContext.is_empty info.abstr_info.abstr_auctx) in let () = assert (Instance.is_empty info.abstr_info.abstr_ausubst) in
a
let lift_private_poly_univs info (inst, cstrs) = let cstrs = Univ.subst_univs_level_constraints (snd (make_instance_subst info.abstr_info.abstr_ausubst)) cstrs in
(inst, cstrs)
let lift_relevance info relevance =
UVars.subst_sort_level_relevance (make_instance_subst info.abstr_info.abstr_ausubst) relevance
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-10)
¤
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 und die Messung sind noch experimentell.