1(* res_quanLib.sml - simpsets, tactics, etc. for restricted quantification
2
3FILE: res_rules.ml       DATE: 1 Aug 92      BY: Wai Wong
4TRANSLATED               DATE: 28 May 93     BY: Paul Curzon
5UPDATED                  DATE: 30 Oct 01     BY: Joe Hurd
6
7============================================================================*)
8
9structure res_quanLib :> res_quanLib =
10struct
11
12open HolKernel Parse Drule Conv Tactic Tactical Thm_cont
13     Rewrite boolSyntax boolLib res_quanTheory boolTheory simpLib Cond_rewrite;
14
15infix THENR ORELSER ++ ||;
16
17local  (* Fix the grammar used by this file *)
18  val ambient_grammars = Parse.current_grammars();
19  val _ = Parse.temp_set_grammars boolTheory.bool_grammars
20in
21
22val bool_ss = boolSimps.bool_ss;
23val op++ = op THEN;
24val op|| = op ORELSE;
25fun f THENR g = g o f;
26fun f ORELSER g = fn x => f x handle HOL_ERR _ => g x;
27
28val ERR = mk_HOL_ERR "res_quanTools";
29
30(* ===================================================================== *)
31(* Syntactic operations on restricted quantifications.                   *)
32(* These ought to be generalised to all kinds of restrictions,           *)
33(* but one thing at a time.                                              *)
34(*  (These now all come from boolSyntax.)                                *)
35(* --------------------------------------------------------------------- *)
36
37
38
39(* ===================================================================== *)
40(* Conversions                                                           *)
41(* --------------------------------------------------------------------- *)
42
43local
44  fun RES_QUAN_CONV c tm =
45    let
46      val b = snd (dest_comb tm)
47    in
48      (if is_abs b then
49         let
50           val v = fst (dest_abs b)
51         in
52           c
53           THENC RAND_CONV (ALPHA_CONV v)
54           THENC RAND_CONV (ABS_CONV (RAND_CONV BETA_CONV))
55         end
56       else c) tm
57    end;
58in
59  val RES_FORALL_CONV = RES_QUAN_CONV (REWR_CONV RES_FORALL);
60  val RES_EXISTS_CONV = RES_QUAN_CONV (REWR_CONV RES_EXISTS);
61  val RES_SELECT_CONV = RES_QUAN_CONV (REWR_CONV RES_SELECT);
62end;
63
64val RES_EXISTS_UNIQUE_CONV =
65  REWR_CONV RES_EXISTS_UNIQUE THENC
66  TRY_CONV
67  (LAND_CONV (RAND_CONV (ABS_CONV BETA_CONV)) THENC
68   RAND_CONV
69   (RAND_CONV
70    (ABS_CONV
71     (RAND_CONV
72      (ABS_CONV
73       (LAND_CONV ((LAND_CONV BETA_CONV) THENC (RAND_CONV BETA_CONV))))))));
74
75(* ---------------------------------------------------------------------     *)
76(* If conversion c maps term (--`\i.t1`--) to theorem |- (\i.t1) = (\i'.t1'),*)
77(* then RF_BODY_CONV c (--`!i :: P. t1`--) returns the theorem               *)
78(*     |- (!i :: P. t1) = (!i' :: P. t1')                                    *)
79(*                                                                           *)
80(* If conversion c maps term (--`t1`--) to the theorem |- t1 = t1',          *)
81(* then RF_CONV c (--`!i :: P. t1`--) returns the theorem                    *)
82(*     |- (!i :: P. t1) = (!i :: P. t1')                                     *)
83(* ---------------------------------------------------------------------     *)
84
85fun BOTH_CONV c = (LAND_CONV c THENC RAND_CONV c);
86fun LEFT_THENC_RIGHT c1 c2 = (LAND_CONV c1 THENC RAND_CONV c2);
87
88val RF_BODY_CONV = RAND_CONV;
89val RF_PRED_CONV = (RATOR_CONV o RAND_CONV);
90val RF_CONV = (RAND_CONV o ABS_CONV);
91fun PRED_THENC_BODY c1 c2 =
92   (((RATOR_CONV o RAND_CONV) c1) THENC ((RAND_CONV o ABS_CONV) c2));
93
94(* --------------------------------------------------------------------- *)
95(* IMP_RES_FORALL_CONV (--`!x. P x ==> t[x]`--)                  *)
96(*     |- !x. P x ==> t[x] = !x :: P. t[x]                               *)
97(* --------------------------------------------------------------------- *)
98
99val IMP_RES_FORALL_CONV  = (fn tm =>
100    let val dthm = res_quanTheory.RES_FORALL
101    val (var, a) = dest_forall tm
102    val (ante,t) = dest_imp a
103    val (pred,v) = dest_comb ante
104    in
105     if var !~ v then
106       raise ERR "IMP_RES_FORALL_CONV" "term not in the correct form"
107     else
108       SYM (RIGHT_CONV_RULE ((GEN_ALPHA_CONV var) THENC
109                             (ONCE_DEPTH_CONV BETA_CONV))
110                            (ISPECL [pred,mk_abs(var,t)] dthm))
111    end
112     handle HOL_ERR _ =>
113        raise ERR "IMP_RES_FORALL_CONV" "")
114    :conv;
115
116(* --------------------------------------------------------------------- *)
117(* RES_FORALL_AND_CONV (--`!i :: P. t1 /\ t2`--)  =                     *)
118(*     |- (!i :: P. t1 /\ t2) = (!i :: P. t1) /\ (!i :: P. t2)           *)
119(* --------------------------------------------------------------------- *)
120
121val RES_FORALL_AND_CONV = (fn tm =>
122    let val rthm = res_quanTheory.RES_FORALL_CONJ_DIST
123    val (var,pred,conj) = dest_res_forall tm
124    val (left,right) = dest_conj conj
125    val left_pred = mk_abs(var,left)
126    val right_pred = mk_abs(var,right)
127    val thm = ISPECL [pred, left_pred, right_pred] rthm
128    val c = LEFT_THENC_RIGHT
129        (RF_CONV(BOTH_CONV BETA_CONV)) (BOTH_CONV(RF_CONV BETA_CONV))
130    in
131       CONV_RULE c thm
132    end
133     handle HOL_ERR _ =>
134        raise ERR "RES_FORALL_AND_CONV" "")
135    :conv;
136
137(* --------------------------------------------------------------------- *)
138(* AND_RES_FORALL_CONV (--`(!i :: P. t1) /\ (!i :: P. t2)`--) =         *)
139(*     |- (!i :: P. t1) /\ (!i :: P. t2) = (!i :: P. t1 /\ t2)           *)
140(* --------------------------------------------------------------------- *)
141
142val AND_RES_FORALL_CONV = (fn tm =>
143    let val rthm = res_quanTheory.RES_FORALL_CONJ_DIST
144    val conj1 = rand(rator tm) and conj2 = rand tm
145    val (var1,pred1,body1) = dest_res_forall conj1
146    val (var2,pred2,body2) = dest_res_forall conj2
147    val thm = SYM(
148        ISPECL[pred1, mk_abs(var1,body1), mk_abs(var2,body2)] rthm)
149    val c = LEFT_THENC_RIGHT
150        (BOTH_CONV(RF_CONV BETA_CONV)) (RF_CONV(BOTH_CONV BETA_CONV))
151    in
152      CONV_RULE c thm
153    end
154     handle HOL_ERR _ =>
155        raise ERR "AND_RES_FORALL_CONV" "")
156    :conv;
157
158(* --------------------------------------------------------------------- *)
159(* RES_FORALL_SWAP_CONV (--`!i :: P. !j :: Q. R`--) =                         *)
160(*     |- (!i :: P. !j :: Q. R) = (!j :: Q. !i :: P. R)                  *)
161(* --------------------------------------------------------------------- *)
162
163val RES_FORALL_SWAP_CONV = (fn tm =>
164    let val rthm = res_quanTheory.RES_FORALL_REORDER
165    val (i,P,body) = dest_res_forall tm
166    val (j,Q,R) = dest_res_forall body
167    val thm1 = ISPECL [P,Q,mk_abs(i, mk_abs(j, R))] rthm
168    (* Reduce the two beta-redexes on either side of the equation. *)
169    val c1 = RF_CONV(RF_CONV(RATOR_CONV BETA_CONV THENC BETA_CONV))
170    val thm2 = CONV_RULE (LAND_CONV c1 THENC RAND_CONV c1) thm1
171    (* Rename the bound variables in the quantifications. *)
172    val c2 =
173        LAND_CONV(RF_CONV(RF_BODY_CONV(ALPHA_CONV j)) THENC
174            RF_BODY_CONV(ALPHA_CONV i)) THENC
175        RAND_CONV(RF_CONV(RF_BODY_CONV(ALPHA_CONV i)) THENC
176            RF_BODY_CONV(ALPHA_CONV j))
177    in
178     if i ~~ j orelse free_in i Q orelse free_in j P
179     then raise ERR "RES_FORALL_SWAP" ""
180     else CONV_RULE c2 thm2
181    end
182     handle HOL_ERR _ =>
183        raise ERR "RES_FORALL_SWAP" "")
184    :conv;
185
186(* --------------------------------------------------------------------- *)
187(* RESQ_REWRITE1_CONV : thm list -> thm -> conv                          *)
188(* RESQ_REWRITE1_CONV thms thm tm                                        *)
189(* The input theorem thm should be restricted quantified equational      *)
190(* theorem ie. the form suitable for RESQ_REWRITE_TAC. The input term tm *)
191(* should be an instance of the left-hand side of the conclusion of thm. *)
192(* The theorem list thms should contains theorems matching the conditions*)
193(* in the input thm. They are used to discharge the conditions. The      *)
194(* conditions which cannot be discharged by matching theorems will be    *)
195(* left in the assumption.                                               *)
196(* --------------------------------------------------------------------- *)
197
198fun RESQ_REWRITE1_CONV thms th =
199  (fn  tm =>
200    let val th' = CONV_RULE ((TOP_DEPTH_CONV RES_FORALL_CONV)
201        THENC (TOP_DEPTH_CONV RIGHT_IMP_FORALL_CONV)) th
202    in
203      COND_REWRITE1_CONV thms th' tm
204    end):conv;
205
206(* ===================================================================== *)
207(* Derived rules                                                         *)
208(* --------------------------------------------------------------------- *)
209
210(* --------------------------------------------------------------------- *)
211(* Rule to specialize a restricted universal quantification.             *)
212(*                                                                       *)
213(*    A |- !x :: P. M x                                                  *)
214(*   -------------------  RESQ_HALF_SPEC                                 *)
215(*    A |- t IN P ==> M [t/x]                                            *)
216(*                                                                       *)
217(* --------------------------------------------------------------------- *)
218
219fun RESQ_HALF_SPEC tm = CONV_RULE RES_FORALL_CONV THENR SPEC tm;
220
221(* --------------------------------------------------------------------- *)
222(* Specialize a list of universal quantifiers which may be a mixture     *)
223(* of ordinary or restricted in any order.                               *)
224(* --------------------------------------------------------------------- *)
225
226fun GEN_RESQ_HALF_SPECL spec res_spec =
227  let
228    fun half_specl asms [] th = foldl (uncurry DISCH) th asms
229      | half_specl asms (s :: rest) th =
230      if is_res_forall (concl th) then
231        let
232          val th = res_spec s th
233          val (a, _) = dest_imp (concl th)
234        in
235          half_specl (a :: asms) rest (UNDISCH th)
236        end
237      else if is_forall (concl th) then half_specl asms rest (spec s th)
238      else raise ERR "GEN_RESQ_HALF_SPECL" "not a universal quantifier"
239  in
240    half_specl []
241  end;
242
243val RESQ_HALF_SPECL = GEN_RESQ_HALF_SPECL SPEC RESQ_HALF_SPEC;
244
245(* --------------------------------------------------------------------- *)
246(* Rule to specialize a possibly restricted universal quantification.    *)
247(*                                                                       *)
248(*    A |- !x :: P. M x       A |- !x. M x                               *)
249(*   -------------------     --------------    RESQ_SPEC ``t``           *)
250(*    A, t IN P |- M t          A |- M t                                 *)
251(*                                                                       *)
252(* --------------------------------------------------------------------- *)
253
254fun RESQ_SPEC tm = (RESQ_HALF_SPEC tm THENR UNDISCH) ORELSER SPEC tm;
255
256(* ---------------------------------------------------------------------*)
257(* RESQ_SPECL : term list -> thm -> thm                                 *)
258(* An analogy to SPECL as RESQ_SEPC to SPEC.                            *)
259(* Instatiate a list of possibly restricted universal quantifiers.      *)
260(* ---------------------------------------------------------------------*)
261
262val RESQ_SPECL = C (foldl (uncurry RESQ_SPEC));
263
264(* --------------------------------------------------------------------- *)
265(* RESQ_MATCH_MP : thm -> thm -> thm                                     *)
266(* RESQ_MATCH_MP (|- !x :: P. Q x) (|- t IN P) returns |- Q t            *)
267(* --------------------------------------------------------------------- *)
268
269fun RESQ_MATCH_MP th1 th2 = MATCH_MP (CONV_RULE RES_FORALL_CONV th1) th2;
270
271(* --------------------------------------------------------------------- *)
272(* RESQ_REWR_CANON : thm -> thm                                          *)
273(* convert a theorem into a canonical form for COND_REWR_TAC             *)
274(* --------------------------------------------------------------------- *)
275
276val RESQ_REWR_CANON =
277    COND_REWR_CANON o (CONV_RULE ((TOP_DEPTH_CONV RES_FORALL_CONV)));
278
279(* ===================================================================== *)
280(* Tactics                                                              *)
281(* --------------------------------------------------------------------- *)
282
283(* --------------------------------------------------------------------- *)
284(* Tactic to strip off a restricted existential quantification.          *)
285(*                                                                       *)
286(*    A ?- ?x :: P. t                                                    *)
287(*   ===================  RESQ_EXISTS_TAC (--`x'`--)                     *)
288(*    A ?-  x' IN P /\ t                                                 *)
289(*                                                                       *)
290(* --------------------------------------------------------------------- *)
291
292fun RESQ_EXISTS_TAC tm = CONV_TAC RES_EXISTS_CONV ++ EXISTS_TAC tm;
293
294(* --------------------------------------------------------------------- *)
295(* Tactic to strip off a restricted universal quantification.            *)
296(* User supplies a thm tactic for the x IN P theorem that results.       *)
297(* --------------------------------------------------------------------- *)
298
299fun RESQ_GEN_THEN ttac =
300  CONV_TAC RES_FORALL_CONV ++ GEN_TAC ++ DISCH_THEN ttac;
301
302(* --------------------------------------------------------------------- *)
303(* A restricted quantification version of STRIP_TAC.                     *)
304(* --------------------------------------------------------------------- *)
305
306fun RESQ_HALF_EXISTS_THEN (ttac : thm_tactic) =
307  ttac o CONV_RULE RES_EXISTS_CONV;
308
309val RESQ_CHOOSE_THEN =
310  RESQ_HALF_EXISTS_THEN THEN_TCL CHOOSE_THEN THEN_TCL CONJUNCTS_THEN;
311
312val RESQ_STRIP_THM_THEN = STRIP_THM_THEN ORELSE_TCL RESQ_CHOOSE_THEN;
313
314fun RESQ_STRIP_GOAL_THEN ttac = STRIP_GOAL_THEN ttac || RESQ_GEN_THEN ttac;
315
316val RESQ_STRIP_ASSUME_TAC = REPEAT_TCL RESQ_STRIP_THM_THEN CHECK_ASSUME_TAC;
317
318val RESQ_STRIP_TAC = RESQ_STRIP_GOAL_THEN RESQ_STRIP_ASSUME_TAC;
319
320(* --------------------------------------------------------------------- *)
321(* Tactic to strip off a restricted universal quantification.            *)
322(* Uses RESQ_STRIP_ASSUME_TAC to add |- x IN P to the assumptions.       *)
323(*                                                                       *)
324(*    A ?- !x :: P. t                                                    *)
325(*   ===================  RESQ_GEN_TAC                                   *)
326(*    A, x IN P ?- t                                                     *)
327(*                                                                       *)
328(* --------------------------------------------------------------------- *)
329
330val RESQ_GEN_TAC = RESQ_GEN_THEN RESQ_STRIP_ASSUME_TAC;
331
332(* --------------------------------------------------------------------- *)
333(* RESOLUTION                                                           *)
334(* --------------------------------------------------------------------- *)
335
336(* --------------------------------------------------------------------- *)
337(* check st l : Fail with st if l is empty, otherwise return l.         *)
338(* --------------------------------------------------------------------- *)
339
340local fun check st l = if null l then raise ERR "check" st else l
341
342(* --------------------------------------------------------------------- *)
343(* check_res th : Fail if th is not in the form:                        *)
344(* !x0 ... xn. !y :: P. t   otherwise, it returns the following theorem *)
345(* !x0 ... xn y. P ==> t.                                               *)
346(* --------------------------------------------------------------------- *)
347
348and  check_res th =
349    if is_forall (concl th) then
350        GEN_ALL (CONV_RULE RES_FORALL_CONV (SPEC_ALL th))
351    else CONV_RULE RES_FORALL_CONV th
352      handle _ => raise ERR "check_res" "not restricted forall";
353in
354
355(* --------------------------------------------------------------------- *)
356(* RESQ_IMP_RES_THEN  : Resolve a restricted quantified theorem against  *)
357(* the assumptions.                                                      *)
358(* --------------------------------------------------------------------- *)
359
360fun RESQ_IMP_RES_THEN ttac resth =
361    let val th = check_res resth
362    in IMP_RES_THEN ttac th
363    end
364    handle HOL_ERR{message = s,...} =>
365        raise ERR "RESQ_IMP_RES_THEN" s
366
367(* --------------------------------------------------------------------- *)
368(* RESQ_RES_THEN : Resolve all restricted universally quantified         *)
369(* assumptions against the rest.                                         *)
370(* --------------------------------------------------------------------- *)
371
372and RESQ_RES_THEN (ttac:thm_tactic) (asl,g) =
373    let val a = map ASSUME asl
374    val ths = mapfilter check_res a
375    val imps = check "RESQ_RES_THEN: no restricted quantification " ths
376    val l = itlist (fn th=>append (mapfilter (MATCH_MP th) a)) imps []
377    val res = check "RESQ_RES_THEN: no resolvents " l
378    val tacs = check "RESQ_RES_THEN: no tactics" (mapfilter ttac res)
379    in
380        EVERY tacs (asl,g)
381    end
382end;
383
384fun RESQ_IMP_RES_TAC th g =
385    RESQ_IMP_RES_THEN (REPEAT_GTCL RESQ_IMP_RES_THEN STRIP_ASSUME_TAC) th g
386    handle _ => ALL_TAC g;
387
388fun RESQ_RES_TAC g =
389    RESQ_RES_THEN (REPEAT_GTCL RESQ_IMP_RES_THEN STRIP_ASSUME_TAC) g
390    handle _ => ALL_TAC g;
391
392(* --------------------------------------------------------------------- *)
393(* RESQ_REWRITE1_TAC : thm_tactic                                        *)
394(* RESQ_REWRITE1_TAC |- !x::P. u[x] = v[x]                               *)
395(* transforms the input restricted quantified theorem to implicative     *)
396(* form then do conditional rewriting.                                   *)
397(* --------------------------------------------------------------------- *)
398
399fun RESQ_REWRITE1_TAC th' =
400    let val th = RESQ_REWR_CANON th'
401    in
402      COND_REWR_TAC search_top_down th
403    end;
404
405(* --------------------------------------------------------------------- *)
406(* Restricted quantifier elimination using the simplifier.               *)
407(* --------------------------------------------------------------------- *)
408
409val ELIM_RESQ_ss = named_rewrites "ELIM_RESQ_ss" [
410  RES_FORALL, RES_EXISTS, RES_EXISTS_UNIQUE, RES_SELECT];
411
412val resq_SS =
413  simpLib.SSFRAG
414  {name=SOME"resq",
415   ac = [], congs = [],
416   convs =
417   [{conv = K (K RES_FORALL_CONV),
418     key = SOME ([], Term `RES_FORALL (p:'a -> bool) m`),
419     name = "RES_FORALL_CONV", trace = 2},
420    {conv = K (K RES_EXISTS_CONV),
421     key = SOME ([], Term `RES_EXISTS (p:'a -> bool) m`),
422     name = "RES_EXISTS_CONV", trace = 2},
423    {conv = K (K RES_SELECT_CONV),
424     key = SOME ([], Term `RES_SELECT (p:'a -> bool) m`),
425     name = "RES_SELECT_CONV", trace = 2},
426    {conv = K (K RES_EXISTS_UNIQUE_CONV),
427     key = SOME ([], Term `RES_EXISTS_UNIQUE (p:'a -> bool) m`),
428     name = "RES_EXISTS_UNIQUE_CONV", trace = 2}],
429   dprocs = [], filter = NONE, rewrs = []};
430
431val resq_ss = simpLib.++ (bool_ss, resq_SS);
432
433val RESQ_TAC =
434  FULL_SIMP_TAC resq_ss [] THEN
435  POP_ASSUM_LIST (EVERY o map STRIP_ASSUME_TAC o rev);
436
437(* Each row is a set of analogus rewrite rules; an additional level of
438indentation means that a row continues the previous one. *)
439val RICH_RESQ_ss = named_rewrites "RICH_RESQ" [
440  (* Unconditional facts that can be simplifier to a boolean value. *)
441  RES_FORALL_T, RES_EXISTS_F, RES_EXISTS_UNIQUE_F,
442  RES_FORALL_EMPTY, RES_EXISTS_EMPTY, RES_EXISTS_UNIQUE_EMPTY,
443
444  (* Unconditional rewriting rules. *)
445  RES_FORALL_UNIV, RES_EXISTS_UNIV, RES_EXISTS_UNIQUE_UNIV,
446  NOT_RES_FORALL, NOT_RES_EXISTS,
447  RES_FORALL_UNIQUE, RES_EXISTS_EQUAL,
448  RES_FORALL_F, RES_EXISTS_T, RES_EXISTS_UNIQUE_T,
449  RES_FORALL_NULL, RES_EXISTS_NULL, RES_EXISTS_UNIQUE_NULL,
450
451  (* Conditional rewriting rules and facts. *)
452  RES_FORALL_SUBSET, RES_EXISTS_SUBSET];
453
454val RESQ_PRED_SET_ss = named_rewrites "RESQ_PRED_SET_ss" [
455  RES_FORALL_UNION, RES_EXISTS_UNION,
456  RES_FORALL_DIFF, RES_EXISTS_DIFF,
457  IN_BIGINTER_RES_FORALL, IN_BIGUNION_RES_EXISTS,
458  RES_FORALL_BIGUNION, RES_EXISTS_BIGUNION,
459  RES_FORALL_BIGINTER, RES_EXISTS_BIGINTER];
460
461(* ===================================================================== *)
462(* Functions for making definition with restrict universal quantified    *)
463(* variables.                                                            *)
464(* The auxiliary functions used here are taken from the system directly. *)
465(* --------------------------------------------------------------------- *)
466
467(* check that tm is a <varstruct> where:
468
469   <varstruct> ::= <var> | (<varstruct>,...,<varstruct>)
470
471  and that there are no repeated variables. Return list of variables.
472*)
473
474fun check_varstruct tm =
475  if is_var tm then [tm]
476  else
477   let val (t1,t2) = pairSyntax.dest_pair tm
478               handle _ => raise ERR "check_varstruct" "bad varstruct"
479
480   val l1 = check_varstruct t1
481   val l2 = check_varstruct t2
482   in
483    if null (op_intersect aconv l1 l2) then l1@l2
484    else raise ERR "check_varstruct" "repeated variable in varstruct"
485   end;
486
487(* check that tm is a <lhs> where:
488
489   <lhs> ::= <var> | <lhs> <varstruct>
490
491 and that no variables are repeated. Return list of variables.
492*)
493
494fun check_lhs tm =
495 if is_var tm then [tm] else
496 if is_const tm
497 then raise ERR "check_lhs" ("attempt to redefine the constant " ^
498                             fst (dest_const tm))
499 else if not(is_comb tm)
500 then raise ERR "check_lhs" "lhs not of form (--`x = ...`--) or (--`f x = ... `--)"
501 else
502  let val (t1,t2) = dest_comb tm
503      val l1 = check_lhs t1
504      val l2 = check_varstruct t2
505  in
506     if null (op_intersect aconv l1 l2)
507     then l1@l2
508     else raise ERR "check_lhs" "var used twice"
509  end;
510
511(*  if (--`C ... = (...:ty)`--) then  (get_type (--`C ...`--) ty) gives the
512   type of C.
513*)
514
515fun get_type left rightty =
516  if is_var left then rightty
517  else get_type (rator left)  (type_of(rand left) --> rightty)
518  handle _ => raise ERR "get_type" "bad lhs";
519
520(* ---------------------------------------------------------------------*)
521(* RESQ_DEF_EXISTS_RULE `!x1::P1. ... !xn::Pn.                          *)
522(*   C y x1 ... xn z = t[y,x1,...,xn,z]`returns a theorem which is      *)
523(* suitable to be used in new_specification                             *)
524(* If there are free variables in Pi, then Skolem conversion will be    *)
525(* done, so the constant C will become C' m where m is free in Pi.      *)
526(* ---------------------------------------------------------------------*)
527
528fun RESQ_DEF_EXISTS_RULE tm =
529    let val (gvars,tm') = strip_forall tm
530    val (ress,(lh,rh)) = ((I ## dest_eq) o strip_res_forall) tm'
531        handle _ => raise ERR "RESQ_DEF_EXISTS_RULE" "definition not an equation"
532    val leftvars = check_lhs lh val leftvars_s = listset leftvars
533    val cty = get_type lh (type_of rh)
534    val rightvars = free_vars rh val rightvars_s = listset rightvars
535    val resvars = map fst ress
536    val finpred = op_mk_set aconv (flatten (map (free_vars o snd) ress))
537    val finpred_s = listset finpred
538    val pConst = hd leftvars
539    val cname = fst(dest_var pConst)
540    in
541    if not(Lexis.allowed_term_constant cname) then
542        raise ERR "RESQ_DEF_EXISTS_RULE" (cname^" is not allowed as a constant name")
543    else if tmem pConst resvars then
544        raise ERR "RESQ_DEF_EXISTS_RULE" (cname^" is restrict bound")
545    else if not(all (fn x => tmem x leftvars) resvars) then
546        raise ERR "RESQ_DEF_EXISTS_RULE" "restrict bound var not in lhs"
547    else if
548      not(HOLset.equal((finpred_s Un leftvars_s) Isct rightvars_s, rightvars_s))
549    then
550        raise ERR "RESQ_DEF_EXISTS_RULE" "unbound var in rhs"
551    else if tmem(hd leftvars)rightvars then
552        raise ERR "RESQ_DEF_EXISTS_RULE" "recursive definitions not allowed"
553    else if not(null(subtract (type_vars_in_term rh)
554                              (type_vars_in_term pConst))) then
555        raise ERR "RESQ_DEF_EXISTS_RULE"
556          (dest_vartype(hd(subtract (type_vars_in_term rh)
557           (type_vars_in_term pConst))) ^
558           "an unbound type variable in definition")
559    else
560      let val gl = list_mk_forall (finpred,
561                    mk_exists(pConst, list_mk_res_forall
562                      (ress, list_mk_forall
563                              (op_set_diff aconv (tl leftvars) resvars,
564                               mk_eq(lh,rh)))))
565      val ex = list_mk_abs((tl leftvars), rh)
566      val defthm = prove(gl,
567        REPEAT GEN_TAC THEN EXISTS_TAC ex THEN BETA_TAC
568        THEN REPEAT RESQ_GEN_TAC THEN REPEAT GEN_TAC THEN REFL_TAC)
569      in
570       if is_forall(concl defthm)
571       then CONV_RULE SKOLEM_CONV defthm
572       else defthm
573      end
574    end
575     handle HOL_ERR {message = s,...} =>
576        raise ERR "RESQ_DEF_EXISTS_RULE" s;
577
578(* --------------------------------------------------------------------- *)
579(* new_gen_resq_definition flag (name, (--`!x1::P1. ... !xn::Pn.         *)
580(*   C y x1 ... xn z = t[y,x1,...,xn,z]`--))                             *)
581(* This makes a new constant definition via new_specification.           *)
582(*  The definition is stored in the current theory under the give name.  *)
583(*  flag specifies the syntactic status of the new constant. It should   *)
584(*    be either "constant", or "infix" or "binder".                      *)
585(* --------------------------------------------------------------------- *)
586
587open Parse
588
589fun new_gen_resq_definition flag (name, tm) = let
590  val def_thm = RESQ_DEF_EXISTS_RULE tm
591  val cname = (fst o dest_var o fst o dest_exists o concl) def_thm
592in
593
594  Rsyntax.new_specification {name=name,
595                     consts= [{fixity = flag, const_name = cname}],
596                     sat_thm = def_thm}
597end;
598
599val new_resq_definition =  new_gen_resq_definition NONE;
600
601fun new_infixl_resq_definition (name,tm,fix) =
602    new_gen_resq_definition (SOME (Infixl fix)) (name,tm);
603fun new_infixr_resq_definition (name,tm,fix) =
604    new_gen_resq_definition (SOME (Infixr fix)) (name,tm);
605
606val new_binder_resq_definition =  new_gen_resq_definition (SOME Binder);
607
608(* --------------------------------------------------------------------- *)
609(* Some restricted quantifier functions using term quotations            *)
610(* --------------------------------------------------------------------- *)
611
612fun Q_RESQ_EXISTS_TAC tm = CONV_TAC RES_EXISTS_CONV ++ Q.EXISTS_TAC tm;
613fun Q_RESQ_HALF_SPEC tm = CONV_RULE RES_FORALL_CONV THENR Q.SPEC tm;
614val Q_RESQ_HALF_SPECL = GEN_RESQ_HALF_SPECL Q.SPEC Q_RESQ_HALF_SPEC;
615fun Q_RESQ_SPEC tm = (Q_RESQ_HALF_SPEC tm THENR UNDISCH) ORELSER Q.SPEC tm;
616val Q_RESQ_SPECL = C (foldl (uncurry Q_RESQ_SPEC));
617fun Q_RESQ_HALF_ISPEC tm = CONV_RULE RES_FORALL_CONV THENR Q.ISPEC tm;
618val Q_RESQ_HALF_ISPECL = GEN_RESQ_HALF_SPECL Q.ISPEC Q_RESQ_HALF_ISPEC;
619fun Q_RESQ_ISPEC tm = (Q_RESQ_HALF_ISPEC tm THENR UNDISCH) ORELSER Q.ISPEC tm;
620val Q_RESQ_ISPECL = C (foldl (uncurry Q_RESQ_ISPEC));
621
622val _ = Parse.temp_set_grammars ambient_grammars
623
624end;
625end; (* res_quanLib *)
626
627(* Local Variables: *)
628(* fill-column: 78 *)
629(* indent-tabs-mode: nil *)
630(* End: *)
631