Source file elimschemes.ml
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
open Names
open Indrec
open Declarations
open Ind_tables
open UnivGen
let prop_but_default_dependent_elim =
Summary.ref ~name:"PROP-BUT-DEFAULT-DEPENDENT-ELIM" Indset_env.empty
let inPropButDefaultDepElim : inductive -> Libobject.obj =
Libobject.declare_object @@
Libobject.superglobal_object "prop_but_default_dependent_elim"
~cache:(fun i ->
prop_but_default_dependent_elim := Indset_env.add i !prop_but_default_dependent_elim)
~subst:(Some (fun (subst,i) -> Mod_subst.subst_ind subst i))
~discharge:(fun i -> Some i)
let declare_prop_but_default_dependent_elim i =
Lib.add_leaf (inPropButDefaultDepElim i)
let is_prop_but_default_dependent_elim i = Indset_env.mem i !prop_but_default_dependent_elim
let pseudo_sort_quality_for_elim ind mip =
let s = mip.mind_sort in
if Sorts.is_prop s && is_prop_but_default_dependent_elim ind
then Sorts.Quality.qtype
else Sorts.quality s
let default_case_analysis_dependence env ind =
let _, mip as specif = Inductive.lookup_mind_specif env ind in
Inductiveops.has_dependent_elim specif
&& (not (Sorts.is_prop mip.mind_sort) || is_prop_but_default_dependent_elim ind)
let build_induction_scheme_in_type env dep sort ind =
let sigma = Evd.from_env env in
let sigma, pind = Evd.fresh_inductive_instance ~rigid:UState.univ_rigid env sigma ind in
let sigma, sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in
let sigma, c = build_induction_scheme env sigma pind dep sort in
EConstr.to_constr sigma c, Evd.ustate sigma
let rect_dep =
declare_individual_scheme_object "rect_dep"
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.qtype x)
let rec_dep =
declare_individual_scheme_object "rec_dep"
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.set x)
let ind_dep =
declare_individual_scheme_object "ind_dep"
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.prop x)
let sind_dep =
declare_individual_scheme_object "sind_dep"
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.sprop x)
let rect_nodep =
declare_individual_scheme_object "rect_nodep"
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.qtype x)
let rec_nodep =
declare_individual_scheme_object "rec_nodep"
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.set x)
let ind_nodep =
declare_individual_scheme_object "ind_nodep"
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.prop x)
let sind_nodep =
declare_individual_scheme_object "sind_nodep"
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.sprop x)
let elim_scheme ~dep ~to_kind =
let open QualityOrSet in
match to_kind with
| Qual q ->
begin
match q with
| QConstant QSProp when dep -> sind_dep
| QConstant QProp when dep -> ind_dep
| (QConstant QType | QVar _) when dep -> rect_dep
| QConstant QSProp -> sind_nodep
| QConstant QProp -> ind_nodep
| QConstant QType | QVar _ -> rect_nodep
end
| Set -> if dep then rec_dep else rec_nodep
let elimination_suffix =
let open UnivGen.QualityOrSet in
let open Sorts.Quality in
function
| Qual (QConstant QSProp) -> "_sind"
| Qual (QConstant QProp) -> "_ind"
| Qual (QConstant QType) | Qual (QVar _) -> "_rect"
| Set -> "_rec"
let make_elimination_ident id s = Nameops.add_suffix id (elimination_suffix s)
let lookup_eliminator_by_name env ind_sp s =
let open Names in
let open Environ in
let kn,i = ind_sp in
let mpu = KerName.modpath @@ MutInd.user kn in
let mpc = KerName.modpath @@ MutInd.canonical kn in
let ind_id = (lookup_mind kn env).mind_packets.(i).mind_typename in
let id = make_elimination_ident ind_id s in
let knu = KerName.make mpu id in
let knc = KerName.make mpc id in
let cst = Constant.make knu knc in
if mem_constant cst env then GlobRef.ConstRef cst
else
try Nametab.locate (Libnames.qualid_of_ident id)
with Not_found ->
CErrors.user_err
Pp.(strbrk "Cannot find the elimination combinator " ++
Id.print id ++ strbrk ", the elimination of the inductive definition " ++
Nametab.pr_global_env Id.Set.empty (GlobRef.IndRef ind_sp) ++
strbrk " on sort " ++ UnivGen.QualityOrSet.pr Sorts.QVar.raw_pr s ++
strbrk " is probably not allowed.")
let deprecated_lookup_by_name =
CWarnings.create ~name:"deprecated-lookup-elim-by-name" ~category:Deprecation.Version.v9_2
Pp.(fun (env,ind,to_kind,r) ->
let pp_scheme () s = str (scheme_kind_name s) in
fmt "Found unregistered eliminator %t for %t by name.@ \
Use \"Register Scheme\" with it instead@ \
(\"as %a\" if dependent or \"as %a\" if non dependent)."
(fun () -> Termops.pr_global_env env r)
(fun () -> Termops.pr_global_env env (IndRef ind))
pp_scheme (elim_scheme ~dep:true ~to_kind)
pp_scheme (elim_scheme ~dep:false ~to_kind))
let lookup_eliminator_by_name env ind s =
let r = lookup_eliminator_by_name env ind s in
deprecated_lookup_by_name (env,ind,s,r);
r
let lookup_eliminator env ind s =
let nodep_scheme_first =
let _, mip = Inductive.lookup_mind_specif env ind in
Sorts.is_prop mip.mind_sort && not (is_prop_but_default_dependent_elim ind)
in
let schemes =
List.map (fun dep -> elim_scheme ~dep ~to_kind:s)
(if nodep_scheme_first then [false;true] else [true;false])
in
match List.find_map (fun scheme -> lookup_scheme scheme ind) schemes with
| Some c -> c
| None ->
lookup_eliminator_by_name env ind s
let build_case_analysis_scheme_in_type env dep sort ind =
let sigma = Evd.from_env env in
let (sigma, indu) = Evd.fresh_inductive_instance env sigma ind in
let sigma, sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in
let (sigma, c, _) = build_case_analysis_scheme env sigma indu dep sort in
EConstr.Unsafe.to_constr c, Evd.ustate sigma
let case_dep =
declare_individual_scheme_object "case_dep"
(fun env _ x -> build_case_analysis_scheme_in_type env true QualityOrSet.qtype x)
let case_nodep =
declare_individual_scheme_object "case_nodep"
(fun env _ x -> build_case_analysis_scheme_in_type env false QualityOrSet.qtype x)
let casep_dep =
declare_individual_scheme_object "casep_dep"
(fun env _ x -> build_case_analysis_scheme_in_type env true QualityOrSet.prop x)
let casep_nodep =
declare_individual_scheme_object "casep_nodep"
(fun env _ x -> build_case_analysis_scheme_in_type env false QualityOrSet.prop x)