summaryrefslogtreecommitdiff
path: root/kernel/mod_subst.ml
diff options
context:
space:
mode:
authorGravatar Enrico Tassi <gareuselesinge@debian.org>2015-01-25 14:42:51 +0100
committerGravatar Enrico Tassi <gareuselesinge@debian.org>2015-01-25 14:42:51 +0100
commit7cfc4e5146be5666419451bdd516f1f3f264d24a (patch)
treee4197645da03dc3c7cc84e434cc31d0a0cca7056 /kernel/mod_subst.ml
parent420f78b2caeaaddc6fe484565b2d0e49c66888e5 (diff)
Imported Upstream version 8.5~beta1+dfsg
Diffstat (limited to 'kernel/mod_subst.ml')
-rw-r--r--kernel/mod_subst.ml293
1 files changed, 154 insertions, 139 deletions
diff --git a/kernel/mod_subst.ml b/kernel/mod_subst.ml
index d46833db..f7ae30e7 100644
--- a/kernel/mod_subst.ml
+++ b/kernel/mod_subst.ml
@@ -1,6 +1,6 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2014 *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2015 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
@@ -19,7 +19,7 @@ open Names
open Term
(* For Inline, the int is an inlining level, and the constr (if present)
- is the term into which we should inline *)
+ is the term into which we should inline. *)
type delta_hint =
| Inline of int * constr option
@@ -31,28 +31,26 @@ type delta_hint =
module Deltamap = struct
type t = module_path MPmap.t * delta_hint KNmap.t
let empty = MPmap.empty, KNmap.empty
+ let is_empty (mm, km) =
+ MPmap.is_empty mm && KNmap.is_empty km
let add_kn kn hint (mm,km) = (mm,KNmap.add kn hint km)
let add_mp mp mp' (mm,km) = (MPmap.add mp mp' mm, km)
let find_mp mp map = MPmap.find mp (fst map)
let find_kn kn map = KNmap.find kn (snd map)
let mem_mp mp map = MPmap.mem mp (fst map)
- let mem_kn kn map = KNmap.mem kn (snd map)
let fold_kn f map i = KNmap.fold f (snd map) i
let fold fmp fkn (mm,km) i =
MPmap.fold fmp mm (KNmap.fold fkn km i)
let join map1 map2 = fold add_mp add_kn map1 map2
end
+(* Invariant: in the [delta_hint] map, an [Equiv] should only
+ relate [kernel_name] with the same label (and section dirpath). *)
+
type delta_resolver = Deltamap.t
let empty_delta_resolver = Deltamap.empty
-module MBImap = Map.Make
- (struct
- type t = mod_bound_id
- let compare = Pervasives.compare
- end)
-
module Umap = struct
type 'a t = 'a MPmap.t * 'a MBImap.t
let empty = MPmap.empty, MBImap.empty
@@ -61,8 +59,6 @@ module Umap = struct
let add_mp mp x (m1,m2) = (MPmap.add mp x m1, m2)
let find_mp mp map = MPmap.find mp (fst map)
let find_mbi mbi map = MBImap.find mbi (snd map)
- let mem_mp mp map = MPmap.mem mp (fst map)
- let mem_mbi mbi map = MBImap.mem mbi (snd map)
let iter_mbi f map = MBImap.iter f (snd map)
let fold fmp fmbi (m1,m2) i =
MPmap.fold fmp m1 (MBImap.fold fmbi m2 i)
@@ -95,7 +91,7 @@ let debug_string_of_delta resolve =
let list_contents sub =
let one_pair (mp,reso) = (string_of_mp mp,debug_string_of_delta reso) in
let mp_one_pair mp0 p l = (string_of_mp mp0, one_pair p)::l in
- let mbi_one_pair mbi p l = (debug_string_of_mbid mbi, one_pair p)::l in
+ let mbi_one_pair mbi p l = (MBId.debug_to_string mbi, one_pair p)::l in
Umap.fold mp_one_pair mbi_one_pair sub []
let debug_string_of_subst sub =
@@ -120,11 +116,13 @@ let debug_pr_subst sub =
let add_inline_delta_resolver kn (lev,oc) = Deltamap.add_kn kn (Inline (lev,oc))
-let add_kn_delta_resolver kn kn' = Deltamap.add_kn kn (Equiv kn')
+let add_kn_delta_resolver kn kn' =
+ assert (Label.equal (label kn) (label kn'));
+ Deltamap.add_kn kn (Equiv kn')
let add_mp_delta_resolver mp1 mp2 = Deltamap.add_mp mp1 mp2
-(** Extending a [substitution *)
+(** Extending a [substitution] *)
let add_mbid mbid mp resolve s = Umap.add_mbi mbid (mp,resolve) s
let add_mp mp1 mp2 resolve s = Umap.add_mp mp1 (mp2,resolve) s
@@ -141,13 +139,13 @@ let kn_in_delta kn resolver =
| Inline _ -> false
with Not_found -> false
-let con_in_delta con resolver = kn_in_delta (user_con con) resolver
-let mind_in_delta mind resolver = kn_in_delta (user_mind mind) resolver
+let con_in_delta con resolver = kn_in_delta (Constant.user con) resolver
+let mind_in_delta mind resolver = kn_in_delta (MutInd.user mind) resolver
let mp_of_delta resolve mp =
try Deltamap.find_mp mp resolve with Not_found -> mp
-let rec find_prefix resolve mp =
+let find_prefix resolve mp =
let rec sub_mp = function
| MPdot(mp,l) as mp_sup ->
(try Deltamap.find_mp mp_sup resolve
@@ -156,6 +154,8 @@ let rec find_prefix resolve mp =
in
try sub_mp mp with Not_found -> mp
+(** Applying a resolver to a kernel name *)
+
exception Change_equiv_to_inline of (int * constr)
let solve_delta_kn resolve kn =
@@ -174,35 +174,25 @@ let solve_delta_kn resolve kn =
let kn_of_delta resolve kn =
try solve_delta_kn resolve kn
- with e when Errors.noncritical e -> kn
+ with Change_equiv_to_inline _ -> kn
-let constant_of_delta_kn resolve kn =
- constant_of_kn_equiv kn (kn_of_delta resolve kn)
+(** Try a 1st resolver, and then a 2nd in case it had no effect *)
-let gen_of_delta resolve x kn fix_can =
- try
- let new_kn = solve_delta_kn resolve kn in
- if kn == new_kn then x else fix_can new_kn
- with e when Errors.noncritical e -> x
+let kn_of_deltas resolve1 resolve2 kn =
+ let kn' = kn_of_delta resolve1 kn in
+ if kn' == kn then kn_of_delta resolve2 kn else kn'
-let constant_of_delta resolve con =
- let kn = user_con con in
- gen_of_delta resolve con kn (constant_of_kn_equiv kn)
+let constant_of_delta_kn resolve kn =
+ Constant.make kn (kn_of_delta resolve kn)
-let constant_of_delta2 resolve con =
- let kn, kn' = canonical_con con, user_con con in
- gen_of_delta resolve con kn (constant_of_kn_equiv kn')
+let constant_of_deltas_kn resolve1 resolve2 kn =
+ Constant.make kn (kn_of_deltas resolve1 resolve2 kn)
let mind_of_delta_kn resolve kn =
- mind_of_kn_equiv kn (kn_of_delta resolve kn)
+ MutInd.make kn (kn_of_delta resolve kn)
-let mind_of_delta resolve mind =
- let kn = user_mind mind in
- gen_of_delta resolve mind kn (mind_of_kn_equiv kn)
-
-let mind_of_delta2 resolve mind =
- let kn, kn' = canonical_mind mind, user_mind mind in
- gen_of_delta resolve mind kn (mind_of_kn_equiv kn')
+let mind_of_deltas_kn resolve1 resolve2 kn =
+ MutInd.make kn (kn_of_deltas resolve1 resolve2 kn)
let inline_of_delta inline resolver =
match inline with
@@ -215,18 +205,16 @@ let inline_of_delta inline resolver =
in
Deltamap.fold_kn extract resolver []
-let find_inline_of_delta kn resolve =
- match Deltamap.find_kn kn resolve with
+let search_delta_inline resolve kn1 kn2 =
+ let find kn = match Deltamap.find_kn kn resolve with
| Inline (_,o) -> o
- | _ -> raise Not_found
-
-let constant_of_delta_with_inline resolve con =
- let kn1,kn2 = canonical_con con,user_con con in
- try find_inline_of_delta kn2 resolve
+ | Equiv _ -> raise Not_found
+ in
+ try find kn1
with Not_found ->
if kn1 == kn2 then None
else
- try find_inline_of_delta kn1 resolve
+ try find kn2
with Not_found -> None
let subst_mp0 sub mp = (* 's like subst *)
@@ -270,52 +258,76 @@ let subst_kn sub kn =
exception No_subst
-type sideconstantsubst =
- | User
- | Canonical
-
-let gen_subst_mp f sub mp1 mp2 =
+let subst_dual_mp sub mp1 mp2 =
let o1 = subst_mp0 sub mp1 in
let o2 = if mp1 == mp2 then o1 else subst_mp0 sub mp2 in
match o1, o2 with
| None, None -> raise No_subst
- | Some (mp',resolve), None -> User, (f mp' mp2), resolve
- | None, Some (mp',resolve) -> Canonical, (f mp1 mp'), resolve
- | Some (mp1',_), Some (mp2',resolve2) -> Canonical, (f mp1' mp2'), resolve2
-
-let subst_ind sub mind =
- let kn1,kn2 = user_mind mind, canonical_mind mind in
- let mp1,dir,l = repr_kn kn1 in
- let mp2,_,_ = repr_kn kn2 in
- let rebuild_mind mp1 mp2 = make_mind_equiv mp1 mp2 dir l in
+ | Some (mp1',resolve), None -> mp1', mp2, resolve, true
+ | None, Some (mp2',resolve) -> mp1, mp2', resolve, false
+ | Some (mp1',_), Some (mp2',resolve) -> mp1', mp2', resolve, false
+
+let progress f x ~orelse =
+ let y = f x in
+ if y != x then y else orelse
+
+let subst_mind sub mind =
+ let mpu,dir,l = MutInd.repr3 mind in
+ let mpc = KerName.modpath (MutInd.canonical mind) in
try
- let side,mind',resolve = gen_subst_mp rebuild_mind sub mp1 mp2 in
- match side with
- | User -> mind_of_delta resolve mind'
- | Canonical -> mind_of_delta2 resolve mind'
+ let mpu,mpc,resolve,user = subst_dual_mp sub mpu mpc in
+ let knu = KerName.make mpu dir l in
+ let knc = if mpu == mpc then knu else KerName.make mpc dir l in
+ let knc' =
+ progress (kn_of_delta resolve) (if user then knu else knc) ~orelse:knc
+ in
+ MutInd.make knu knc'
with No_subst -> mind
-let subst_con0 sub con =
- let kn1,kn2 = user_con con,canonical_con con in
- let mp1,dir,l = repr_kn kn1 in
- let mp2,_,_ = repr_kn kn2 in
- let rebuild_con mp1 mp2 = make_con_equiv mp1 mp2 dir l in
- let dup con = con, mkConst con in
- let side,con',resolve = gen_subst_mp rebuild_con sub mp1 mp2 in
- match constant_of_delta_with_inline resolve con' with
+let subst_ind sub (ind,i as indi) =
+ let ind' = subst_mind sub ind in
+ if ind' == ind then indi else ind',i
+
+let subst_pind sub (ind,u) =
+ (subst_ind sub ind, u)
+
+let subst_con0 sub (cst,u) =
+ let mpu,dir,l = Constant.repr3 cst in
+ let mpc = KerName.modpath (Constant.canonical cst) in
+ let mpu,mpc,resolve,user = subst_dual_mp sub mpu mpc in
+ let knu = KerName.make mpu dir l in
+ let knc = if mpu == mpc then knu else KerName.make mpc dir l in
+ match search_delta_inline resolve knu knc with
| Some t ->
(* In case of inlining, discard the canonical part (cf #2608) *)
- constant_of_kn (user_con con'), t
+ Constant.make1 knu, t
| None ->
- let con'' = match side with
- | User -> constant_of_delta resolve con'
- | Canonical -> constant_of_delta2 resolve con'
+ let knc' =
+ progress (kn_of_delta resolve) (if user then knu else knc) ~orelse:knc
in
- if con'' == con then raise No_subst else dup con''
+ let cst' = Constant.make knu knc' in
+ cst', mkConstU (cst',u)
+
+let subst_con sub cst =
+ try subst_con0 sub cst
+ with No_subst -> fst cst, mkConstU cst
+
+let subst_con_kn sub con =
+ subst_con sub (con,Univ.Instance.empty)
+
+let subst_pcon sub (con,u as pcon) =
+ try let con', can = subst_con0 sub pcon in
+ con',u
+ with No_subst -> pcon
-let subst_con sub con =
- try subst_con0 sub con
- with No_subst -> con, mkConst con
+let subst_pcon_term sub (con,u as pcon) =
+ try let con', can = subst_con0 sub pcon in
+ (con',u), can
+ with No_subst -> pcon, mkConstU pcon
+
+let subst_constant sub con =
+ try fst (subst_con0 sub (con,Univ.Instance.empty))
+ with No_subst -> con
(* Here the semantics is completely unclear.
What does "Hint Unfold t" means when "t" is a parameter?
@@ -324,18 +336,27 @@ let subst_con sub con =
interpretation (i.e. an evaluable reference is never expanded). *)
let subst_evaluable_reference subst = function
| EvalVarRef id -> EvalVarRef id
- | EvalConstRef kn -> EvalConstRef (fst (subst_con subst kn))
+ | EvalConstRef kn -> EvalConstRef (subst_constant subst kn)
let rec map_kn f f' c =
let func = map_kn f f' in
match kind_of_term c with
| Const kn -> (try snd (f' kn) with No_subst -> c)
- | Ind (kn,i) ->
+ | Proj (p,t) ->
+ let p' =
+ try
+ Projection.map (fun kn -> fst (f' (kn,Univ.Instance.empty))) p
+ with No_subst -> p
+ in
+ let t' = func t in
+ if p' == p && t' == t then c
+ else mkProj (p', t')
+ | Ind ((kn,i),u) ->
let kn' = f kn in
- if kn'==kn then c else mkInd (kn',i)
- | Construct ((kn,i),j) ->
+ if kn'==kn then c else mkIndU ((kn',i),u)
+ | Construct (((kn,i),j),u) ->
let kn' = f kn in
- if kn'==kn then c else mkConstruct ((kn',i),j)
+ if kn'==kn then c else mkConstructU (((kn',i),j),u)
| Case (ci,p,ct,l) ->
let ci_ind =
let (kn,i) = ci.ci_ind in
@@ -344,7 +365,7 @@ let rec map_kn f f' c =
in
let p' = func p in
let ct' = func ct in
- let l' = array_smartmap func l in
+ let l' = Array.smartmap func l in
if (ci.ci_ind==ci_ind && p'==p
&& l'==l && ct'==ct)then c
else
@@ -373,35 +394,35 @@ let rec map_kn f f' c =
else mkLetIn (na, b', t', ct')
| App (ct,l) ->
let ct' = func ct in
- let l' = array_smartmap func l in
+ let l' = Array.smartmap func l in
if (ct'== ct && l'==l) then c
else mkApp (ct',l')
| Evar (e,l) ->
- let l' = array_smartmap func l in
+ let l' = Array.smartmap func l in
if (l'==l) then c
else mkEvar (e,l')
| Fix (ln,(lna,tl,bl)) ->
- let tl' = array_smartmap func tl in
- let bl' = array_smartmap func bl in
+ let tl' = Array.smartmap func tl in
+ let bl' = Array.smartmap func bl in
if (bl == bl'&& tl == tl') then c
else mkFix (ln,(lna,tl',bl'))
| CoFix(ln,(lna,tl,bl)) ->
- let tl' = array_smartmap func tl in
- let bl' = array_smartmap func bl in
+ let tl' = Array.smartmap func tl in
+ let bl' = Array.smartmap func bl in
if (bl == bl'&& tl == tl') then c
else mkCoFix (ln,(lna,tl',bl'))
| _ -> c
let subst_mps sub c =
if is_empty_subst sub then c
- else map_kn (subst_ind sub) (subst_con0 sub) c
+ else map_kn (subst_mind sub) (subst_con0 sub) c
let rec replace_mp_in_mp mpfrom mpto mp =
match mp with
- | _ when mp = mpfrom -> mpto
+ | _ when mp_eq mp mpfrom -> mpto
| MPdot (mp1,l) ->
let mp1' = replace_mp_in_mp mpfrom mpto mp1 in
- if mp1==mp1' then mp
+ if mp1 == mp1' then mp
else MPdot (mp1',l)
| _ -> mp
@@ -413,7 +434,7 @@ let replace_mp_in_kn mpfrom mpto kn =
let rec mp_in_mp mp mp1 =
match mp1 with
- | _ when mp1 = mp -> true
+ | _ when mp_eq mp1 mp -> true
| MPdot (mp2,l) -> mp_in_mp mp mp2
| _ -> false
@@ -471,33 +492,30 @@ let subst_dom_codom_delta_resolver = gen_subst_delta_resolver true
let update_delta_resolver resolver1 resolver2 =
let mp_apply_rslv mkey mequ rslv =
- if Deltamap.mem_mp mkey resolver2 then rslv
- else Deltamap.add_mp mkey (find_prefix resolver2 mequ) rslv
+ Deltamap.add_mp mkey (find_prefix resolver2 mequ) rslv
in
- let kn_apply_rslv kkey hint rslv =
- if Deltamap.mem_kn kkey resolver2 then rslv
- else
- let hint' = match hint with
- | Equiv kequ ->
- (try Equiv (solve_delta_kn resolver2 kequ)
- with Change_equiv_to_inline (lev,c) -> Inline (lev, Some c))
- | _ -> hint
- in
- Deltamap.add_kn kkey hint' rslv
+ let kn_apply_rslv kkey hint1 rslv =
+ let hint = match hint1 with
+ | Equiv kequ ->
+ (try Equiv (solve_delta_kn resolver2 kequ)
+ with Change_equiv_to_inline (lev,c) -> Inline (lev, Some c))
+ | Inline (_,Some _) -> hint1
+ | Inline (_,None) ->
+ (try Deltamap.find_kn kkey resolver2 with Not_found -> hint1)
+ in
+ Deltamap.add_kn kkey hint rslv
in
- Deltamap.fold mp_apply_rslv kn_apply_rslv resolver1 empty_delta_resolver
+ Deltamap.fold mp_apply_rslv kn_apply_rslv resolver1 resolver2
let add_delta_resolver resolver1 resolver2 =
- if resolver1 == resolver2 then
- resolver2
- else if resolver2 = empty_delta_resolver then
+ if Deltamap.is_empty resolver2 then
resolver1
else
- Deltamap.join (update_delta_resolver resolver1 resolver2) resolver2
+ update_delta_resolver resolver1 resolver2
let substition_prefixed_by k mp subst =
let mp_prefixmp kmp (mp_to,reso) sub =
- if mp_in_mp mp kmp && mp <> kmp then
+ if mp_in_mp mp kmp && not (mp_eq mp kmp) then
let new_key = replace_mp_in_mp mp k kmp in
Umap.add_mp new_key (mp_to,reso) sub
else sub
@@ -529,44 +547,41 @@ let join subst1 subst2 =
Umap.join subst2 subst
let rec occur_in_path mbi = function
- | MPbound bid' -> mbi = bid'
+ | MPbound bid' -> MBId.equal mbi bid'
| MPdot (mp1,_) -> occur_in_path mbi mp1
| _ -> false
let occur_mbid mbi sub =
let check_one mbi' (mp,_) =
- if mbi = mbi' || occur_in_path mbi mp then raise Exit
+ if MBId.equal mbi mbi' || occur_in_path mbi mp then raise Exit
in
try
Umap.iter_mbi check_one sub;
false
with Exit -> true
-type 'a lazy_subst =
- | LSval of 'a
- | LSlazy of substitution list * 'a
+type 'a substituted = {
+ mutable subst_value : 'a;
+ mutable subst_subst : substitution list;
+}
-type 'a substituted = 'a lazy_subst ref
+let from_val x = { subst_value = x; subst_subst = []; }
-let from_val a = ref (LSval a)
+let force fsubst r = match r.subst_subst with
+| [] -> r.subst_value
+| s ->
+ let subst = List.fold_left join empty_subst (List.rev s) in
+ let x = fsubst subst r.subst_value in
+ let () = r.subst_subst <- [] in
+ let () = r.subst_value <- x in
+ x
-let force fsubst r =
- match !r with
- | LSval a -> a
- | LSlazy(s,a) ->
- let subst = List.fold_left join empty_subst (List.rev s) in
- let a' = fsubst subst a in
- r := LSval a';
- a'
+let subst_substituted s r = { r with subst_subst = s :: r.subst_subst; }
-let subst_substituted s r =
- match !r with
- | LSval a -> ref (LSlazy([s],a))
- | LSlazy(s',a) ->
- ref (LSlazy(s::s',a))
+let force_constr = force subst_mps
+let subst_constr = subst_substituted
(* debug *)
-let repr_substituted r =
- match !r with
- | LSval a -> None, a
- | LSlazy(s,a) -> Some s, a
+let repr_substituted r = match r.subst_subst with
+| [] -> None, r.subst_value
+| s -> Some s, r.subst_value