1 (* ========================================================================= *)
2 (* Simplification and rewriting. *)
4 (* John Harrison, University of Cambridge Computer Laboratory *)
6 (* (c) Copyright, University of Cambridge 1998 *)
7 (* (c) Copyright, John Harrison 1998-2007 *)
8 (* ========================================================================= *)
12 (* ------------------------------------------------------------------------- *)
13 (* Generalized conversion (conversion plus a priority). *)
14 (* ------------------------------------------------------------------------- *)
16 type gconv = int * conv;;
18 (* ------------------------------------------------------------------------- *)
19 (* Primitive rewriting conversions: unconditional and conditional equations. *)
20 (* ------------------------------------------------------------------------- *)
22 let REWR_CONV = PART_MATCH lhs;;
24 let IMP_REWR_CONV = PART_MATCH (lhs o snd o dest_imp);;
26 (* ------------------------------------------------------------------------- *)
27 (* Versions with ordered rewriting. We must have l' > r' for the rewrite *)
28 (* |- l = r (or |- c ==> (l = r)) to apply. *)
29 (* ------------------------------------------------------------------------- *)
31 let ORDERED_REWR_CONV ord th =
32 let basic_conv = REWR_CONV th in
34 let thm = basic_conv tm in
35 let l,r = dest_eq(concl thm) in
37 else failwith "ORDERED_REWR_CONV: wrong orientation";;
39 let ORDERED_IMP_REWR_CONV ord th =
40 let basic_conv = IMP_REWR_CONV th in
42 let thm = basic_conv tm in
43 let l,r = dest_eq(rand(concl thm)) in
45 else failwith "ORDERED_IMP_REWR_CONV: wrong orientation";;
47 (* ------------------------------------------------------------------------- *)
48 (* Standard AC-compatible term ordering: a "dynamic" lexicographic ordering. *)
50 (* This is a slight hack to make AC normalization work. However I *think* *)
51 (* it's properly AC compatible, i.e. monotonic and total, WF on ground terms *)
52 (* (over necessarily finite signature) and with the properties for any *)
53 (* binary operator +: *)
55 (* (x + y) + z > x + (y + z) *)
56 (* x + y > y + x iff x > y *)
57 (* x + (y + z) > y + (x + z) iff x > y *)
59 (* The idea is that when invoking lex ordering with identical head operator *)
60 (* "f", one sticks "f" at the head of an otherwise arbitrary ordering on *)
61 (* subterms (the built-in CAML one). This avoids the potentially inefficient *)
62 (* calculation of term size in the standard orderings. *)
63 (* ------------------------------------------------------------------------- *)
66 let rec lexify ord l1 l2 =
68 else if l2 = [] then true else
69 let h1 = hd l1 and h2 = hd l2 in
70 ord h1 h2 or (h1 = h2 & lexify ord (tl l1) (tl l2)) in
71 let rec dyn_order top tm1 tm2 =
72 let f1,args1 = strip_comb tm1
73 and f2,args2 = strip_comb tm2 in
75 lexify (dyn_order f1) args1 args2
77 if f2 = top then false
78 else if f1 = top then true
82 (* ------------------------------------------------------------------------- *)
83 (* Create a gconv net for a theorem as a (cond) rewrite. The "rep" flag *)
84 (* will cause any trivially looping rewrites to be modified, and any that *)
85 (* are permutative to be ordered w.r.t. the standard order. The idea is that *)
86 (* this flag will be set iff the conversion is going to get repeated. *)
87 (* This includes a completely ad hoc but useful special case for ETA_AX, *)
88 (* which forces a first order match (otherwise it would loop on a lambda). *)
89 (* ------------------------------------------------------------------------- *)
91 let net_of_thm rep th =
93 let lconsts = freesl (hyp th) in
94 let matchable = can o term_match lconsts in
96 Comb(Comb(Const("=",_),(Abs(x,Comb(Var(s,ty) as v,x')) as l)),v')
97 when x' = x & v' = v & not(x = v) ->
100 Abs(y,Comb(t,y')) when y = y' & not(free_in y t) ->
101 INSTANTIATE(term_match [] v t) th
102 | _ -> failwith "REWR_CONV (ETA_AX special case)" in
103 enter lconsts (l,(1,conv))
104 | Comb(Comb(Const("=",_),l),r) ->
105 if rep & free_in l r then
106 let th' = EQT_INTRO th in
107 enter lconsts (l,(1,REWR_CONV th'))
108 else if rep & matchable l r & matchable r l then
109 enter lconsts (l,(1,ORDERED_REWR_CONV term_order th))
110 else enter lconsts (l,(1,REWR_CONV th))
111 | Comb(Comb(_,t),Comb(Comb(Const("=",_),l),r)) ->
112 if rep & free_in l r then
113 let th' = DISCH t (EQT_INTRO(UNDISCH th)) in
114 enter lconsts (l,(3,IMP_REWR_CONV th'))
115 else if rep & matchable l r & matchable r l then
116 enter lconsts (l,(3,ORDERED_IMP_REWR_CONV term_order th))
117 else enter lconsts(l,(3,IMP_REWR_CONV th));;
119 (* ------------------------------------------------------------------------- *)
120 (* Create a gconv net for a conversion with a term index. *)
121 (* ------------------------------------------------------------------------- *)
123 let net_of_conv tm conv sofar =
124 enter [] (tm,(2,conv)) sofar;;
126 (* ------------------------------------------------------------------------- *)
127 (* Create a gconv net for a congruence rule (in canonical form!) *)
128 (* ------------------------------------------------------------------------- *)
130 let net_of_cong th sofar =
131 let conc,n = repeat (fun (tm,m) -> snd(dest_imp tm),m+1) (concl th,0) in
132 if n = 0 then failwith "net_of_cong: Non-implicational congruence" else
133 let pat = lhs conc in
134 let conv = GEN_PART_MATCH (lhand o funpow n rand) th in
135 enter [] (pat,(4,conv)) sofar;;
137 (* ------------------------------------------------------------------------- *)
138 (* Rewrite maker for ordinary and conditional rewrites (via "cf" flag). *)
140 (* We follow Don in going from ~(s = t) to (s = t) = F *and* (t = s) = F. *)
141 (* Well, why not? However, we don't abandon s = t where FV(t) is not a *)
142 (* subset of FV(s) in favour of (s = t) = T, as he does. *)
143 (* Note: looping rewrites are not discarded here, only when netted. *)
144 (* ------------------------------------------------------------------------- *)
147 let IMP_CONJ_CONV = REWR_CONV(ITAUT `p ==> q ==> r <=> p /\ q ==> r`)
148 and IMP_EXISTS_RULE =
149 let cnv = REWR_CONV(ITAUT `(!x. P x ==> Q) <=> (?x. P x) ==> Q`) in
150 fun v th -> CONV_RULE cnv (GEN v th) in
151 let collect_condition oldhyps th =
152 let conds = subtract (hyp th) oldhyps in
153 if conds = [] then th else
154 let jth = itlist DISCH conds th in
155 let kth = CONV_RULE (REPEATC IMP_CONJ_CONV) jth in
156 let cond,eqn = dest_imp(concl kth) in
157 let fvs = subtract (subtract (frees cond) (frees eqn)) (freesl oldhyps) in
158 itlist IMP_EXISTS_RULE fvs kth in
159 let rec split_rewrites oldhyps cf th sofar =
162 split_rewrites oldhyps cf (SPEC_ALL th) sofar
163 else if is_conj tm then
164 split_rewrites oldhyps cf (CONJUNCT1 th)
165 (split_rewrites oldhyps cf (CONJUNCT2 th) sofar)
166 else if is_imp tm & cf then
167 split_rewrites oldhyps cf (UNDISCH th) sofar
168 else if is_eq tm then
169 (if cf then collect_condition oldhyps th else th)::sofar
170 else if is_neg tm then
171 let ths = split_rewrites oldhyps cf (EQF_INTRO th) sofar in
173 then split_rewrites oldhyps cf (EQF_INTRO (GSYM th)) ths
176 split_rewrites oldhyps cf (EQT_INTRO th) sofar in
177 fun cf th sofar -> split_rewrites (hyp th) cf th sofar;;
179 (* ------------------------------------------------------------------------- *)
180 (* Rewriting (and application of other conversions) based on a convnet. *)
181 (* ------------------------------------------------------------------------- *)
183 let REWRITES_CONV net tm =
184 let pconvs = lookup tm net in
185 try tryfind (fun (_,cnv) -> cnv tm) pconvs
186 with Failure _ -> failwith "REWRITES_CONV";;
188 (* ------------------------------------------------------------------------- *)
189 (* Decision procedures may accumulate their state in different ways (e.g. *)
190 (* term nets and predicate-indexed lists of Horn clauses). To allow mixing *)
191 (* of arbitrary types for state storage, we use a trick due to RJB via DRS. *)
192 (* ------------------------------------------------------------------------- *)
194 type prover = Prover of conv * (thm list -> prover);;
196 let mk_prover applicator augmentor =
197 let rec mk_prover state =
198 let apply = applicator state
199 and augment thms = mk_prover (augmentor state thms) in
200 Prover(apply,augment) in
203 let augment(Prover(_,aug)) thms = aug thms;;
205 let apply_prover(Prover(conv,_)) tm = conv tm;;
207 (* ------------------------------------------------------------------------- *)
208 (* Type of simpsets. We have a convnet containing rewrites (implicational *)
209 (* and otherwise), other term-indexed context-free conversions like *)
210 (* BETA_CONV, and congruence rules. Then there is a list of provers that *)
211 (* have their own way of storing and using context, and finally a rewrite *)
212 (* maker function, to allow customization. *)
214 (* We also have a type of (traversal) strategy, following Konrad. *)
215 (* ------------------------------------------------------------------------- *)
218 Simpset of gconv net (* Rewrites & congruences *)
219 * (strategy -> strategy) (* Prover for conditions *)
220 * prover list (* Subprovers for prover *)
221 * (thm -> thm list -> thm list) (* Rewrite maker *)
223 and strategy = simpset -> int -> term -> thm;;
225 (* ------------------------------------------------------------------------- *)
226 (* Very simple prover: recursively simplify then try provers. *)
227 (* ------------------------------------------------------------------------- *)
229 let basic_prover strat (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
230 let sth = try strat ss lev tm with Failure _ -> REFL tm in
233 let tth = tryfind (fun pr -> apply_prover pr (rand(concl sth))) provers in
234 EQ_MP (SYM sth) tth;;
236 (* ------------------------------------------------------------------------- *)
237 (* Functions for changing or augmenting components of simpsets. *)
238 (* ------------------------------------------------------------------------- *)
240 let ss_of_thms thms (Simpset(net,prover,provers,rewmaker)) =
241 let cthms = itlist rewmaker thms [] in
242 let net' = itlist (net_of_thm true) cthms net in
243 Simpset(net',prover,provers,rewmaker);;
245 let ss_of_conv keytm conv (Simpset(net,prover,provers,rewmaker)) =
246 let net' = net_of_conv keytm conv net in
247 Simpset(net',prover,provers,rewmaker);;
249 let ss_of_congs thms (Simpset(net,prover,provers,rewmaker)) =
250 let net' = itlist net_of_cong thms net in
251 Simpset(net',prover,provers,rewmaker);;
253 let ss_of_prover newprover (Simpset(net,_,provers,rewmaker)) =
254 Simpset(net,newprover,provers,rewmaker);;
256 let ss_of_provers newprovers (Simpset(net,prover,provers,rewmaker)) =
257 Simpset(net,prover,newprovers@provers,rewmaker);;
259 let ss_of_maker newmaker (Simpset(net,prover,provers,_)) =
260 Simpset(net,prover,provers,newmaker);;
262 (* ------------------------------------------------------------------------- *)
263 (* Perform a context-augmentation operation on a simpset. *)
264 (* ------------------------------------------------------------------------- *)
266 let AUGMENT_SIMPSET cth (Simpset(net,prover,provers,rewmaker)) =
267 let provers' = map (C augment [cth]) provers in
268 let cthms = rewmaker cth [] in
269 let net' = itlist (net_of_thm true) cthms net in
270 Simpset(net',prover,provers',rewmaker);;
272 (* ------------------------------------------------------------------------- *)
273 (* Depth conversions. *)
274 (* ------------------------------------------------------------------------- *)
276 let ONCE_DEPTH_SQCONV,DEPTH_SQCONV,REDEPTH_SQCONV,
277 TOP_DEPTH_SQCONV,TOP_SWEEP_SQCONV =
278 let IMP_REWRITES_CONV strat (Simpset(net,prover,provers,rewmaker) as ss) lev
280 tryfind (fun (n,cnv) ->
281 if n >= 4 then fail() else
283 let etm = concl th in
284 if is_eq etm then th else
285 if lev <= 0 then failwith "IMP_REWRITES_CONV: Too deep" else
286 let cth = prover strat ss (lev-1) (lhand etm) in
288 let rec RUN_SUB_CONV strat ss lev triv th =
291 let subtm = lhand tm in
292 let avs,bod = strip_forall subtm in
293 let (t,t'),ss',mk_fun =
294 try dest_eq bod,ss,I with Failure _ ->
295 let cxt,deq = dest_imp bod in
296 dest_eq deq,AUGMENT_SIMPSET (ASSUME cxt) ss,DISCH cxt in
297 let eth,triv' = try strat ss' lev t,false with Failure _ -> REFL t,triv in
298 let eth' = GENL avs (mk_fun eth) in
299 let th' = if is_var t' then INST [rand(concl eth),t'] th
300 else GEN_PART_MATCH lhand th (concl eth') in
301 let th'' = MP th' eth' in
302 RUN_SUB_CONV strat ss lev triv' th''
303 else if triv then fail() else th in
304 let GEN_SUB_CONV strat ss lev pconvs tm =
305 try tryfind (fun (n,cnv) ->
306 if n < 4 then fail() else
308 RUN_SUB_CONV strat ss lev true th) pconvs
311 let l,r = dest_comb tm in
312 try let th1 = strat ss lev l in
313 try let th2 = strat ss lev r in MK_COMB(th1,th2)
314 with Failure _ -> AP_THM th1 r
315 with Failure _ -> AP_TERM l (strat ss lev r)
316 else if is_abs tm then
317 let v,bod = dest_abs tm in
318 let th = strat ss lev bod in
319 try ABS v th with Failure _ ->
320 let gv = genvar(type_of v) in
321 let gbod = vsubst[gv,v] bod in
322 let gth = ABS gv (strat ss lev gbod) in
323 let gtm = concl gth in
324 let l,r = dest_eq gtm in
325 let v' = variant (frees gtm) v in
326 let l' = alpha v' l and r' = alpha v' r in
327 EQ_MP (ALPHA gtm (mk_eq(l',r'))) gth
328 else failwith "GEN_SUB_CONV" in
329 let rec ONCE_DEPTH_SQCONV
330 (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
331 let pconvs = lookup tm net in
332 try IMP_REWRITES_CONV ONCE_DEPTH_SQCONV ss lev pconvs tm
334 GEN_SUB_CONV ONCE_DEPTH_SQCONV ss lev pconvs tm in
335 let rec DEPTH_SQCONV (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
336 let pconvs = lookup tm net in
337 try let th1 = GEN_SUB_CONV DEPTH_SQCONV ss lev pconvs tm in
338 let tm1 = rand(concl th1) in
339 let pconvs1 = lookup tm1 net in
340 try TRANS th1 (IMP_REWRITES_CONV DEPTH_SQCONV ss lev pconvs1 tm1)
341 with Failure _ -> th1
343 IMP_REWRITES_CONV DEPTH_SQCONV ss lev pconvs tm in
344 let rec REDEPTH_SQCONV (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
345 let pconvs = lookup tm net in
347 try let th1 = GEN_SUB_CONV REDEPTH_SQCONV ss lev pconvs tm in
348 let tm1 = rand(concl th1) in
349 let pconvs1 = lookup tm1 net in
350 try TRANS th1 (IMP_REWRITES_CONV REDEPTH_SQCONV ss lev pconvs1 tm1)
351 with Failure _ -> th1
353 IMP_REWRITES_CONV REDEPTH_SQCONV ss lev pconvs tm in
354 try let th' = REDEPTH_SQCONV ss lev (rand(concl th)) in
356 with Failure _ -> th in
357 let rec TOP_DEPTH_SQCONV (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
358 let pconvs = lookup tm net in
360 try IMP_REWRITES_CONV TOP_DEPTH_SQCONV ss lev pconvs tm
361 with Failure _ -> GEN_SUB_CONV TOP_DEPTH_SQCONV ss lev pconvs tm in
362 try let th2 = TOP_DEPTH_SQCONV ss lev (rand(concl th1)) in
364 with Failure _ -> th1 in
365 let rec TOP_SWEEP_SQCONV (Simpset(net,prover,provers,rewmaker) as ss) lev tm =
366 let pconvs = lookup tm net in
367 try let th1 = IMP_REWRITES_CONV TOP_SWEEP_SQCONV ss lev pconvs tm in
368 try let th2 = TOP_SWEEP_SQCONV ss lev (rand(concl th1)) in
370 with Failure _ -> th1
371 with Failure _ -> GEN_SUB_CONV TOP_SWEEP_SQCONV ss lev pconvs tm in
372 ONCE_DEPTH_SQCONV,DEPTH_SQCONV,REDEPTH_SQCONV,
373 TOP_DEPTH_SQCONV,TOP_SWEEP_SQCONV;;
375 (* ------------------------------------------------------------------------- *)
376 (* Maintenence of basic rewrites and conv nets for rewriting. *)
377 (* ------------------------------------------------------------------------- *)
379 let set_basic_rewrites,extend_basic_rewrites,basic_rewrites,
380 set_basic_convs,extend_basic_convs,basic_convs,basic_net =
381 let rewrites = ref ([]:thm list)
382 and conversions = ref ([]:(string*(term*conv))list)
383 and conv_net = ref (empty_net: gconv net) in
384 let rehash_convnet() =
385 conv_net := itlist (net_of_thm true) (!rewrites)
386 (itlist (fun (_,(pat,cnv)) -> net_of_conv pat cnv) (!conversions)
388 let set_basic_rewrites thl =
389 let canon_thl = itlist (mk_rewrites false) thl [] in
390 (rewrites := canon_thl; rehash_convnet())
391 and extend_basic_rewrites thl =
392 let canon_thl = itlist (mk_rewrites false) thl [] in
393 (rewrites := canon_thl @ !rewrites; rehash_convnet())
394 and basic_rewrites() = !rewrites
395 and set_basic_convs cnvs =
396 (conversions := cnvs; rehash_convnet())
397 and extend_basic_convs (name,patcong) =
399 (name,patcong)::filter(fun (name',_) -> name <> name') (!conversions);
401 and basic_convs() = !conversions
402 and basic_net() = !conv_net in
403 set_basic_rewrites,extend_basic_rewrites,basic_rewrites,
404 set_basic_convs,extend_basic_convs,basic_convs,basic_net;;
406 (* ------------------------------------------------------------------------- *)
407 (* Same thing for the default congruences. *)
408 (* ------------------------------------------------------------------------- *)
410 let set_basic_congs,extend_basic_congs,basic_congs =
411 let congs = ref ([]:thm list) in
412 (fun thl -> congs := thl),
413 (fun thl -> congs := union' equals_thm thl (!congs)),
416 (* ------------------------------------------------------------------------- *)
417 (* Main rewriting conversions. *)
418 (* ------------------------------------------------------------------------- *)
420 let GENERAL_REWRITE_CONV rep (cnvl:conv->conv) (builtin_net:gconv net) thl =
421 let thl_canon = itlist (mk_rewrites false) thl [] in
422 let final_net = itlist (net_of_thm rep) thl_canon builtin_net in
423 cnvl (REWRITES_CONV final_net);;
425 let GEN_REWRITE_CONV (cnvl:conv->conv) thl =
426 GENERAL_REWRITE_CONV false cnvl empty_net thl;;
428 let PURE_REWRITE_CONV thl =
429 GENERAL_REWRITE_CONV true TOP_DEPTH_CONV empty_net thl;;
431 let REWRITE_CONV thl =
432 GENERAL_REWRITE_CONV true TOP_DEPTH_CONV (basic_net()) thl;;
434 let PURE_ONCE_REWRITE_CONV thl =
435 GENERAL_REWRITE_CONV false ONCE_DEPTH_CONV empty_net thl;;
437 let ONCE_REWRITE_CONV thl =
438 GENERAL_REWRITE_CONV false ONCE_DEPTH_CONV (basic_net()) thl;;
440 (* ------------------------------------------------------------------------- *)
441 (* Rewriting rules and tactics. *)
442 (* ------------------------------------------------------------------------- *)
444 let GEN_REWRITE_RULE cnvl thl = CONV_RULE(GEN_REWRITE_CONV cnvl thl);;
446 let PURE_REWRITE_RULE thl = CONV_RULE(PURE_REWRITE_CONV thl);;
448 let REWRITE_RULE thl = CONV_RULE(REWRITE_CONV thl);;
450 let PURE_ONCE_REWRITE_RULE thl = CONV_RULE(PURE_ONCE_REWRITE_CONV thl);;
452 let ONCE_REWRITE_RULE thl = CONV_RULE(ONCE_REWRITE_CONV thl);;
454 let PURE_ASM_REWRITE_RULE thl th =
455 PURE_REWRITE_RULE ((map ASSUME (hyp th)) @ thl) th;;
457 let ASM_REWRITE_RULE thl th =
458 REWRITE_RULE ((map ASSUME (hyp th)) @ thl) th;;
460 let PURE_ONCE_ASM_REWRITE_RULE thl th =
461 PURE_ONCE_REWRITE_RULE ((map ASSUME (hyp th)) @ thl) th;;
463 let ONCE_ASM_REWRITE_RULE thl th =
464 ONCE_REWRITE_RULE ((map ASSUME (hyp th)) @ thl) th;;
466 let GEN_REWRITE_TAC cnvl thl = CONV_TAC(GEN_REWRITE_CONV cnvl thl);;
468 let PURE_REWRITE_TAC thl = CONV_TAC(PURE_REWRITE_CONV thl);;
470 let REWRITE_TAC thl = CONV_TAC(REWRITE_CONV thl);;
472 let PURE_ONCE_REWRITE_TAC thl = CONV_TAC(PURE_ONCE_REWRITE_CONV thl);;
474 let ONCE_REWRITE_TAC thl = CONV_TAC(ONCE_REWRITE_CONV thl);;
476 let (PURE_ASM_REWRITE_TAC: thm list -> tactic) =
477 ASM PURE_REWRITE_TAC;;
479 let (ASM_REWRITE_TAC: thm list -> tactic) =
482 let (PURE_ONCE_ASM_REWRITE_TAC: thm list -> tactic) =
483 ASM PURE_ONCE_REWRITE_TAC;;
485 let (ONCE_ASM_REWRITE_TAC: thm list -> tactic) =
486 ASM ONCE_REWRITE_TAC;;
488 (* ------------------------------------------------------------------------- *)
489 (* Simplification functions. *)
490 (* ------------------------------------------------------------------------- *)
492 let GEN_SIMPLIFY_CONV (strat:strategy) ss lev thl =
493 let ss' = itlist AUGMENT_SIMPSET thl ss in
494 TRY_CONV (strat ss' lev);;
496 let ONCE_SIMPLIFY_CONV ss = GEN_SIMPLIFY_CONV ONCE_DEPTH_SQCONV ss 1;;
498 let SIMPLIFY_CONV ss = GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV ss 3;;
500 (* ------------------------------------------------------------------------- *)
501 (* Simple but useful default version. *)
502 (* ------------------------------------------------------------------------- *)
504 let empty_ss = Simpset(empty_net,basic_prover,[],mk_rewrites true);;
507 let rewmaker = mk_rewrites true in
509 let cthms = itlist rewmaker thl [] in
510 let net' = itlist (net_of_thm true) cthms (basic_net()) in
511 let net'' = itlist net_of_cong (basic_congs()) net' in
512 Simpset(net'',basic_prover,[],rewmaker);;
514 let SIMP_CONV thl = SIMPLIFY_CONV (basic_ss []) thl;;
516 let PURE_SIMP_CONV thl = SIMPLIFY_CONV empty_ss thl;;
518 let ONCE_SIMP_CONV thl = ONCE_SIMPLIFY_CONV (basic_ss []) thl;;
520 let SIMP_RULE thl = CONV_RULE(SIMP_CONV thl);;
522 let PURE_SIMP_RULE thl = CONV_RULE(PURE_SIMP_CONV thl);;
524 let ONCE_SIMP_RULE thl = CONV_RULE(ONCE_SIMP_CONV thl);;
526 let SIMP_TAC thl = CONV_TAC(SIMP_CONV thl);;
528 let PURE_SIMP_TAC thl = CONV_TAC(PURE_SIMP_CONV thl);;
530 let ONCE_SIMP_TAC thl = CONV_TAC(ONCE_SIMP_CONV thl);;
532 let ASM_SIMP_TAC = ASM SIMP_TAC;;
534 let PURE_ASM_SIMP_TAC = ASM PURE_SIMP_TAC;;
536 let ONCE_ASM_SIMP_TAC = ASM ONCE_SIMP_TAC;;
538 (* ------------------------------------------------------------------------- *)
539 (* Abbreviation tactics. *)
540 (* ------------------------------------------------------------------------- *)
543 let cvs,t = dest_eq tm in
544 let v,vs = strip_comb cvs in
545 let rs = list_mk_abs(vs,t) in
546 let eq = mk_eq(rs,v) in
547 let th1 = itlist (fun v th -> CONV_RULE(LAND_CONV BETA_CONV) (AP_THM th v))
548 (rev vs) (ASSUME eq) in
549 let th2 = SIMPLE_CHOOSE v (SIMPLE_EXISTS v (GENL vs th1)) in
550 let th3 = PROVE_HYP (EXISTS(mk_exists(v,eq),rs) (REFL rs)) th2 in
552 let avoids = itlist (union o frees o concl o snd) asl (frees w) in
553 if mem v avoids then failwith "ABBREV_TAC: variable already used" else
555 (fun th -> RULE_ASSUM_TAC(PURE_ONCE_REWRITE_RULE[th]) THEN
556 PURE_ONCE_REWRITE_TAC[th] THEN
560 let EXPAND_TAC s = FIRST_ASSUM(SUBST1_TAC o SYM o
561 check((=) s o fst o dest_var o rhs o concl)) THEN BETA_TAC;;