Skip to content

Commit daa1773

Browse files
felixL-KfelixL-K
authored andcommitted
generalize Scheme to support custom schemes
1 parent cf817af commit daa1773

26 files changed

+698
-424
lines changed

clib/option.ml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,5 +181,14 @@ module List =
181181
| Some y -> y :: aux f l
182182
in
183183
try Some (aux f l) with Exit -> None
184-
184+
185+
let fold_left f init lst =
186+
let rec aux acc = function
187+
| [] -> Some acc
188+
| x :: xs ->
189+
match f acc x with
190+
| None -> None
191+
| Some acc' -> aux acc' xs
192+
in
193+
aux init lst
185194
end

clib/option.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,9 @@ module List : sig
126126
[None] if, for at least one i, [f ai] is [None]. *)
127127
val map : ('a -> 'b option) -> 'a list -> 'b list option
128128

129+
(** [List.fold_left f acc [a1;...;an]] is [Some f (...(f (f init a1) a2)...)an] if
130+
for all i, there is a [bi] such that [f acc ai] is [Some bi]; it is
131+
[None] if, for at least one i, [f acc ai] is [None]. *)
132+
val fold_left : ('acc -> 'b -> 'acc option) -> 'acc -> 'b list -> 'acc option
133+
129134
end

engine/evd.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,11 @@ type evar_flags =
440440
rewrite_rule_evars : Evar.Set.t;
441441
}
442442

443+
(* inductive * (scheme_name * sort * is_mutual *)
443444
type side_effect_role =
444-
| Schema of inductive * string
445+
| Schema of inductive * (string list * UnivGen.QualityOrSet.t option * bool)
445446

447+
(* Schemes already defined but not yet in the global env *)
446448
type side_effects = {
447449
seff_safeenv : Safe_typing.safe_environment option;
448450
(* If seff_safeenv = Some senv, then senv = Global.safe_env + seff_private *)

engine/evd.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,9 @@ val dependent_evar_ident : Evar.t -> evar_map -> Id.t
386386

387387
(** {5 Side-effects} *)
388388

389+
(* inductive * (scheme_name * sort * is_mutual *)
389390
type side_effect_role =
390-
| Schema of inductive * string
391+
| Schema of inductive * (string list * UnivGen.QualityOrSet.t option * bool)
391392

392393
type side_effects
393394

engine/univGen.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,12 @@ let fresh_sort_context_instance ((qs,us),csts) =
234234
(QVar.Map.empty, QVar.Set.empty)
235235
in
236236
(qsubst, usubst), ((qs, us), csts)
237+
238+
let family_to_str = function
239+
| QualityOrSet.Set -> "InSet"
240+
| Qual a -> begin match a with
241+
| Quality.QConstant Quality.QSProp -> "InSProp"
242+
| Quality.QConstant Quality.QProp -> "InProp"
243+
| Quality.QConstant Quality.QType -> "InType"
244+
| Quality.QVar _ -> "InQSort"
245+
end

engine/univGen.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,5 @@ val fresh_sort_context_instance : sort_context_set ->
111111
See Evd.fresh_global, Evarutil.new_global, and pf_constr_of_global for
112112
the proper way to get a fresh copy of a polymorphic global reference. *)
113113
val constr_of_monomorphic_global : env -> GlobRef.t -> constr
114+
115+
val family_to_str : QualityOrSet.t -> string

tactics/declareScheme.ml

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,39 @@
1010

1111
open Names
1212

13+
module Key = struct
14+
15+
type is_mutual = bool
16+
17+
type t = (string list * UnivGen.QualityOrSet.t option * is_mutual)
18+
19+
let compare (a : t) (b : t) =
20+
let a1, a2, a3 = a and b1, b2, b3 = b in
21+
let c = CList.compare String.compare a1 b1 in
22+
if c <> 0 then c
23+
else
24+
let c = Option.compare UnivGen.QualityOrSet.compare a2 b2 in
25+
if c <> 0 then c
26+
else Bool.compare a3 b3
27+
28+
module Self = struct
29+
type nonrec t = t
30+
let compare = compare
31+
end
32+
33+
let equal a b = compare a b = 0
34+
35+
module Set = CSet.Make(Self)
36+
module Map = CMap.Make(Self)
37+
38+
end
39+
1340
let scheme_map = Summary.ref Indmap_env.empty ~name:"Schemes"
1441

1542
let cache_one_scheme kind (ind,const) =
1643
scheme_map := Indmap_env.update ind (function
17-
| None -> Some (CString.Map.singleton kind const)
18-
| Some map -> Some (CString.Map.add kind const map))
44+
| None -> Some (Key.Map.singleton kind const)
45+
| Some map -> Some (Key.Map.add kind const map))
1946
!scheme_map
2047

2148
let cache_scheme (kind,l) =
@@ -28,7 +55,7 @@ let subst_one_scheme subst (ind,const) =
2855
let subst_scheme (subst,(kind,l)) =
2956
(kind, subst_one_scheme subst l)
3057

31-
let inScheme : Libobject.locality * (string * (inductive * Constant.t)) -> Libobject.obj =
58+
let inScheme : Libobject.locality * (Key.t * (inductive * Constant.t)) -> Libobject.obj =
3259
let open Libobject in
3360
declare_object @@ object_with_locality "SCHEME"
3461
~cache:cache_scheme
@@ -38,6 +65,6 @@ let inScheme : Libobject.locality * (string * (inductive * Constant.t)) -> Libob
3865
let declare_scheme local kind indcl =
3966
Lib.add_leaf (inScheme (local,(kind,indcl)))
4067

41-
let lookup_scheme kind ind = CString.Map.find kind (Indmap_env.find ind !scheme_map)
68+
let lookup_scheme kind ind = Key.Map.find kind (Indmap_env.find ind !scheme_map)
4269

4370
let all_schemes () = !scheme_map

tactics/declareScheme.mli

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@
1010

1111
open Names
1212

13-
val declare_scheme : Libobject.locality -> string -> (inductive * Constant.t) -> unit
14-
val lookup_scheme : string -> inductive -> Constant.t
15-
val all_schemes : unit -> Constant.t CString.Map.t Indmap_env.t
13+
module Key : sig
14+
15+
type t = (string list * UnivGen.QualityOrSet.t option * bool)
16+
17+
val equal : t -> t -> bool
18+
19+
module Set : CSet.ExtS with type elt = t
20+
module Map : CMap.ExtS with type key = t and module Set := Set
21+
end
22+
23+
24+
val declare_scheme : Libobject.locality -> Key.t -> (inductive * Constant.t) -> unit
25+
val lookup_scheme : (string list * UnivGen.QualityOrSet.t option * bool) -> inductive -> Constant.t
26+
val all_schemes : unit -> Constant.t Key.Map.t Indmap_env.t

tactics/elimschemes.ml

Lines changed: 148 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,39 +27,134 @@ let build_induction_scheme_in_type env dep sort ind =
2727
let sigma, pind = Evd.fresh_inductive_instance ~rigid:UState.univ_rigid env sigma ind in
2828
let sigma, sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in
2929
let sigma, c = build_induction_scheme env sigma pind dep sort in
30-
EConstr.to_constr sigma c, Evd.ustate sigma
30+
Some (EConstr.to_constr sigma c, Evd.ustate sigma)
31+
32+
let build_mutual_induction_scheme_in_type env dep sort isrec l =
33+
let ind,_ = match l with | x::_ -> x | [] -> assert false in
34+
let sigma, inst =
35+
let _, ctx = Typeops.type_of_global_in_context env (Names.GlobRef.IndRef (ind,0)) in
36+
let u, ctx = UnivGen.fresh_instance_from ctx None in
37+
let u = EConstr.EInstance.make u in
38+
let sigma = Evd.from_ctx (UState.of_context_set ctx) in
39+
sigma, u
40+
in
41+
let n = List.length l in
42+
let sigma, lrecspec =
43+
let rec loop i n sigma ll =
44+
if i>=n then (sigma,ll)
45+
else
46+
let new_sigma, new_sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in
47+
let (indd,ii) = List.nth l i in
48+
let new_l = List.append ll [(((indd,ii),inst),dep,new_sort)] in
49+
loop (i + 1) n new_sigma new_l
50+
in
51+
loop 0 n sigma []
52+
in
53+
let sigma, listdecl =
54+
if isrec then Indrec.build_mutual_induction_scheme env sigma ~force_mutual:false lrecspec
55+
else
56+
List.fold_left_map (fun sigma (ind,dep,sort) ->
57+
let sigma, c = Indrec.build_case_analysis_scheme env sigma ind dep sort in
58+
let c, _ = Indrec.eval_case_analysis c in
59+
sigma, c)
60+
sigma lrecspec
61+
in
62+
let array = Array.of_list listdecl in
63+
let l = Array.map (fun x -> EConstr.to_constr sigma x) array in
64+
Some (l, Evd.ustate sigma)
65+
66+
let make_suff_sort one_ind suff dep =
67+
match one_ind with
68+
| None -> suff
69+
| Some i ->
70+
let sort = i.mind_sort
71+
in
72+
match sort with
73+
| Prop -> if dep then (Names.Id.to_string i.mind_typename) ^ "_" ^ suff ^ "_dep"
74+
else (Names.Id.to_string i.mind_typename) ^ "_" ^ suff
75+
| Type _ | SProp | Set -> if dep then (Names.Id.to_string i.mind_typename) ^ "_" ^ suff
76+
else (Names.Id.to_string i.mind_typename) ^ "_" ^ suff ^ "_nodep"
77+
| QSort _ -> (Names.Id.to_string i.mind_typename) ^ "_" ^ suff
3178

3279
let rect_dep =
33-
declare_individual_scheme_object "rect_dep"
34-
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.qtype x)
80+
declare_individual_scheme_object (["Induction"], Some QualityOrSet.qtype)
81+
(fun id -> make_suff_sort id "rect" true)
82+
(fun env _ x _ -> build_induction_scheme_in_type env true QualityOrSet.qtype x)
83+
84+
let mutual_rect_dep =
85+
declare_mutual_scheme_object (["Induction"], Some QualityOrSet.qtype)
86+
(fun id -> make_suff_sort id "rect" true)
87+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env true QualityOrSet.qtype true x)
3588

3689
let rec_dep =
37-
declare_individual_scheme_object "rec_dep"
38-
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.set x)
90+
declare_individual_scheme_object (["Induction"], Some QualityOrSet.set)
91+
(fun id -> make_suff_sort id "rec" true)
92+
(fun env _ x _ -> build_induction_scheme_in_type env true QualityOrSet.set x)
93+
94+
let mutual_rec_dep =
95+
declare_mutual_scheme_object (["Induction"], Some QualityOrSet.set)
96+
(fun id -> make_suff_sort id "rec" true)
97+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env true QualityOrSet.set true x)
3998

4099
let ind_dep =
41-
declare_individual_scheme_object "ind_dep"
42-
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.prop x)
100+
declare_individual_scheme_object (["Induction"], Some QualityOrSet.prop)
101+
(fun id -> make_suff_sort id "ind" true)
102+
(fun env _ x _ -> build_induction_scheme_in_type env true QualityOrSet.prop x)
103+
104+
let mutual_ind_dep =
105+
declare_mutual_scheme_object (["Induction"], Some QualityOrSet.prop)
106+
(fun id -> make_suff_sort id "ind" true)
107+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env true QualityOrSet.prop true x)
43108

44109
let sind_dep =
45-
declare_individual_scheme_object "sind_dep"
46-
(fun env _ x -> build_induction_scheme_in_type env true QualityOrSet.sprop x)
110+
declare_individual_scheme_object (["Induction"], Some QualityOrSet.sprop)
111+
(fun id -> make_suff_sort id "inds" true)
112+
(fun env _ x _ -> build_induction_scheme_in_type env true QualityOrSet.sprop x)
113+
114+
let mutual_sind_dep =
115+
declare_mutual_scheme_object (["Induction"], Some QualityOrSet.sprop)
116+
(fun id -> make_suff_sort id "inds" true)
117+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env true QualityOrSet.sprop true x)
47118

48119
let rect_nodep =
49-
declare_individual_scheme_object "rect_nodep"
50-
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.qtype x)
120+
declare_individual_scheme_object (["Minimality"], Some QualityOrSet.qtype)
121+
(fun id -> make_suff_sort id "rect" false)
122+
(fun env _ x _ -> build_induction_scheme_in_type env false QualityOrSet.qtype x)
123+
124+
let mutual_rect_nodep =
125+
declare_mutual_scheme_object (["Minimality"], Some QualityOrSet.qtype)
126+
(fun id -> make_suff_sort id "rect" false)
127+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env false QualityOrSet.qtype true x)
51128

52129
let rec_nodep =
53-
declare_individual_scheme_object "rec_nodep"
54-
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.set x)
130+
declare_individual_scheme_object (["Minimality"], Some QualityOrSet.set)
131+
(fun id -> make_suff_sort id "rec" false)
132+
(fun env _ x _ -> build_induction_scheme_in_type env false QualityOrSet.set x)
133+
134+
let mutual_rec_nodep =
135+
declare_mutual_scheme_object (["Minimality"], Some QualityOrSet.set)
136+
(fun id -> make_suff_sort id "rec" false)
137+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env false QualityOrSet.set true x)
55138

56139
let ind_nodep =
57-
declare_individual_scheme_object "ind_nodep"
58-
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.prop x)
140+
declare_individual_scheme_object (["Minimality"], Some QualityOrSet.prop)
141+
(fun id -> make_suff_sort id "ind" false)
142+
(fun env _ x _ -> build_induction_scheme_in_type env false QualityOrSet.prop x)
143+
144+
let mutual_ind_nodep =
145+
declare_mutual_scheme_object (["Minimality"], Some QualityOrSet.prop)
146+
(fun id -> make_suff_sort id "ind" false)
147+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env false QualityOrSet.prop true x)
59148

60149
let sind_nodep =
61-
declare_individual_scheme_object "sind_nodep"
62-
(fun env _ x -> build_induction_scheme_in_type env false QualityOrSet.sprop x)
150+
declare_individual_scheme_object (["Minimality"], Some QualityOrSet.sprop)
151+
(fun id -> make_suff_sort id "inds" false)
152+
(fun env _ x _ -> build_induction_scheme_in_type env false QualityOrSet.sprop x)
153+
154+
let mutual_sind_nodep =
155+
declare_mutual_scheme_object (["Minimality"], Some QualityOrSet.sprop)
156+
(fun id -> make_suff_sort id "inds" false)
157+
(fun env _ x _ -> build_mutual_induction_scheme_in_type env false QualityOrSet.sprop true x)
63158

64159
let elim_scheme ~dep ~to_kind =
65160
let open QualityOrSet in
@@ -118,7 +213,7 @@ let lookup_eliminator_by_name env ind_sp s =
118213
let deprecated_lookup_by_name =
119214
CWarnings.create ~name:"deprecated-lookup-elim-by-name" ~category:Deprecation.Version.v9_1
120215
Pp.(fun (env,ind,to_kind,r) ->
121-
let pp_scheme () s = str (scheme_kind_name s) in
216+
let pp_scheme () s = str (match scheme_kind_name s with (ss,_,_) -> String.concat " " ss) in
122217
fmt "Found unregistered eliminator %t for %t by name.@ \
123218
Use \"Register Scheme\" with it instead@ \
124219
(\"as %a\" if dependent or \"as %a\" if non dependent)."
@@ -156,20 +251,44 @@ let build_case_analysis_scheme_in_type env dep sort ind =
156251
let sigma, sort = Evd.fresh_sort_in_quality ~rigid:UnivRigid sigma sort in
157252
let (sigma, c) = build_case_analysis_scheme env sigma indu dep sort in
158253
let (c, _) = Indrec.eval_case_analysis c in
159-
EConstr.Unsafe.to_constr c, Evd.ustate sigma
254+
Some (EConstr.Unsafe.to_constr c, Evd.ustate sigma)
160255

161256
let case_dep =
162-
declare_individual_scheme_object "case_dep"
163-
(fun env _ x -> build_case_analysis_scheme_in_type env true QualityOrSet.qtype x)
164-
165-
let case_nodep =
166-
declare_individual_scheme_object "case_nodep"
167-
(fun env _ x -> build_case_analysis_scheme_in_type env false QualityOrSet.qtype x)
257+
declare_individual_scheme_object (["Elimination"], Some QualityOrSet.qtype)
258+
(fun id -> make_suff_sort id "caset" true)
259+
(fun env _ x _ -> build_case_analysis_scheme_in_type env true QualityOrSet.qtype x)
168260

169261
let casep_dep =
170-
declare_individual_scheme_object "casep_dep"
171-
(fun env _ x -> build_case_analysis_scheme_in_type env true QualityOrSet.prop x)
262+
declare_individual_scheme_object (["Elimination"], Some QualityOrSet.prop)
263+
(fun id -> make_suff_sort id "case" true)
264+
(fun env _ x _ -> build_case_analysis_scheme_in_type env true QualityOrSet.prop x)
265+
266+
let cases_dep =
267+
declare_individual_scheme_object (["Elimination"], Some QualityOrSet.sprop)
268+
(fun id -> make_suff_sort id "cases" true)
269+
(fun env _ x _ -> build_case_analysis_scheme_in_type env true QualityOrSet.sprop x)
270+
271+
let casep_dep_set =
272+
declare_individual_scheme_object (["Elimination"], Some QualityOrSet.set)
273+
(fun id -> make_suff_sort id "case" true)
274+
(fun env _ x _ -> build_case_analysis_scheme_in_type env true QualityOrSet.set x)
275+
276+
let case_nodep =
277+
declare_individual_scheme_object (["Case"], Some QualityOrSet.qtype)
278+
(fun id -> make_suff_sort id "caset" false)
279+
(fun env _ x _ -> build_case_analysis_scheme_in_type env false QualityOrSet.qtype x)
172280

173281
let casep_nodep =
174-
declare_individual_scheme_object "casep_nodep"
175-
(fun env _ x -> build_case_analysis_scheme_in_type env false QualityOrSet.prop x)
282+
declare_individual_scheme_object (["Case"], Some QualityOrSet.prop)
283+
(fun id -> make_suff_sort id "case" false)
284+
(fun env _ x _ -> build_case_analysis_scheme_in_type env false QualityOrSet.prop x)
285+
286+
let cases_nodep =
287+
declare_individual_scheme_object (["Case"], Some QualityOrSet.sprop)
288+
(fun id -> make_suff_sort id "cases" false)
289+
(fun env _ x _ -> build_case_analysis_scheme_in_type env false QualityOrSet.sprop x)
290+
291+
let case_nodep_set =
292+
declare_individual_scheme_object (["Case"], Some QualityOrSet.set)
293+
(fun id -> make_suff_sort id "case" false)
294+
(fun env _ x _ -> build_case_analysis_scheme_in_type env false QualityOrSet.set x)

tactics/elimschemes.mli

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,27 @@ open Ind_tables
1414

1515
val elim_scheme : dep:bool -> to_kind:UnivGen.QualityOrSet.t -> individual scheme_kind
1616

17+
val mutual_rect_dep : mutual scheme_kind
18+
val mutual_rec_dep : mutual scheme_kind
19+
val mutual_ind_dep : mutual scheme_kind
20+
val mutual_sind_dep : mutual scheme_kind
21+
val mutual_rect_nodep : mutual scheme_kind
22+
val mutual_rec_nodep : mutual scheme_kind
23+
val mutual_ind_nodep : mutual scheme_kind
24+
val mutual_sind_nodep : mutual scheme_kind
25+
1726
(** Case analysis schemes *)
1827

1928
val case_dep : individual scheme_kind
2029
val case_nodep : individual scheme_kind
2130
val casep_dep : individual scheme_kind
2231
val casep_nodep : individual scheme_kind
2332

33+
val cases_dep : individual scheme_kind
34+
val cases_nodep : individual scheme_kind
35+
val casep_dep_set : individual scheme_kind
36+
val case_nodep_set : individual scheme_kind
37+
2438
(** Recursor names utilities *)
2539

2640
val lookup_eliminator : Environ.env -> Names.inductive -> UnivGen.QualityOrSet.t -> Names.GlobRef.t

0 commit comments

Comments
 (0)