aboutsummaryrefslogtreecommitdiffhomepage
path: root/hol-light/TacticRecording/wrappers.ml
blob: 115163d43e8f012899f22aba94924edd414f4bbf (plain)
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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
(* ========================================================================== *)
(* WRAPPER FUNCTIONS (HOL LIGHT)                                              *)
(* - Functions for promoting thm/goal-related ML objects for xthm/xgoal       *)
(*                                                                            *)
(* By Mark Adams                                                              *)
(* Copyright (c) Univeristy of Edinburgh, 2011-2012                           *)
(* ========================================================================== *)



(* ** THEOREM-RELATED WRAPPER FUNCTIONS ** *)


(* mldata_as_meta_arg *)

let mldata_as_meta_arg (obj:mldata) =
  match obj with
    (x, ((_::_) as args))
       -> Mlfn (x, front args)
  | _  -> failwith "mldata_as_meta_arg: Unexpected empty rule arg list";;

let mldata_as_meta2_arg (obj:mldata) =
  match obj with
    (x, ((_::_) as args))
       -> Mlfn (x, (front o front) args)
  | _  -> failwith "mldata_as_meta_arg: Unexpected empty rule arg list";;


(* detect_rule_app *)

(* Based on the assumption that the given meta function actually executes its *)
(* rule argument at some point, this utility detects such an execution during *)
(* the demotion of a given xrule argument to a rule.  The meta function's     *)
(* result is returned along with an 'farg' that captures the rule.            *)

let detect_rule_app (mfunc:('a->thm)->'b) (xr:'a->xthm) : 'c =
  let temp = ref (Mlfn ("<rule>", []) : mlarg) in
  let r arg = let xth = xr arg in
              let (th,obj) = dest_xthm xth in
              (temp := mldata_as_meta_arg obj;
               th) in
  let th = mfunc r in
  (th,!temp);;

let detect_metarule_app (mfunc:(('a->thm)->'b->thm)->'c)
                        (xmr:('a->xthm)->'b->xthm) : 'd =
  let temp = ref (Mlfn ("<meta-rule>",[]) : mlarg) in
  let mr marg arg = let xmarg arg0 =
                       let th = marg arg0 in
                       let obj = ("<rule>", [Mlfn ("<arg>",[])]) in
                       mk_xthm (th,obj) in
                    let xth = xmr xmarg arg in
                    let (th,obj) = dest_xthm xth in
                    (temp := mldata_as_meta2_arg obj;
                     th) in
  let th = mfunc mr in
  (th,!temp);;


(* Theorem wrapper *)

let theorem_wrap (x:string) (th:thm) : xthm =
  (th, (x,[]));;


(* Rule wrappers *)

(* Lots of rule wrappers are required because there are many different type   *)
(* shapes for rules.                                                          *)

let rule_wrap0 obj (r:'a->thm) (arg:'a) : xthm =
  let th' = r arg in
  mk_xthm (th',obj);;

let conv_wrap x (r:term->thm) (tm:term) : xthm =
  rule_wrap0 (x, [Mlterm tm]) r tm;;

let thm_conv_wrap x (r:thm->term->thm) (xth:xthm) tm : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mlthm prf; Mlterm tm]) (r th) tm;;

let thmlist_conv_wrap x (r:thm list->term->thm) xths (tm:term) : xthm =
  let (ths,prfs) = unzip (map dest_xthm xths) in
  rule_wrap0 (x, [Mllist (map (fun prf -> Mlthm prf) prfs); Mlterm tm])
             (r ths) tm;;

let rule_wrap x (r:thm->thm) (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mlthm prf]) r th;;

let drule_wrap x (r:thm->thm->thm) (xth1:xthm) (xth2:xthm) : xthm =
  let (th1,prf1) = dest_xthm xth1 in
  let (th2,prf2) = dest_xthm xth2 in
  rule_wrap0 (x, [Mlthm prf1; Mlthm prf2]) (r th1) th2;;

let prule_wrap x (r:thm*thm->thm) ((xth1:xthm),(xth2:xthm)) : xthm =
  let (th1,prf1) = dest_xthm xth1 in
  let (th2,prf2) = dest_xthm xth2 in
  rule_wrap0 (x, [Mlpair(Mlthm prf1, Mlthm prf2)]) r (th1,th2);;

let trule_wrap x (r:thm->thm->thm->thm)
                 (xth1:xthm) (xth2:xthm) (xth3:xthm) : xthm =
  let (th1,prf1) = dest_xthm xth1 in
  let (th2,prf2) = dest_xthm xth2 in
  let (th3,prf3) = dest_xthm xth3 in
  rule_wrap0 (x, [Mlthm prf1; Mlthm prf2; Mlthm prf3]) (r th1 th2) th3;;

let term_rule_wrap x (r:term->thm->thm) tm (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mlterm tm; Mlthm prf]) (r tm) th;;

let termpair_rule_wrap x (r:term*term->thm->thm) (tm1,tm2) (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mlpair(Mlterm tm1,Mlterm tm2); Mlthm prf]) (r (tm1,tm2)) th;;

let termthmpair_rule_wrap x (r:term*thm->thm->thm) (tm,xth0) (xth:xthm) : xthm =
  let (th0,prf0) = dest_xthm xth0 in
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mlpair(Mlterm tm, Mlthm prf0); Mlthm prf]) (r (tm,th0)) th;;

let termlist_rule_wrap x (r:term list->thm->thm) tms (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mllist (map (fun tm -> Mlterm tm) tms); Mlthm prf])
             (r tms) th;;

let terminst_rule_wrap x (r:(term*term)list->thm->thm) theta (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x,
              [Mllist (map (fun (tm1,tm2) -> Mlpair(Mlterm tm1, Mlterm tm2))
                           theta);
               Mlthm prf])
             (r theta) th;;

let typeinst_rule_wrap x (r:(hol_type*hol_type)list->thm->thm)
                         theta (xth:xthm) : xthm =
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x,
              [Mllist (map (fun (tm1,tm2) -> Mlpair(Mltype tm1, Mltype tm2))
                           theta);
               Mlthm prf])
             (r theta) th;;

let thmlist_rule_wrap x (r:thm list->thm->thm) xths (xth:xthm) : xthm =
  let (ths,prfs) = unzip (map dest_xthm xths) in
  let (th,prf) = dest_xthm xth in
  rule_wrap0 (x, [Mllist (map (fun prf -> Mlthm prf) prfs); Mlthm prf])
             (r ths) th;;


(* Multi-rule wrappers *)

let multirule_wrap0 obj (r:'a->thm list) (arg:'a) : xthm list =
  let ths' = r arg in
  let n = length ths' in
  let infos' = map (fun i -> ("el", [Mlint i; Mlfn obj])) (0 -- (n-1)) in
  map mk_xthm (zip ths' infos');; 

let multirule_wrap x (r:thm->thm list) (xth:xthm) : xthm list =
  let (th,prf) = dest_xthm xth in
  multirule_wrap0 (x, [Mlthm prf]) r th;;


(* Meta rule wrappers *)

let meta_rule_wrap0 info0 (mr:('a->thm)->'b->thm)
                          (xr:'a->xthm) (arg:'b) : xthm =
  let (th',f) = detect_rule_app (fun r -> mr r arg) xr in
  let (x,args0) = info0 in
  let obj' = (x, f::args0) in
  (th',obj');;

let conv_conv_wrap x (mc:conv->conv) (xc:term->xthm) (tm:term) : xthm =
  meta_rule_wrap0 (x, [Mlterm tm]) mc xc tm;;



(* ** TACTIC-RELATED WRAPPER FUNCTIONS ** *)

(* These functions are for promoting existing tactics and tacticals.          *)


(* Generic basic wrapper util *)

(* Applies a tactic and incorproates the results into the goal tree.  Takes   *)
(* an "infotactic", i.e. like a normal tactic that works on 'goal' and        *)
(* returns 'goalstate', but that also returns a 'gstep' summary of the        *)
(* operation.  This is used to promote every basic tactic-based function.     *)

let infotactic_wrap (infotac:goal->goalstate*mldata) (xg:xgoal) : xgoalstate =
  let (g,id) = dest_xgoal xg in
  let ((meta,gs,just),obj) = infotac g in
  let xgs = extend_gtree id (Gatom obj) gs in
  (meta,xgs,just);;


(* Generic box wrapper util *)

(* Sets up a box to apply an xtactic within, applies the xtactic (which       *)
(* incorporates itself into the goal tree) and wires up the resulting         *)
(* subgoals to external subgoals of the box.  Note that this is not quite     *)
(* generic enough for 'SUBGOAL_THEN' (because there is not a total surjection *)
(* between internal and external goals).                                      *)

let infobox_wrap (xinfotac:xgoal->xgoalstate*label) (xg:xgoal) : xgoalstate =
  let (g,id) = dest_xgoal xg in
  let (id0,gtr0) = new_active_subgtree id g in
  let xg0 = mk_xgoal (g,id0) in
  let ((meta,xgs0,just),l) = xinfotac xg0 in
  let (gs0,ids0) = unzip (map dest_xgoal xgs0) in
  let xgs = extend_gtree id (Gbox (l,gtr0,false)) gs0 in
  let ids = map xgoal_id xgs in
  (do_list externalise_gtree (zip ids0 ids);
   (meta,xgs,just));;


(* Tactic wrapper *)

(* This is for wrapping around a tactic, to promote it to work on xgoals and  *)
(* incorporate the results into an existing gtree.                            *)

let tactic_wrap0 obj (tac:tactic) : xtactic =
  let infotac g = (tac g, obj) in
  infotactic_wrap infotac;;

let tactic_wrap x tac =
  tactic_wrap0 (x, []) tac;;

let string_tactic_wrap x (tac:string->tactic) (s:string) : xtactic =
  tactic_wrap0 (x, [Mlstring s]) (tac s);;

let term_tactic_wrap x (tac:term->tactic) (tm:term) : xtactic =
  tactic_wrap0 (x, [Mlterm tm]) (tac tm);;

let termpair_tactic_wrap x (tac:term*term->tactic) (tm1,tm2) : xtactic =
  tactic_wrap0 (x, [Mlpair (Mlterm tm1, Mlterm tm2)]) (tac (tm1,tm2));;

let termlist_tactic_wrap x (tac:term list->tactic) tms : xtactic =
  tactic_wrap0 (x, [Mllist (map (fun tm -> Mlterm tm) tms)]) (tac tms);;

let thm_tactic_wrap x (tac:thm->tactic) (xth:xthm) : xtactic =
  let (th,prf) = dest_xthm xth in
  tactic_wrap0 (x, [Mlthm prf]) (tac th);;

let thmlist_tactic_wrap x (tac:thm list->tactic) (xths:xthm list) : xtactic =
  let (ths,prfs) = unzip (map dest_xthm xths) in
  tactic_wrap0 (x, [Mllist (map (fun prf -> Mlthm prf) prfs)]) (tac ths);;

let stringthm_tactic_wrap x (tac:string->thm->tactic) s (xth:xthm) : xtactic =
  let (th,prf) = dest_xthm xth in
  tactic_wrap0 (x, [Mlstring s; Mlthm prf]) (tac s th);;


(* Meta-tactic wrapper *)

(* For tactics that take rule arguments.                                      *)

let meta_tactic_wrap0 info0 (mtac:('a->thm)->tactic)
                            (xr:'a->xthm) : xtactic =
  let infotac g =
     let (gst,f) = detect_rule_app (fun r -> mtac r g) xr in
     let (x,args0) = info0 in
     let obj = (x, f::args0) in
     (gst,obj) in
  infotactic_wrap infotac;;

let conv_tactic_wrap x (mtac:conv->tactic) (xc:xconv) : xtactic =
  meta_tactic_wrap0 (x, []) mtac xc;;

let metameta_tactic_wrap info0 (mmtac:(('a->thm)->'b->thm)->tactic)
                               (xmr:('a->xthm)->'b->xthm) : xtactic =
  let infotac g =
     let (gst,f) = detect_metarule_app (fun mr -> mmtac mr g) xmr in
     let (x,args0) = info0 in
     let obj = (x, f::args0) in
     (gst,obj) in
  infotactic_wrap infotac;;

let convconvthmlist_tactic_wrap x (mmtac:(conv->conv)->thm list->tactic)
                                 (xmc:xconv->xconv) (xths:xthm list) : xtactic =
  let (ths,prfs) = unzip (map dest_xthm xths) in
  metameta_tactic_wrap (x, [Mllist (map (fun prf -> Mlthm prf) prfs)])
                       (fun mc -> mmtac mc ths)
                       xmc;;


(* Tactical wrapper *)

(* This is for wrapping around a tactical, to incorporate the results into a  *)
(* box in an existing gtree, where the execution of the tactical's tactics is *)
(* captured inside the box, so that they can be stepped through and/or        *)
(* refactored.  Thus we cannot take the tactical as a black box; it must      *)
(* already be promoted to work with xtactics and xgoals.  This must done by   *)
(* hand for each tactical by trivially adjusting its original source code.    *)

let tactical_wrap0 obj (xttcl:'a->xtactic) (arg:'a) : xtactic =
  let xinfotac xg = (xttcl arg xg, Tactical obj) in
  infobox_wrap xinfotac;;

let tactical_wrap x (xttcl:'a->xtactic) (xtac:'a) : xtactic =
  tactical_wrap0 (x,[]) xttcl xtac;;

let btactical_wrap x (xttcl:'a->'b->xtactic) (xtac1:'a) (xtac2:'b) : xtactic =
  tactical_wrap0 (x,[]) (xttcl xtac1) xtac2;;

let int_tactical_wrap x (xttcl:int->'a->xtactic) (n:int) (xtac:'a) : xtactic =
  tactical_wrap0 (x, [Mlint n]) (xttcl n) xtac;;

let list_tactical_wrap x (xttcl:('a->xtactic)->'a list->xtactic)
                         (xtac:'a->xtactic) (l:'a list) : xtactic =
  tactical_wrap0 (x,[]) (xttcl xtac) l;;


(* HILABEL *)

(* Command for putting the result of a tactic into a box and giving the box a *)
(* label (distinct from a tactical label).                                    *)

let HILABEL x (xtac:xtactic) : xtactic =
  let xinfotac xg = (xtac xg, Label x) in
  infobox_wrap xinfotac;;


(* xSUBGOAL_THEN - seems to be a special case *)

let xASSUME = conv_wrap "ASSUME" ASSUME;;

let xSUBGOAL_THEN (tm:term) (ttac:xthm_tactic) (xg:xgoal) : xgoalstate =
  let arg = xASSUME tm in

  let (g,id) = dest_xgoal xg in
  let (id0,gtr0) = new_active_subgtree id g in
  let xg0 = mk_xgoal (g,id0) in
  let (meta,xgs0,just) = ttac arg xg0 in

  let (asl,_) = g in
  let g2 = (asl,tm) in
  let obj = ("SUBGOAL_THEN",
               [Mlterm tm; (mldata_as_meta_arg o gtree_tactic) gtr0]) in

  let (gs0,ids0) = unzip (map dest_xgoal xgs0) in
  let xgs = extend_gtree id (Gbox (Tactical obj, gtr0, true)) (g2::gs0) in
  let ids1 = map xgoal_id (tl xgs) in
  let just' = fun i l -> PROVE_HYP (hd l) (just i (tl l)) in
  (do_list externalise_gtree (zip ids0 ids1);
   (meta,xgs,just'));;


(*
let SUBGOAL_TAC s tm prfs =
  match prfs with
   p::ps -> (warn (ps <> []) "SUBGOAL_TAC: additional subproofs ignored";
             SUBGOAL_THEN tm (LABEL_TAC s) THENL [p; ALL_TAC])
  | [] -> failwith "SUBGOAL_TAC: no subproof given";;

let (FREEZE_THEN :thm_tactical) =
  fun ttac th (asl,w) ->
    let meta,gl,just = ttac (ASSUME(concl th)) (asl,w) in
    meta,gl,fun i l -> PROVE_HYP th (just i l);;
*)