-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathequtils.ml
221 lines (183 loc) · 5.03 KB
/
equtils.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
209
210
211
212
213
214
215
216
217
218
219
220
221
(*
* Utilities for propositional equality
*)
open Constr
open Names
open Apputils
let coq_init_logic =
ModPath.MPfile
(DirPath.make (List.map Id.of_string ["Logic"; "Init"; "Coq"]))
(* --- Constants --- *)
(* equality *)
let eq : types =
mkInd (MutInd.make1 (KerName.make2 coq_init_logic (Label.make "eq")), 0)
(* Constructor for quality *)
let eq_refl : types =
mkConstruct (fst (destInd eq), 1)
(* Symmetric eliminator for equality *)
let eq_ind_r : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_ind_r"))
(* Eliminator for equality *)
let eq_ind : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_ind"))
(* Symmetric eliminator for equality into type "P : A -> Set" *)
let eq_rec_r : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_rec_r"))
(* Eliminator for equality into type "P : A -> Set" *)
let eq_rec : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_rec"))
(* Symmetric eliminator for equality into type "P : A -> Type" *)
let eq_rect_r : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_rect_r"))
(* Eliminator for equality into type "P : A -> Type" *)
let eq_rect : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_rect"))
(* Symmetry *)
let eq_sym : types =
mkConst (Constant.make2 coq_init_logic (Label.make "eq_sym"))
(* --- Representations --- *)
(*
* An application of eq
*)
type eq_app =
{
at_type : types;
trm1 : types;
trm2 : types;
}
(*
* Make an eq type
*)
let apply_eq (app : eq_app) : types =
mkAppl (eq, [app.at_type; app.trm1; app.trm2])
(*
* Deconstruct an eq type
*)
let dest_eq (trm : types) : eq_app =
let [at_type; trm1; trm2] = unfold_args trm in
{ at_type; trm1; trm2 }
(*
* An application of eq_sym
*)
type eq_sym_app =
{
eq_typ : eq_app;
eq_proof : types;
}
(*
* Make an eq type
*)
let apply_eq_sym (app : eq_sym_app) : types =
let eq_typ = app.eq_typ in
mkAppl (eq_sym, [eq_typ.at_type; eq_typ.trm1; eq_typ.trm2; app.eq_proof])
(*
* Deconstruct an eq type
*)
let dest_eq_sym (trm : types) : eq_sym_app =
let [at_type; trm1; trm2; eq_proof] = unfold_args trm in
let eq_typ = { at_type; trm1; trm2 } in
{ eq_typ; eq_proof }
(*
* An application of eq_ind
*)
type eq_ind_app =
{
at_type : types;
p : types;
trm1 : types;
trm2 : types;
h : types;
b : types;
}
(*
* Apply an eq_ind
*)
let apply_eq_ind (app : eq_ind_app) : types =
mkAppl (eq_ind, [app.at_type; app.trm1; app.p; app.b; app.trm2; app.h])
(*
* Deconstruct an eq_ind
*)
let dest_eq_ind (trm : types) : eq_ind_app =
let [at_type; trm1; p; b; trm2; h] = unfold_args trm in
{ at_type; trm1; p; b; trm2; h }
(*
* An application of eq_refl
*)
type eq_refl_app =
{
typ : types;
trm : types;
}
(*
* Apply an eq_refl
*)
let apply_eq_refl (app : eq_refl_app) : types =
mkAppl (eq_refl, [app.typ; app.trm])
(*
* Deconstruct an eq_refl
*)
let dest_eq_refl (trm : types) : eq_refl_app =
let [typ; trm] = unfold_args trm in
{ typ; trm }
(*
* Deconstruct an eq_refl.
* None on failure, or if not actually an eq_refl.
*)
let dest_eq_refl_opt (trm : types) : eq_refl_app option =
match kind trm with
| App (f, args) ->
if equal f eq_refl && Array.length args == 2 then
Some { typ = args.(0) ; trm = args.(1) }
else
None
| _ -> None
(* --- Questions about constants --- *)
(* Check if a term is eq_ind, eq_rec, or eq_rect *)
let is_rewrite_l (trm : types) : bool =
let eq_term = equal trm in
eq_term eq_ind || eq_term eq_rec || eq_term eq_rect
(* Check if a term is eq_ind_r, eq_rec_r, or eq_rect_r *)
let is_rewrite_r (trm : types) : bool =
let eq_term = equal trm in
eq_term eq_ind_r || eq_term eq_rec_r || eq_term eq_rect_r
(*
* Check if a term is (exactly) a rewrite via eq_ind or eq_ind_r etc.
* Don't consider convertible terms
*)
let is_rewrite (trm : types) : bool =
is_rewrite_l trm || is_rewrite_r trm
(* Information required to perform a rewrite. *)
type rewrite_args = {
a : types;
x : constr;
p : constr;
px : constr;
y : constr;
eq : constr;
params : constr array;
left : bool
}
let rewr_app f app =
let args = [app.a; app.x; app.p; app.px; app.y; app.eq] in
mkAppl (f, args @ Array.to_list app.params)
let apply_rewrite_ind app =
let f = if app.left then eq_ind else eq_ind_r in
rewr_app f app
let apply_rewrite_rec app =
let f = if app.left then eq_rec else eq_rec_r in
rewr_app f app
let apply_rewrite_rect app =
let f = if app.left then eq_rect else eq_rect_r in
rewr_app f app
let dest_rewrite trm : rewrite_args option =
match kind trm with
| App (f, args) ->
if Array.length args >= 6 && is_rewrite f then
let left = is_rewrite_l f in
let params = Array.sub args 6 (Array.length args - 6) in
Some { a = args.(0) ; x = args.(1) ; p = args.(2) ;
px = args.(3) ; y = args.(4) ; eq = args.(5) ;
left = left ; params = params }
else
None
| _ -> None