1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2019 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \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 Names
open Univ
module NamedDecl = Context.Named.Declaration
type section_entry =
| SecDefinition of Constant.t
| SecInductive of MutInd.t
type 'a entry_map = 'a Cmap.t * 'a Mindmap.t
type 'a section = {
sec_context : int;
(** Length of the named context suffix that has been introduced locally *)
sec_mono_universes : ContextSet.t;
sec_poly_universes : Name.t array * UContext.t;
(** Universes local to the section *)
has_poly_univs : bool;
(** Are there polymorphic universes or constraints, including in previous sections. *)
sec_entries : section_entry list;
(** Definitions introduced in the section *)
sec_data : (Instance.t * AUContext.t) entry_map;
(** Additional data synchronized with the section *)
sec_custom : 'a;
}
(** Sections can be nested with the proviso that no monomorphic section can be
opened inside a polymorphic one. The reverse is allowed. *)
type 'a t = 'a section list
let empty = []
let is_empty = List.is_empty
let depth = List.length
let has_poly_univs = function
| [] -> false
| sec :: _ -> sec.has_poly_univs
let find_emap e (cmap, imap) = match e with
| SecDefinition con -> Cmap.find con cmap
| SecInductive ind -> Mindmap.find ind imap
let add_emap e v (cmap, imap) = match e with
| SecDefinition con -> (Cmap.add con v cmap, imap)
| SecInductive ind -> (cmap, Mindmap.add ind v imap)
let on_last_section f sections = match sections with
| [] -> CErrors.user_err (Pp.str "No opened section")
| sec :: rem -> f sec :: rem
let with_last_section f sections = match sections with
| [] -> f None
| sec :: _ -> f (Some sec)
let push_local s =
let on_sec sec = { sec with sec_context = sec.sec_context + 1 } in
on_last_section on_sec s
let push_context (nas, ctx) s =
let on_sec sec =
if UContext.is_empty ctx then sec
else
let (snas, sctx) = sec.sec_poly_universes in
let sec_poly_universes = (Array.append snas nas, UContext.union sctx ctx) in
{ sec with sec_poly_universes; has_poly_univs = true }
in
on_last_section on_sec s
let is_polymorphic_univ u s =
let check sec =
let (_, uctx) = sec.sec_poly_universes in
Array.exists (fun u' -> Level.equal u u') (Instance.to_array (UContext.instance uctx))
in
List.exists check s
let push_constraints uctx s =
let on_sec sec =
if sec.has_poly_univs && Constraint.exists (fun (l,_,r) -> is_polymorphic_univ l s || is_polymorphic_univ r s) (snd uctx)
then CErrors.user_err Pp.(str "Cannot add monomorphic constraints which refer to section polymorphic universes.");
let uctx' = sec.sec_mono_universes in
let sec_mono_universes = (ContextSet.union uctx uctx') in
{ sec with sec_mono_universes }
in
on_last_section on_sec s
let open_section ~custom sections =
let sec = {
sec_context = 0;
sec_mono_universes = ContextSet.empty;
sec_poly_universes = ([||], UContext.empty);
has_poly_univs = has_poly_univs sections;
sec_entries = [];
sec_data = (Cmap.empty, Mindmap.empty);
sec_custom = custom;
} in
sec :: sections
let close_section sections =
match sections with
| sec :: sections ->
sections, sec.sec_entries, sec.sec_mono_universes, sec.sec_custom
| [] ->
CErrors.user_err (Pp.str "No opened section.")
let make_decl_univs (nas,uctx) = abstract_universes nas uctx
let push_global ~poly e s =
if is_empty s then s
else if has_poly_univs s && not poly
then CErrors.user_err
Pp.(str "Cannot add a universe monomorphic declaration when \
section polymorphic universes are present.")
else
let on_sec sec =
{ sec with
sec_entries = e :: sec.sec_entries;
sec_data = add_emap e (make_decl_univs sec.sec_poly_universes) sec.sec_data;
}
in
on_last_section on_sec s
let push_constant ~poly con s = push_global ~poly (SecDefinition con) s
let push_inductive ~poly ind s = push_global ~poly (SecInductive ind) s
type abstr_info = {
abstr_ctx : Constr.named_context;
abstr_subst : Instance.t;
abstr_uctx : AUContext.t;
}
let empty_segment = {
abstr_ctx = [];
abstr_subst = Instance.empty;
abstr_uctx = AUContext.empty;
}
let extract_hyps sec vars used =
(* Keep the section-local segment of variables *)
let vars = List.firstn sec.sec_context vars in
(* Only keep the part that is used by the declaration *)
List.filter (fun d -> Id.Set.mem (NamedDecl.get_id d) used) vars
let section_segment_of_entry vars e hyps sections =
(* [vars] are the named hypotheses, [hyps] the subset that is declared by the
global *)
let with_sec s = match s with
| None ->
CErrors.user_err (Pp.str "No opened section.")
| Some sec ->
let hyps = extract_hyps sec vars hyps in
let inst, auctx = find_emap e sec.sec_data in
{
abstr_ctx = hyps;
abstr_subst = inst;
abstr_uctx = auctx;
}
in
with_last_section with_sec sections
let segment_of_constant env con s =
let body = Environ.lookup_constant con env in
let vars = Environ.named_context env in
let used = Context.Named.to_vars body.Declarations.const_hyps in
section_segment_of_entry vars (SecDefinition con) used s
let segment_of_inductive env mind s =
let mib = Environ.lookup_mind mind env in
let vars = Environ.named_context env in
let used = Context.Named.to_vars mib.Declarations.mind_hyps in
section_segment_of_entry vars (SecInductive mind) used s
let instance_from_variable_context =
List.rev %> List.filter NamedDecl.is_local_assum %> List.map NamedDecl.get_id %> Array.of_list
let extract_worklist info =
let args = instance_from_variable_context info.abstr_ctx in
info.abstr_subst, args
let replacement_context env s =
let with_sec sec = match sec with
| None -> CErrors.user_err (Pp.str "No opened section.")
| Some sec ->
let cmap, imap = sec.sec_data in
let cmap = Cmap.mapi (fun con _ -> extract_worklist @@ segment_of_constant env con s) cmap in
let imap = Mindmap.mapi (fun ind _ -> extract_worklist @@ segment_of_inductive env ind s) imap in
(cmap, imap)
in
with_last_section with_sec s
let is_in_section env gr s =
let with_sec sec = match sec with
| None -> false
| Some sec ->
let open GlobRef in
match gr with
| VarRef id ->
let vars = List.firstn sec.sec_context (Environ.named_context env) in
List.exists (fun decl -> Id.equal id (NamedDecl.get_id decl)) vars
| ConstRef con ->
Cmap.mem con (fst sec.sec_data)
| IndRef (ind, _) | ConstructRef ((ind, _), _) ->
Mindmap.mem ind (snd sec.sec_data)
in
with_last_section with_sec s