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