@@ -20,10 +20,17 @@ open Util
2020open Names
2121open Constr
2222
23+ (* The modpath part of a resolver holds two kinds of statements.
24+ - [p ↦ MPequiv q] states that [q] is the canonical name of [p].
25+ - [p ↦ MPlift] states that [p] is a bound name that should be left untouched
26+ by substitution. *)
27+ type mp_hint =
28+ | MPequiv of ModPath .t (* * the canonical form of the key *)
29+ | MPlift (* * the prefix rule stops here *)
30+
2331(* For Inline, the int is an inlining level, and the constr (if present)
2432 is the term into which we should inline.
2533 Equiv gives the canonical name in the given context. *)
26-
2734type delta_hint =
2835 | Inline of int * constr UVars .univ_abstracted option
2936 | Equiv of KerName .t
@@ -35,7 +42,7 @@ module Deltamap = struct
3542 type t = {
3643 root : ModPath .t ;
3744 (* * Common root of all keys in the deltamap *)
38- mmap : ModPath .t ModPath.Map .t ;
45+ mmap : mp_hint ModPath.Map .t ;
3946 (* * All bindings [mp ↦ _] must satisfy [mp ⊆ root] *)
4047 kmap : delta_hint KerName.Map .t ;
4148 (* * All bindings [kn ↦ _] must satisfy [modpath(kn) ⊆ root] *)
@@ -53,16 +60,19 @@ module Deltamap = struct
5360 let () = assert (ModPath. subpath reso.root (KerName. modpath kn)) in
5461 { reso with kmap = KerName.Map. add kn hint reso.kmap }
5562
56- let add_mp mp mp' reso =
63+ let add_mp_hint mp hint reso =
5764 let () = assert (ModPath. subpath reso.root mp) in
58- { reso with mmap = ModPath.Map. add mp mp' reso.mmap }
65+ { reso with mmap = ModPath.Map. add mp hint reso.mmap }
5966
60- let find_mp mp reso = ModPath.Map. find mp reso.mmap
67+ let add_mp mp mp' reso = add_mp_hint mp (MPequiv mp') reso
68+ let lift_mp mp reso = add_mp_hint mp MPlift reso
69+
70+ let find_mp_opt mp reso = ModPath.Map. find_opt mp reso.mmap
6171 let find_kn kn reso = KerName.Map. find kn reso.kmap
6272 let fold_kn f reso i = KerName.Map. fold f reso.kmap i
6373 let fold fmp fkn reso accu =
6474 ModPath.Map. fold fmp reso.mmap (KerName.Map. fold fkn reso.kmap accu)
65- let join map1 map2 = fold add_mp add_kn map1 map2
75+ let join map1 map2 = fold add_mp_hint add_kn map1 map2
6676
6777 (* * if mp0 ⊆ root, we can see a resolver on root as a resolver on mp *)
6878 let upcast mp0 reso =
@@ -87,8 +97,8 @@ module Deltamap = struct
8797 path in mm above root, as find_prefix will always return this one
8898 without considering the less precise ones. *)
8999 let glb = match glb with
90- | None -> Some mp
91- | Some glb -> if ModPath. subpath glb mp then Some mp else Some glb
100+ | None -> Some (mp, data)
101+ | Some ( g , _ ) as old -> if ModPath. subpath g mp then Some (mp, data) else old
92102 in
93103 glb, accu
94104 else
@@ -98,21 +108,23 @@ module Deltamap = struct
98108 let glb, mm' = ModPath.Map. fold fold_mp mm (None , ModPath.Map. empty) in
99109 let mm' = match glb with
100110 | None -> mm'
101- | Some glb ->
111+ | Some ( glb , data ) ->
102112 if ModPath.Map. mem root mm then mm'
103113 else
104114 (* Add root to the resolver and map it to what find_prefix would have
105115 returned on root *)
106- let rec diff accu mp =
107- if ModPath. equal mp glb then accu
108- else match mp with
109- | MPdot (mp , l ) -> diff (l :: accu) mp
110- | MPbound _ | MPfile _ -> assert false
111- in
112- let diff = diff [] root in
113- let data = ModPath.Map. get glb mm in
114- let data' = List. fold_left (fun accu l -> MPdot (accu, l)) data diff in
115- ModPath.Map. add root data' mm'
116+ match data with
117+ | MPlift -> ModPath.Map. add root MPlift mm'
118+ | MPequiv data ->
119+ let rec diff accu mp =
120+ if ModPath. equal mp glb then accu
121+ else match mp with
122+ | MPdot (mp , l ) -> diff (l :: accu) mp
123+ | MPbound _ | MPfile _ -> assert false
124+ in
125+ let diff = diff [] root in
126+ let data' = List. fold_left (fun accu l -> MPdot (accu, l)) data diff in
127+ ModPath.Map. add root (MPequiv data') mm'
116128 in
117129 (* filter the kernames *)
118130 let filter_kn kn _ = ModPath. subpath root (KerName. modpath kn) in
@@ -166,12 +178,16 @@ let string_of_hint pr = function
166178 | Inline (lvl , None) -> str " inline[" ++ int lvl ++ str " ]"
167179 | Equiv kn -> str " equiv(" ++ KerName. print kn ++ str " )"
168180
181+ let debug_pr_mp_hint = function
182+ | MPequiv mp -> ModPath. print mp
183+ | MPlift -> str " <lift>"
184+
169185let debug_pr_delta pr resolve =
170186 let kn_to_string kn hint l =
171187 hov 2 (KerName. print kn ++ str " =>" ++ spc() ++ string_of_hint pr hint) :: l
172188 in
173- let mp_to_string mp mp' l =
174- hov 2 (ModPath. print mp ++ str " =>" ++ spc() ++ ModPath. print mp' ) :: l
189+ let mp_to_string mp hint l =
190+ hov 2 (ModPath. print mp ++ str " =>" ++ spc() ++ debug_pr_mp_hint hint ) :: l
175191 in
176192 let l = Deltamap. fold mp_to_string kn_to_string resolve [] in
177193 v 0 @@ prlist_with_sep pr_comma (fun p -> p) (List. rev l)
@@ -207,7 +223,11 @@ let add_kn_delta_resolver kn kn' =
207223 assert (Id. equal (KerName. label kn) (KerName. label kn'));
208224 Deltamap. add_kn kn (Equiv kn')
209225
210- let add_mp_delta_resolver mp1 mp2 = Deltamap. add_mp mp1 mp2
226+ let add_mp_delta_resolver mp1 mp2 =
227+ let () = assert (not (ModPath. equal mp1 mp2)) in
228+ Deltamap. add_mp mp1 mp2
229+
230+ let lift_mp_delta_resolver mp = Deltamap. lift_mp mp
211231
212232(* * Extending a [substitution] without sequential composition *)
213233
@@ -223,13 +243,19 @@ let map_mbid mbid mp resolve =
223243let map_mp mp1 mp2 resolve = add_mp mp1 mp2 resolve empty_subst
224244
225245let find_prefix resolve mp =
226- let rec sub_mp = function
227- | MPdot (mp ,l ) as mp_sup ->
228- (try Deltamap. find_mp mp_sup resolve
229- with Not_found -> MPdot (sub_mp mp,l))
230- | p -> Deltamap. find_mp p resolve
246+ let rec sub_mp mp = match Deltamap. find_mp_opt mp resolve with
247+ | Some (MPequiv mp' ) -> mp'
248+ | Some MPlift -> mp
249+ | None ->
250+ match mp with
251+ | MPdot (mp1 , l ) ->
252+ (* Preserving sharing is not an optimisation: [progress] in [subst_con0]
253+ and [subst_mind] tests with [!=]. This should be fixed at some point. *)
254+ let mp1' = sub_mp mp1 in
255+ if mp1' == mp1 then mp else MPdot (mp1', l)
256+ | MPbound _ | MPfile _ -> mp
231257 in
232- try sub_mp mp with Not_found -> mp
258+ sub_mp mp
233259
234260(* TODO: remove the indirection at some point *)
235261let mp_of_delta = find_prefix
@@ -543,8 +569,8 @@ let replace_mp_in_kn mpfrom mpto kn =
543569let mp_in_mp = ModPath. subpath
544570
545571let subset_prefixed_by mp resolver =
546- let mp_prefix mkey mequ rslv =
547- if mp_in_mp mp mkey then Deltamap. add_mp mkey mequ rslv else rslv
572+ let mp_prefix mkey hint rslv =
573+ if mp_in_mp mp mkey then Deltamap. add_mp_hint mkey hint rslv else rslv
548574 in
549575 let kn_prefix kn hint rslv =
550576 match hint with
@@ -557,8 +583,8 @@ let subset_prefixed_by mp resolver =
557583let subst_dom_delta_resolver mp_from mp_to resolver =
558584 let () = assert (ModPath. equal mp_from resolver.Deltamap. root) in
559585 let subst = map_mp mp_from mp_to (empty_delta_resolver mp_to) in
560- let mp_apply_subst mkey mequ rslv =
561- Deltamap. add_mp (subst_mp subst mkey) mequ rslv
586+ let mp_apply_subst mkey hint rslv =
587+ Deltamap. add_mp_hint (subst_mp subst mkey) hint rslv
562588 in
563589 let kn_apply_subst kkey hint rslv =
564590 Deltamap. add_kn (subst_kn subst kkey) hint rslv
@@ -594,10 +620,13 @@ let subst_mp_delta subst mp mkey =
594620 reso, mp1
595621
596622let gen_subst_delta_resolver dom subst resolver =
597- let mp_apply_subst mkey mequ rslv =
623+ let mp_apply_subst mkey hint rslv =
598624 let mkey' = if dom then subst_mp subst mkey else mkey in
599- let rslv',mequ' = subst_mp_delta subst mequ mkey' in
600- Deltamap. join rslv' (Deltamap. add_mp mkey' mequ' rslv)
625+ match hint with
626+ | MPlift -> Deltamap. add_mp_hint mkey' MPlift rslv
627+ | MPequiv mequ ->
628+ let rslv', mequ' = subst_mp_delta subst mequ mkey' in
629+ Deltamap. join rslv' (Deltamap. add_mp_hint mkey' (MPequiv mequ') rslv)
601630 in
602631 let kn_apply_subst kkey hint rslv =
603632 let kkey' = if dom then subst_kn subst kkey else kkey in
@@ -615,8 +644,10 @@ let subst_codom_delta_resolver = gen_subst_delta_resolver false
615644let subst_dom_codom_delta_resolver = gen_subst_delta_resolver true
616645
617646let update_delta_resolver resolver1 resolver2 =
618- let mp_apply_rslv mkey mequ rslv =
619- Deltamap. add_mp mkey (find_prefix resolver2 mequ) rslv
647+ let mp_apply_rslv mkey hint rslv = match hint with
648+ | MPlift -> Deltamap. add_mp_hint mkey MPlift rslv
649+ | MPequiv mequ ->
650+ Deltamap. add_mp_hint mkey (MPequiv (find_prefix resolver2 mequ)) rslv
620651 in
621652 let kn_apply_rslv kkey hint1 rslv =
622653 let hint = match hint1 with
0 commit comments