| author | blanchet | 
| Thu, 24 Jun 2010 17:25:47 +0200 | |
| changeset 37539 | c80e77e8d036 | 
| parent 37391 | 476270a6c2dc | 
| child 37678 | 0040bafffdef | 
| permissions | -rw-r--r-- | 
| 23150 | 1 | (* Title: HOL/Tools/TFL/rules.ML | 
| 2 | Author: Konrad Slind, Cambridge University Computer Laboratory | |
| 3 | ||
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 4 | Emulation of HOL inference rules for TFL. | 
| 23150 | 5 | *) | 
| 6 | ||
| 7 | signature RULES = | |
| 8 | sig | |
| 9 | val dest_thm: thm -> term list * term | |
| 10 | ||
| 11 | (* Inference rules *) | |
| 12 | val REFL: cterm -> thm | |
| 13 | val ASSUME: cterm -> thm | |
| 14 | val MP: thm -> thm -> thm | |
| 15 | val MATCH_MP: thm -> thm -> thm | |
| 16 | val CONJUNCT1: thm -> thm | |
| 17 | val CONJUNCT2: thm -> thm | |
| 18 | val CONJUNCTS: thm -> thm list | |
| 19 | val DISCH: cterm -> thm -> thm | |
| 20 | val UNDISCH: thm -> thm | |
| 21 | val SPEC: cterm -> thm -> thm | |
| 22 | val ISPEC: cterm -> thm -> thm | |
| 23 | val ISPECL: cterm list -> thm -> thm | |
| 24 | val GEN: cterm -> thm -> thm | |
| 25 | val GENL: cterm list -> thm -> thm | |
| 26 | val LIST_CONJ: thm list -> thm | |
| 27 | ||
| 28 | val SYM: thm -> thm | |
| 29 | val DISCH_ALL: thm -> thm | |
| 30 | val FILTER_DISCH_ALL: (term -> bool) -> thm -> thm | |
| 31 | val SPEC_ALL: thm -> thm | |
| 32 | val GEN_ALL: thm -> thm | |
| 33 | val IMP_TRANS: thm -> thm -> thm | |
| 34 | val PROVE_HYP: thm -> thm -> thm | |
| 35 | ||
| 36 | val CHOOSE: cterm * thm -> thm -> thm | |
| 37 | val EXISTS: cterm * cterm -> thm -> thm | |
| 38 | val EXISTL: cterm list -> thm -> thm | |
| 39 | val IT_EXISTS: (cterm*cterm) list -> thm -> thm | |
| 40 | ||
| 41 | val EVEN_ORS: thm list -> thm list | |
| 42 | val DISJ_CASESL: thm -> thm list -> thm | |
| 43 | ||
| 44 | val list_beta_conv: cterm -> cterm list -> thm | |
| 45 | val SUBS: thm list -> thm -> thm | |
| 46 | val simpl_conv: simpset -> thm list -> cterm -> thm | |
| 47 | ||
| 48 | val rbeta: thm -> thm | |
| 49 | (* For debugging my isabelle solver in the conditional rewriter *) | |
| 32740 | 50 | val term_ref: term list Unsynchronized.ref | 
| 51 | val thm_ref: thm list Unsynchronized.ref | |
| 52 | val ss_ref: simpset list Unsynchronized.ref | |
| 53 | val tracing: bool Unsynchronized.ref | |
| 23150 | 54 | val CONTEXT_REWRITE_RULE: term * term list * thm * thm list | 
| 55 | -> thm -> thm * term list | |
| 56 | val RIGHT_ASSOC: thm -> thm | |
| 57 | ||
| 58 | val prove: bool -> cterm * tactic -> thm | |
| 59 | end; | |
| 60 | ||
| 61 | structure Rules: RULES = | |
| 62 | struct | |
| 63 | ||
| 64 | structure S = USyntax; | |
| 65 | structure U = Utils; | |
| 66 | structure D = Dcterm; | |
| 67 | ||
| 68 | ||
| 69 | fun RULES_ERR func mesg = U.ERR {module = "Rules", func = func, mesg = mesg};
 | |
| 70 | ||
| 71 | ||
| 72 | fun cconcl thm = D.drop_prop (#prop (Thm.crep_thm thm)); | |
| 73 | fun chyps thm = map D.drop_prop (#hyps (Thm.crep_thm thm)); | |
| 74 | ||
| 75 | fun dest_thm thm = | |
| 76 |   let val {prop,hyps,...} = Thm.rep_thm thm
 | |
| 77 | in (map HOLogic.dest_Trueprop hyps, HOLogic.dest_Trueprop prop) end | |
| 78 | handle TERM _ => raise RULES_ERR "dest_thm" "missing Trueprop"; | |
| 79 | ||
| 80 | ||
| 81 | (* Inference rules *) | |
| 82 | ||
| 83 | (*--------------------------------------------------------------------------- | |
| 84 | * Equality (one step) | |
| 85 | *---------------------------------------------------------------------------*) | |
| 86 | ||
| 87 | fun REFL tm = Thm.reflexive tm RS meta_eq_to_obj_eq | |
| 88 | handle THM (msg, _, _) => raise RULES_ERR "REFL" msg; | |
| 89 | ||
| 90 | fun SYM thm = thm RS sym | |
| 91 | handle THM (msg, _, _) => raise RULES_ERR "SYM" msg; | |
| 92 | ||
| 93 | fun ALPHA thm ctm1 = | |
| 94 | let | |
| 95 | val ctm2 = Thm.cprop_of thm; | |
| 96 | val ctm2_eq = Thm.reflexive ctm2; | |
| 97 | val ctm1_eq = Thm.reflexive ctm1; | |
| 98 | in Thm.equal_elim (Thm.transitive ctm2_eq ctm1_eq) thm end | |
| 99 | handle THM (msg, _, _) => raise RULES_ERR "ALPHA" msg; | |
| 100 | ||
| 101 | fun rbeta th = | |
| 102 | (case D.strip_comb (cconcl th) of | |
| 103 | (_, [l, r]) => Thm.transitive th (Thm.beta_conversion false r) | |
| 104 | | _ => raise RULES_ERR "rbeta" ""); | |
| 105 | ||
| 106 | ||
| 107 | (*---------------------------------------------------------------------------- | |
| 108 | * Implication and the assumption list | |
| 109 | * | |
| 110 | * Assumptions get stuck on the meta-language assumption list. Implications | |
| 111 | * are in the object language, so discharging an assumption "A" from theorem | |
| 112 | * "B" results in something that looks like "A --> B". | |
| 113 | *---------------------------------------------------------------------------*) | |
| 114 | ||
| 115 | fun ASSUME ctm = Thm.assume (D.mk_prop ctm); | |
| 116 | ||
| 117 | ||
| 118 | (*--------------------------------------------------------------------------- | |
| 119 | * Implication in TFL is -->. Meta-language implication (==>) is only used | |
| 120 | * in the implementation of some of the inference rules below. | |
| 121 | *---------------------------------------------------------------------------*) | |
| 122 | fun MP th1 th2 = th2 RS (th1 RS mp) | |
| 123 | handle THM (msg, _, _) => raise RULES_ERR "MP" msg; | |
| 124 | ||
| 125 | (*forces the first argument to be a proposition if necessary*) | |
| 126 | fun DISCH tm thm = Thm.implies_intr (D.mk_prop tm) thm COMP impI | |
| 127 | handle THM (msg, _, _) => raise RULES_ERR "DISCH" msg; | |
| 128 | ||
| 129 | fun DISCH_ALL thm = fold_rev DISCH (#hyps (Thm.crep_thm thm)) thm; | |
| 130 | ||
| 131 | ||
| 132 | fun FILTER_DISCH_ALL P thm = | |
| 133 | let fun check tm = P (#t (Thm.rep_cterm tm)) | |
| 33339 | 134 | in fold_rev (fn tm => fn th => if check tm then DISCH tm th else th) (chyps thm) thm | 
| 23150 | 135 | end; | 
| 136 | ||
| 137 | fun UNDISCH thm = | |
| 36617 
ed8083930203
UNDISCH/DISJ_CASESL: eliminated slightly odd Thm.legacy_freezeT -- these rules appear to be applied to thms with fixed types only;
 wenzelm parents: 
36615diff
changeset | 138 | let val tm = D.mk_prop (#1 (D.dest_imp (cconcl thm))) | 
| 23150 | 139 | in Thm.implies_elim (thm RS mp) (ASSUME tm) end | 
| 140 | handle U.ERR _ => raise RULES_ERR "UNDISCH" "" | |
| 141 | | THM _ => raise RULES_ERR "UNDISCH" ""; | |
| 142 | ||
| 143 | fun PROVE_HYP ath bth = MP (DISCH (cconcl ath) bth) ath; | |
| 144 | ||
| 145 | fun IMP_TRANS th1 th2 = th2 RS (th1 RS Thms.imp_trans) | |
| 146 | handle THM (msg, _, _) => raise RULES_ERR "IMP_TRANS" msg; | |
| 147 | ||
| 148 | ||
| 149 | (*---------------------------------------------------------------------------- | |
| 150 | * Conjunction | |
| 151 | *---------------------------------------------------------------------------*) | |
| 152 | ||
| 153 | fun CONJUNCT1 thm = thm RS conjunct1 | |
| 154 | handle THM (msg, _, _) => raise RULES_ERR "CONJUNCT1" msg; | |
| 155 | ||
| 156 | fun CONJUNCT2 thm = thm RS conjunct2 | |
| 157 | handle THM (msg, _, _) => raise RULES_ERR "CONJUNCT2" msg; | |
| 158 | ||
| 159 | fun CONJUNCTS th = CONJUNCTS (CONJUNCT1 th) @ CONJUNCTS (CONJUNCT2 th) handle U.ERR _ => [th]; | |
| 160 | ||
| 161 | fun LIST_CONJ [] = raise RULES_ERR "LIST_CONJ" "empty list" | |
| 162 | | LIST_CONJ [th] = th | |
| 163 | | LIST_CONJ (th :: rst) = MP (MP (conjI COMP (impI RS impI)) th) (LIST_CONJ rst) | |
| 164 | handle THM (msg, _, _) => raise RULES_ERR "LIST_CONJ" msg; | |
| 165 | ||
| 166 | ||
| 167 | (*---------------------------------------------------------------------------- | |
| 168 | * Disjunction | |
| 169 | *---------------------------------------------------------------------------*) | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 170 | local val thy = Thm.theory_of_thm disjI1 | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 171 | val prop = Thm.prop_of disjI1 | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 172 | val [P,Q] = OldTerm.term_vars prop | 
| 23150 | 173 | val disj1 = Thm.forall_intr (Thm.cterm_of thy Q) disjI1 | 
| 174 | in | |
| 36945 | 175 | fun DISJ1 thm tm = thm RS (Thm.forall_elim (D.drop_prop tm) disj1) | 
| 23150 | 176 | handle THM (msg, _, _) => raise RULES_ERR "DISJ1" msg; | 
| 177 | end; | |
| 178 | ||
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 179 | local val thy = Thm.theory_of_thm disjI2 | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 180 | val prop = Thm.prop_of disjI2 | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 181 | val [P,Q] = OldTerm.term_vars prop | 
| 23150 | 182 | val disj2 = Thm.forall_intr (Thm.cterm_of thy P) disjI2 | 
| 183 | in | |
| 36945 | 184 | fun DISJ2 tm thm = thm RS (Thm.forall_elim (D.drop_prop tm) disj2) | 
| 23150 | 185 | handle THM (msg, _, _) => raise RULES_ERR "DISJ2" msg; | 
| 186 | end; | |
| 187 | ||
| 188 | ||
| 189 | (*---------------------------------------------------------------------------- | |
| 190 | * | |
| 191 | * A1 |- M1, ..., An |- Mn | |
| 192 | * --------------------------------------------------- | |
| 193 | * [A1 |- M1 \/ ... \/ Mn, ..., An |- M1 \/ ... \/ Mn] | |
| 194 | * | |
| 195 | *---------------------------------------------------------------------------*) | |
| 196 | ||
| 197 | ||
| 198 | fun EVEN_ORS thms = | |
| 199 | let fun blue ldisjs [] _ = [] | |
| 200 | | blue ldisjs (th::rst) rdisjs = | |
| 201 | let val tail = tl rdisjs | |
| 202 | val rdisj_tl = D.list_mk_disj tail | |
| 203 | in fold_rev DISJ2 ldisjs (DISJ1 th rdisj_tl) | |
| 204 | :: blue (ldisjs @ [cconcl th]) rst tail | |
| 205 | end handle U.ERR _ => [fold_rev DISJ2 ldisjs th] | |
| 206 | in blue [] thms (map cconcl thms) end; | |
| 207 | ||
| 208 | ||
| 209 | (*---------------------------------------------------------------------------- | |
| 210 | * | |
| 211 | * A |- P \/ Q B,P |- R C,Q |- R | |
| 212 | * --------------------------------------------------- | |
| 213 | * A U B U C |- R | |
| 214 | * | |
| 215 | *---------------------------------------------------------------------------*) | |
| 216 | ||
| 217 | fun DISJ_CASES th1 th2 th3 = | |
| 218 | let | |
| 219 | val c = D.drop_prop (cconcl th1); | |
| 220 | val (disj1, disj2) = D.dest_disj c; | |
| 221 | val th2' = DISCH disj1 th2; | |
| 222 | val th3' = DISCH disj2 th3; | |
| 223 | in | |
| 224 | th3' RS (th2' RS (th1 RS Thms.tfl_disjE)) | |
| 225 | handle THM (msg, _, _) => raise RULES_ERR "DISJ_CASES" msg | |
| 226 | end; | |
| 227 | ||
| 228 | ||
| 229 | (*----------------------------------------------------------------------------- | |
| 230 | * | |
| 231 | * |- A1 \/ ... \/ An [A1 |- M, ..., An |- M] | |
| 232 | * --------------------------------------------------- | |
| 233 | * |- M | |
| 234 | * | |
| 235 | * Note. The list of theorems may be all jumbled up, so we have to | |
| 236 | * first organize it to align with the first argument (the disjunctive | |
| 237 | * theorem). | |
| 238 | *---------------------------------------------------------------------------*) | |
| 239 | ||
| 240 | fun organize eq = (* a bit slow - analogous to insertion sort *) | |
| 241 | let fun extract a alist = | |
| 242 | let fun ex (_,[]) = raise RULES_ERR "organize" "not a permutation.1" | |
| 243 | | ex(left,h::t) = if (eq h a) then (h,rev left@t) else ex(h::left,t) | |
| 244 | in ex ([],alist) | |
| 245 | end | |
| 246 | fun place [] [] = [] | |
| 247 | | place (a::rst) alist = | |
| 248 | let val (item,next) = extract a alist | |
| 249 | in item::place rst next | |
| 250 | end | |
| 251 | | place _ _ = raise RULES_ERR "organize" "not a permutation.2" | |
| 252 | in place | |
| 253 | end; | |
| 36617 
ed8083930203
UNDISCH/DISJ_CASESL: eliminated slightly odd Thm.legacy_freezeT -- these rules appear to be applied to thms with fixed types only;
 wenzelm parents: 
36615diff
changeset | 254 | |
| 23150 | 255 | fun DISJ_CASESL disjth thl = | 
| 256 | let val c = cconcl disjth | |
| 257 | fun eq th atm = exists (fn t => HOLogic.dest_Trueprop t | |
| 258 | aconv term_of atm) | |
| 259 | (#hyps(rep_thm th)) | |
| 260 | val tml = D.strip_disj c | |
| 261 | fun DL th [] = raise RULES_ERR "DISJ_CASESL" "no cases" | |
| 262 | | DL th [th1] = PROVE_HYP th th1 | |
| 263 | | DL th [th1,th2] = DISJ_CASES th th1 th2 | |
| 264 | | DL th (th1::rst) = | |
| 265 | let val tm = #2(D.dest_disj(D.drop_prop(cconcl th))) | |
| 266 | in DISJ_CASES th th1 (DL (ASSUME tm) rst) end | |
| 36617 
ed8083930203
UNDISCH/DISJ_CASESL: eliminated slightly odd Thm.legacy_freezeT -- these rules appear to be applied to thms with fixed types only;
 wenzelm parents: 
36615diff
changeset | 267 | in DL disjth (organize eq tml thl) | 
| 23150 | 268 | end; | 
| 269 | ||
| 270 | ||
| 271 | (*---------------------------------------------------------------------------- | |
| 272 | * Universals | |
| 273 | *---------------------------------------------------------------------------*) | |
| 274 | local (* this is fragile *) | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 275 | val thy = Thm.theory_of_thm spec | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 276 | val prop = Thm.prop_of spec | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 277 | val x = hd (tl (OldTerm.term_vars prop)) | 
| 23150 | 278 | val cTV = ctyp_of thy (type_of x) | 
| 36945 | 279 | val gspec = Thm.forall_intr (cterm_of thy x) spec | 
| 23150 | 280 | in | 
| 281 | fun SPEC tm thm = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 282 | let val gspec' = instantiate ([(cTV, Thm.ctyp_of_term tm)], []) gspec | 
| 36945 | 283 | in thm RS (Thm.forall_elim tm gspec') end | 
| 23150 | 284 | end; | 
| 285 | ||
| 286 | fun SPEC_ALL thm = fold SPEC (#1(D.strip_forall(cconcl thm))) thm; | |
| 287 | ||
| 288 | val ISPEC = SPEC | |
| 289 | val ISPECL = fold ISPEC; | |
| 290 | ||
| 291 | (* Not optimized! Too complicated. *) | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 292 | local val thy = Thm.theory_of_thm allI | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 293 | val prop = Thm.prop_of allI | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 294 | val [P] = OldTerm.add_term_vars (prop, []) | 
| 23150 | 295 | fun cty_theta s = map (fn (i, (S, ty)) => (ctyp_of s (TVar (i, S)), ctyp_of s ty)) | 
| 296 | fun ctm_theta s = map (fn (i, (_, tm2)) => | |
| 297 | let val ctm2 = cterm_of s tm2 | |
| 298 | in (cterm_of s (Var(i,#T(rep_cterm ctm2))), ctm2) | |
| 299 | end) | |
| 300 | fun certify s (ty_theta,tm_theta) = | |
| 301 | (cty_theta s (Vartab.dest ty_theta), | |
| 302 | ctm_theta s (Vartab.dest tm_theta)) | |
| 303 | in | |
| 304 | fun GEN v th = | |
| 36945 | 305 | let val gth = Thm.forall_intr v th | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 306 | val thy = Thm.theory_of_thm gth | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 307 |        val Const("all",_)$Abs(x,ty,rst) = Thm.prop_of gth
 | 
| 23150 | 308 | val P' = Abs(x,ty, HOLogic.dest_Trueprop rst) (* get rid of trueprop *) | 
| 309 | val theta = Pattern.match thy (P,P') (Vartab.empty, Vartab.empty); | |
| 310 | val allI2 = instantiate (certify thy theta) allI | |
| 311 | val thm = Thm.implies_elim allI2 gth | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 312 | val tp $ (A $ Abs(_,_,M)) = Thm.prop_of thm | 
| 23150 | 313 | val prop' = tp $ (A $ Abs(x,ty,M)) | 
| 314 | in ALPHA thm (cterm_of thy prop') | |
| 315 | end | |
| 316 | end; | |
| 317 | ||
| 318 | val GENL = fold_rev GEN; | |
| 319 | ||
| 320 | fun GEN_ALL thm = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 321 | let val thy = Thm.theory_of_thm thm | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 322 | val prop = Thm.prop_of thm | 
| 23150 | 323 | val tycheck = cterm_of thy | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 324 | val vlist = map tycheck (OldTerm.add_term_vars (prop, [])) | 
| 23150 | 325 | in GENL vlist thm | 
| 326 | end; | |
| 327 | ||
| 328 | ||
| 329 | fun MATCH_MP th1 th2 = | |
| 330 | if (D.is_forall (D.drop_prop(cconcl th1))) | |
| 331 | then MATCH_MP (th1 RS spec) th2 | |
| 332 | else MP th1 th2; | |
| 333 | ||
| 334 | ||
| 335 | (*---------------------------------------------------------------------------- | |
| 336 | * Existentials | |
| 337 | *---------------------------------------------------------------------------*) | |
| 338 | ||
| 339 | ||
| 340 | ||
| 341 | (*--------------------------------------------------------------------------- | |
| 342 | * Existential elimination | |
| 343 | * | |
| 344 | * A1 |- ?x.t[x] , A2, "t[v]" |- t' | |
| 345 | * ------------------------------------ (variable v occurs nowhere) | |
| 346 | * A1 u A2 |- t' | |
| 347 | * | |
| 348 | *---------------------------------------------------------------------------*) | |
| 349 | ||
| 350 | fun CHOOSE (fvar, exth) fact = | |
| 351 | let | |
| 352 | val lam = #2 (D.dest_comb (D.drop_prop (cconcl exth))) | |
| 353 | val redex = D.capply lam fvar | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 354 | val thy = Thm.theory_of_cterm redex | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 355 | val t$u = Thm.term_of redex | 
| 23150 | 356 | val residue = Thm.cterm_of thy (Term.betapply (t, u)) | 
| 357 | in | |
| 358 | GEN fvar (DISCH residue fact) RS (exth RS Thms.choose_thm) | |
| 359 | handle THM (msg, _, _) => raise RULES_ERR "CHOOSE" msg | |
| 360 | end; | |
| 361 | ||
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 362 | local val thy = Thm.theory_of_thm exI | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 363 | val prop = Thm.prop_of exI | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 364 | val [P,x] = OldTerm.term_vars prop | 
| 23150 | 365 | in | 
| 366 | fun EXISTS (template,witness) thm = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 367 | let val thy = Thm.theory_of_thm thm | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 368 | val prop = Thm.prop_of thm | 
| 23150 | 369 | val P' = cterm_of thy P | 
| 370 | val x' = cterm_of thy x | |
| 371 | val abstr = #2 (D.dest_comb template) | |
| 372 | in | |
| 373 | thm RS (cterm_instantiate[(P',abstr), (x',witness)] exI) | |
| 374 | handle THM (msg, _, _) => raise RULES_ERR "EXISTS" msg | |
| 375 | end | |
| 376 | end; | |
| 377 | ||
| 378 | (*---------------------------------------------------------------------------- | |
| 379 | * | |
| 380 | * A |- M | |
| 381 | * ------------------- [v_1,...,v_n] | |
| 382 | * A |- ?v1...v_n. M | |
| 383 | * | |
| 384 | *---------------------------------------------------------------------------*) | |
| 385 | ||
| 386 | fun EXISTL vlist th = | |
| 387 | fold_rev (fn v => fn thm => EXISTS(D.mk_exists(v,cconcl thm), v) thm) | |
| 388 | vlist th; | |
| 389 | ||
| 390 | ||
| 391 | (*---------------------------------------------------------------------------- | |
| 392 | * | |
| 393 | * A |- M[x_1,...,x_n] | |
| 394 | * ---------------------------- [(x |-> y)_1,...,(x |-> y)_n] | |
| 395 | * A |- ?y_1...y_n. M | |
| 396 | * | |
| 397 | *---------------------------------------------------------------------------*) | |
| 398 | (* Could be improved, but needs "subst_free" for certified terms *) | |
| 399 | ||
| 400 | fun IT_EXISTS blist th = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 401 | let val thy = Thm.theory_of_thm th | 
| 23150 | 402 | val tych = cterm_of thy | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 403 | val blist' = map (pairself Thm.term_of) blist | 
| 23150 | 404 |        fun ex v M  = cterm_of thy (S.mk_exists{Bvar=v,Body = M})
 | 
| 405 | ||
| 406 | in | |
| 407 | fold_rev (fn (b as (r1,r2)) => fn thm => | |
| 408 | EXISTS(ex r2 (subst_free [b] | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 409 | (HOLogic.dest_Trueprop(Thm.prop_of thm))), tych r1) | 
| 23150 | 410 | thm) | 
| 411 | blist' th | |
| 412 | end; | |
| 413 | ||
| 414 | (*--------------------------------------------------------------------------- | |
| 415 | * Faster version, that fails for some as yet unknown reason | |
| 416 | * fun IT_EXISTS blist th = | |
| 417 |  *    let val {thy,...} = rep_thm th
 | |
| 418 | * val tych = cterm_of thy | |
| 419 | * fun detype (x,y) = ((#t o rep_cterm) x, (#t o rep_cterm) y) | |
| 420 | * in | |
| 421 | * fold (fn (b as (r1,r2), thm) => | |
| 422 | * EXISTS(D.mk_exists(r2, tych(subst_free[detype b](#t(rep_cterm(cconcl thm))))), | |
| 423 | * r1) thm) blist th | |
| 424 | * end; | |
| 425 | *---------------------------------------------------------------------------*) | |
| 426 | ||
| 427 | (*---------------------------------------------------------------------------- | |
| 428 | * Rewriting | |
| 429 | *---------------------------------------------------------------------------*) | |
| 430 | ||
| 431 | fun SUBS thl = | |
| 432 | rewrite_rule (map (fn th => th RS eq_reflection handle THM _ => th) thl); | |
| 433 | ||
| 434 | val rew_conv = MetaSimplifier.rewrite_cterm (true, false, false) (K (K NONE)); | |
| 435 | ||
| 436 | fun simpl_conv ss thl ctm = | |
| 437 | rew_conv (ss addsimps thl) ctm RS meta_eq_to_obj_eq; | |
| 438 | ||
| 439 | ||
| 440 | val RIGHT_ASSOC = rewrite_rule [Thms.disj_assoc]; | |
| 441 | ||
| 442 | ||
| 443 | ||
| 444 | (*--------------------------------------------------------------------------- | |
| 445 | * TERMINATION CONDITION EXTRACTION | |
| 446 | *---------------------------------------------------------------------------*) | |
| 447 | ||
| 448 | ||
| 449 | (* Object language quantifier, i.e., "!" *) | |
| 450 | fun Forall v M = S.mk_forall{Bvar=v, Body=M};
 | |
| 451 | ||
| 452 | ||
| 453 | (* Fragile: it's a cong if it is not "R y x ==> cut f R x y = f y" *) | |
| 454 | fun is_cong thm = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 455 | case (Thm.prop_of thm) | 
| 23150 | 456 |      of (Const("==>",_)$(Const("Trueprop",_)$ _) $
 | 
| 32603 | 457 |          (Const("==",_) $ (Const (@{const_name Recdef.cut},_) $ f $ R $ a $ x) $ _)) => false
 | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 458 | | _ => true; | 
| 23150 | 459 | |
| 460 | ||
| 461 | fun dest_equal(Const ("==",_) $
 | |
| 462 |                (Const ("Trueprop",_) $ lhs)
 | |
| 463 |                $ (Const ("Trueprop",_) $ rhs)) = {lhs=lhs, rhs=rhs}
 | |
| 464 |   | dest_equal(Const ("==",_) $ lhs $ rhs)  = {lhs=lhs, rhs=rhs}
 | |
| 465 | | dest_equal tm = S.dest_eq tm; | |
| 466 | ||
| 467 | fun get_lhs tm = #lhs(dest_equal (HOLogic.dest_Trueprop tm)); | |
| 468 | ||
| 469 | fun dest_all used (Const("all",_) $ (a as Abs _)) = S.dest_abs used a
 | |
| 470 | | dest_all _ _ = raise RULES_ERR "dest_all" "not a !!"; | |
| 471 | ||
| 472 | val is_all = can (dest_all []); | |
| 473 | ||
| 474 | fun strip_all used fm = | |
| 475 | if (is_all fm) | |
| 476 |    then let val ({Bvar, Body}, used') = dest_all used fm
 | |
| 477 | val (bvs, core, used'') = strip_all used' Body | |
| 478 | in ((Bvar::bvs), core, used'') | |
| 479 | end | |
| 480 | else ([], fm, used); | |
| 481 | ||
| 482 | fun break_all(Const("all",_) $ Abs (_,_,body)) = body
 | |
| 483 | | break_all _ = raise RULES_ERR "break_all" "not a !!"; | |
| 484 | ||
| 485 | fun list_break_all(Const("all",_) $ Abs (s,ty,body)) =
 | |
| 486 | let val (L,core) = list_break_all body | |
| 487 | in ((s,ty)::L, core) | |
| 488 | end | |
| 489 | | list_break_all tm = ([],tm); | |
| 490 | ||
| 491 | (*--------------------------------------------------------------------------- | |
| 492 | * Rename a term of the form | |
| 493 | * | |
| 494 | * !!x1 ...xn. x1=M1 ==> ... ==> xn=Mn | |
| 495 | * ==> ((%v1...vn. Q) x1 ... xn = g x1 ... xn. | |
| 496 | * to one of | |
| 497 | * | |
| 498 | * !!v1 ... vn. v1=M1 ==> ... ==> vn=Mn | |
| 499 | * ==> ((%v1...vn. Q) v1 ... vn = g v1 ... vn. | |
| 500 | * | |
| 501 | * This prevents name problems in extraction, and helps the result to read | |
| 502 | * better. There is a problem with varstructs, since they can introduce more | |
| 503 | * than n variables, and some extra reasoning needs to be done. | |
| 504 | *---------------------------------------------------------------------------*) | |
| 505 | ||
| 506 | fun get ([],_,L) = rev L | |
| 507 | | get (ant::rst,n,L) = | |
| 508 | case (list_break_all ant) | |
| 509 | of ([],_) => get (rst, n+1,L) | |
| 510 | | (vlist,body) => | |
| 511 | let val eq = Logic.strip_imp_concl body | |
| 512 | val (f,args) = S.strip_comb (get_lhs eq) | |
| 513 | val (vstrl,_) = S.strip_abs f | |
| 514 | val names = | |
| 29270 
0eade173f77e
moved old add_type_XXX, add_term_XXX etc. to structure OldTerm;
 wenzelm parents: 
29265diff
changeset | 515 | Name.variant_list (OldTerm.add_term_names(body, [])) (map (#1 o dest_Free) vstrl) | 
| 23150 | 516 | in get (rst, n+1, (names,n)::L) end | 
| 517 | handle TERM _ => get (rst, n+1, L) | |
| 518 | | U.ERR _ => get (rst, n+1, L); | |
| 519 | ||
| 31945 | 520 | (* Note: Thm.rename_params_rule counts from 1, not 0 *) | 
| 23150 | 521 | fun rename thm = | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 522 | let val thy = Thm.theory_of_thm thm | 
| 23150 | 523 | val tych = cterm_of thy | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 524 | val ants = Logic.strip_imp_prems (Thm.prop_of thm) | 
| 23150 | 525 | val news = get (ants,1,[]) | 
| 526 | in | |
| 31945 | 527 | fold Thm.rename_params_rule news thm | 
| 23150 | 528 | end; | 
| 529 | ||
| 530 | ||
| 531 | (*--------------------------------------------------------------------------- | |
| 532 | * Beta-conversion to the rhs of an equation (taken from hol90/drule.sml) | |
| 533 | *---------------------------------------------------------------------------*) | |
| 534 | ||
| 535 | fun list_beta_conv tm = | |
| 36945 | 536 | let fun rbeta th = Thm.transitive th (Thm.beta_conversion false (#2(D.dest_eq(cconcl th)))) | 
| 23150 | 537 | fun iter [] = Thm.reflexive tm | 
| 36945 | 538 | | iter (v::rst) = rbeta (Thm.combination(iter rst) (Thm.reflexive v)) | 
| 23150 | 539 | in iter end; | 
| 540 | ||
| 541 | ||
| 542 | (*--------------------------------------------------------------------------- | |
| 543 | * Trace information for the rewriter | |
| 544 | *---------------------------------------------------------------------------*) | |
| 32740 | 545 | val term_ref = Unsynchronized.ref [] : term list Unsynchronized.ref | 
| 546 | val ss_ref = Unsynchronized.ref [] : simpset list Unsynchronized.ref; | |
| 547 | val thm_ref = Unsynchronized.ref [] : thm list Unsynchronized.ref; | |
| 548 | val tracing = Unsynchronized.ref false; | |
| 23150 | 549 | |
| 550 | fun say s = if !tracing then writeln s else (); | |
| 551 | ||
| 552 | fun print_thms s L = | |
| 32091 
30e2ffbba718
proper context for Display.pretty_thm etc. or old-style versions Display.pretty_thm_global, Display.pretty_thm_without_context etc.;
 wenzelm parents: 
31945diff
changeset | 553 | say (cat_lines (s :: map Display.string_of_thm_without_context L)); | 
| 23150 | 554 | |
| 32429 
54758ca53fd6
modernized messages -- eliminated old Display.print_cterm;
 wenzelm parents: 
32091diff
changeset | 555 | fun print_cterm s ct = | 
| 
54758ca53fd6
modernized messages -- eliminated old Display.print_cterm;
 wenzelm parents: 
32091diff
changeset | 556 | say (cat_lines [s, Syntax.string_of_term_global (Thm.theory_of_cterm ct) (Thm.term_of ct)]); | 
| 23150 | 557 | |
| 558 | ||
| 559 | (*--------------------------------------------------------------------------- | |
| 560 | * General abstraction handlers, should probably go in USyntax. | |
| 561 | *---------------------------------------------------------------------------*) | |
| 562 | fun mk_aabs (vstr, body) = | |
| 563 |   S.mk_abs {Bvar = vstr, Body = body}
 | |
| 564 |   handle U.ERR _ => S.mk_pabs {varstruct = vstr, body = body};
 | |
| 565 | ||
| 566 | fun list_mk_aabs (vstrl,tm) = | |
| 567 | fold_rev (fn vstr => fn tm => mk_aabs(vstr,tm)) vstrl tm; | |
| 568 | ||
| 569 | fun dest_aabs used tm = | |
| 570 |    let val ({Bvar,Body}, used') = S.dest_abs used tm
 | |
| 571 | in (Bvar, Body, used') end | |
| 572 | handle U.ERR _ => | |
| 573 |      let val {varstruct, body, used} = S.dest_pabs used tm
 | |
| 574 | in (varstruct, body, used) end; | |
| 575 | ||
| 576 | fun strip_aabs used tm = | |
| 577 | let val (vstr, body, used') = dest_aabs used tm | |
| 578 | val (bvs, core, used'') = strip_aabs used' body | |
| 579 | in (vstr::bvs, core, used'') end | |
| 580 | handle U.ERR _ => ([], tm, used); | |
| 581 | ||
| 582 | fun dest_combn tm 0 = (tm,[]) | |
| 583 | | dest_combn tm n = | |
| 584 |      let val {Rator,Rand} = S.dest_comb tm
 | |
| 585 | val (f,rands) = dest_combn Rator (n-1) | |
| 586 | in (f,Rand::rands) | |
| 587 | end; | |
| 588 | ||
| 589 | ||
| 590 | ||
| 591 | ||
| 592 | local fun dest_pair M = let val {fst,snd} = S.dest_pair M in (fst,snd) end
 | |
| 593 | fun mk_fst tm = | |
| 37391 | 594 |           let val ty as Type("Product_Type.*", [fty,sty]) = type_of tm
 | 
| 595 |           in  Const ("Product_Type.fst", ty --> fty) $ tm  end
 | |
| 23150 | 596 | fun mk_snd tm = | 
| 37391 | 597 |           let val ty as Type("Product_Type.*", [fty,sty]) = type_of tm
 | 
| 598 |           in  Const ("Product_Type.snd", ty --> sty) $ tm  end
 | |
| 23150 | 599 | in | 
| 600 | fun XFILL tych x vstruct = | |
| 601 | let fun traverse p xocc L = | |
| 602 | if (is_Free p) | |
| 603 | then tych xocc::L | |
| 604 | else let val (p1,p2) = dest_pair p | |
| 605 | in traverse p1 (mk_fst xocc) (traverse p2 (mk_snd xocc) L) | |
| 606 | end | |
| 607 | in | |
| 608 | traverse vstruct x [] | |
| 609 | end end; | |
| 610 | ||
| 611 | (*--------------------------------------------------------------------------- | |
| 612 | * Replace a free tuple (vstr) by a universally quantified variable (a). | |
| 613 | * Note that the notion of "freeness" for a tuple is different than for a | |
| 614 | * variable: if variables in the tuple also occur in any other place than | |
| 615 | * an occurrences of the tuple, they aren't "free" (which is thus probably | |
| 616 | * the wrong word to use). | |
| 617 | *---------------------------------------------------------------------------*) | |
| 618 | ||
| 619 | fun VSTRUCT_ELIM tych a vstr th = | |
| 620 | let val L = S.free_vars_lr vstr | |
| 621 | val bind1 = tych (HOLogic.mk_Trueprop (HOLogic.mk_eq(a,vstr))) | |
| 36945 | 622 | val thm1 = Thm.implies_intr bind1 (SUBS [SYM(Thm.assume bind1)] th) | 
| 23150 | 623 | val thm2 = forall_intr_list (map tych L) thm1 | 
| 624 | val thm3 = forall_elim_list (XFILL tych a vstr) thm2 | |
| 625 | in refl RS | |
| 37136 | 626 |      rewrite_rule [Thm.symmetric (@{thm surjective_pairing} RS eq_reflection)] thm3
 | 
| 23150 | 627 | end; | 
| 628 | ||
| 629 | fun PGEN tych a vstr th = | |
| 630 | let val a1 = tych a | |
| 631 | val vstr1 = tych vstr | |
| 632 | in | |
| 36945 | 633 | Thm.forall_intr a1 | 
| 23150 | 634 | (if (is_Free vstr) | 
| 635 | then cterm_instantiate [(vstr1,a1)] th | |
| 636 | else VSTRUCT_ELIM tych a vstr th) | |
| 637 | end; | |
| 638 | ||
| 639 | ||
| 640 | (*--------------------------------------------------------------------------- | |
| 641 | * Takes apart a paired beta-redex, looking like "(\(x,y).N) vstr", into | |
| 642 | * | |
| 643 | * (([x,y],N),vstr) | |
| 644 | *---------------------------------------------------------------------------*) | |
| 645 | fun dest_pbeta_redex used M n = | |
| 646 | let val (f,args) = dest_combn M n | |
| 647 | val dummy = dest_aabs used f | |
| 648 | in (strip_aabs used f,args) | |
| 649 | end; | |
| 650 | ||
| 651 | fun pbeta_redex M n = can (U.C (dest_pbeta_redex []) n) M; | |
| 652 | ||
| 653 | fun dest_impl tm = | |
| 654 | let val ants = Logic.strip_imp_prems tm | |
| 655 | val eq = Logic.strip_imp_concl tm | |
| 656 | in (ants,get_lhs eq) | |
| 657 | end; | |
| 658 | ||
| 33035 | 659 | fun restricted t = is_some (S.find_term | 
| 32603 | 660 |                             (fn (Const(@{const_name Recdef.cut},_)) =>true | _ => false)
 | 
| 23150 | 661 | t) | 
| 662 | ||
| 663 | fun CONTEXT_REWRITE_RULE (func, G, cut_lemma, congs) th = | |
| 664 | let val globals = func::G | |
| 35232 
f588e1169c8b
renamed Simplifier.theory_context to Simplifier.global_context to emphasize that this is not the real thing;
 wenzelm parents: 
33339diff
changeset | 665 | val ss0 = Simplifier.global_context (Thm.theory_of_thm th) empty_ss | 
| 37136 | 666 |      val pbeta_reduce = simpl_conv ss0 [@{thm split_conv} RS eq_reflection];
 | 
| 32740 | 667 | val tc_list = Unsynchronized.ref []: term list Unsynchronized.ref | 
| 23150 | 668 | val dummy = term_ref := [] | 
| 669 | val dummy = thm_ref := [] | |
| 670 | val dummy = ss_ref := [] | |
| 671 | val cut_lemma' = cut_lemma RS eq_reflection | |
| 672 | fun prover used ss thm = | |
| 673 | let fun cong_prover ss thm = | |
| 674 | let val dummy = say "cong_prover:" | |
| 29302 | 675 | val cntxt = Simplifier.prems_of_ss ss | 
| 23150 | 676 | val dummy = print_thms "cntxt:" cntxt | 
| 677 | val dummy = say "cong rule:" | |
| 32091 
30e2ffbba718
proper context for Display.pretty_thm etc. or old-style versions Display.pretty_thm_global, Display.pretty_thm_without_context etc.;
 wenzelm parents: 
31945diff
changeset | 678 | val dummy = say (Display.string_of_thm_without_context thm) | 
| 23150 | 679 | val dummy = thm_ref := (thm :: !thm_ref) | 
| 680 | val dummy = ss_ref := (ss :: !ss_ref) | |
| 681 | (* Unquantified eliminate *) | |
| 682 | fun uq_eliminate (thm,imp,thy) = | |
| 683 | let val tych = cterm_of thy | |
| 32429 
54758ca53fd6
modernized messages -- eliminated old Display.print_cterm;
 wenzelm parents: 
32091diff
changeset | 684 | val dummy = print_cterm "To eliminate:" (tych imp) | 
| 23150 | 685 | val ants = map tych (Logic.strip_imp_prems imp) | 
| 686 | val eq = Logic.strip_imp_concl imp | |
| 687 | val lhs = tych(get_lhs eq) | |
| 29302 | 688 | val ss' = Simplifier.add_prems (map ASSUME ants) ss | 
| 23150 | 689 | val lhs_eq_lhs1 = MetaSimplifier.rewrite_cterm (false,true,false) (prover used) ss' lhs | 
| 690 | handle U.ERR _ => Thm.reflexive lhs | |
| 691 | val dummy = print_thms "proven:" [lhs_eq_lhs1] | |
| 692 | val lhs_eq_lhs2 = implies_intr_list ants lhs_eq_lhs1 | |
| 693 | val lhs_eeq_lhs2 = lhs_eq_lhs2 RS meta_eq_to_obj_eq | |
| 694 | in | |
| 695 | lhs_eeq_lhs2 COMP thm | |
| 696 | end | |
| 697 | fun pq_eliminate (thm,thy,vlist,imp_body,lhs_eq) = | |
| 698 | let val ((vstrl, _, used'), args) = dest_pbeta_redex used lhs_eq (length vlist) | |
| 699 | val dummy = forall (op aconv) (ListPair.zip (vlist, args)) | |
| 700 | orelse error "assertion failed in CONTEXT_REWRITE_RULE" | |
| 701 | val imp_body1 = subst_free (ListPair.zip (args, vstrl)) | |
| 702 | imp_body | |
| 703 | val tych = cterm_of thy | |
| 704 | val ants1 = map tych (Logic.strip_imp_prems imp_body1) | |
| 705 | val eq1 = Logic.strip_imp_concl imp_body1 | |
| 706 | val Q = get_lhs eq1 | |
| 707 | val QeqQ1 = pbeta_reduce (tych Q) | |
| 708 | val Q1 = #2(D.dest_eq(cconcl QeqQ1)) | |
| 29302 | 709 | val ss' = Simplifier.add_prems (map ASSUME ants1) ss | 
| 23150 | 710 | val Q1eeqQ2 = MetaSimplifier.rewrite_cterm (false,true,false) (prover used') ss' Q1 | 
| 711 | handle U.ERR _ => Thm.reflexive Q1 | |
| 712 | val Q2 = #2 (Logic.dest_equals (Thm.prop_of Q1eeqQ2)) | |
| 713 | val Q3 = tych(list_comb(list_mk_aabs(vstrl,Q2),vstrl)) | |
| 714 | val Q2eeqQ3 = Thm.symmetric(pbeta_reduce Q3 RS eq_reflection) | |
| 715 | val thA = Thm.transitive(QeqQ1 RS eq_reflection) Q1eeqQ2 | |
| 716 | val QeeqQ3 = Thm.transitive thA Q2eeqQ3 handle THM _ => | |
| 717 | ((Q2eeqQ3 RS meta_eq_to_obj_eq) | |
| 718 | RS ((thA RS meta_eq_to_obj_eq) RS trans)) | |
| 719 | RS eq_reflection | |
| 720 | val impth = implies_intr_list ants1 QeeqQ3 | |
| 721 | val impth1 = impth RS meta_eq_to_obj_eq | |
| 722 | (* Need to abstract *) | |
| 723 | val ant_th = U.itlist2 (PGEN tych) args vstrl impth1 | |
| 724 | in ant_th COMP thm | |
| 725 | end | |
| 726 | fun q_eliminate (thm,imp,thy) = | |
| 727 | let val (vlist, imp_body, used') = strip_all used imp | |
| 728 | val (ants,Q) = dest_impl imp_body | |
| 729 | in if (pbeta_redex Q) (length vlist) | |
| 730 | then pq_eliminate (thm,thy,vlist,imp_body,Q) | |
| 731 | else | |
| 732 | let val tych = cterm_of thy | |
| 733 | val ants1 = map tych ants | |
| 734 | val ss' = MetaSimplifier.add_prems (map ASSUME ants1) ss | |
| 735 | val Q_eeq_Q1 = MetaSimplifier.rewrite_cterm | |
| 736 | (false,true,false) (prover used') ss' (tych Q) | |
| 737 | handle U.ERR _ => Thm.reflexive (tych Q) | |
| 738 | val lhs_eeq_lhs2 = implies_intr_list ants1 Q_eeq_Q1 | |
| 739 | val lhs_eq_lhs2 = lhs_eeq_lhs2 RS meta_eq_to_obj_eq | |
| 740 | val ant_th = forall_intr_list(map tych vlist)lhs_eq_lhs2 | |
| 741 | in | |
| 742 | ant_th COMP thm | |
| 743 | end end | |
| 744 | ||
| 745 | fun eliminate thm = | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 746 | case Thm.prop_of thm | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 747 |                of Const("==>",_) $ imp $ _ =>
 | 
| 23150 | 748 | eliminate | 
| 749 | (if not(is_all imp) | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 750 | then uq_eliminate (thm, imp, Thm.theory_of_thm thm) | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 751 | else q_eliminate (thm, imp, Thm.theory_of_thm thm)) | 
| 23150 | 752 | (* Assume that the leading constant is ==, *) | 
| 753 | | _ => thm (* if it is not a ==> *) | |
| 754 | in SOME(eliminate (rename thm)) end | |
| 755 | handle U.ERR _ => NONE (* FIXME handle THM as well?? *) | |
| 756 | ||
| 757 | fun restrict_prover ss thm = | |
| 758 | let val dummy = say "restrict_prover:" | |
| 29302 | 759 | val cntxt = rev(Simplifier.prems_of_ss ss) | 
| 23150 | 760 | val dummy = print_thms "cntxt:" cntxt | 
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 761 | val thy = Thm.theory_of_thm thm | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 762 |               val Const("==>",_) $ (Const("Trueprop",_) $ A) $ _ = Thm.prop_of thm
 | 
| 23150 | 763 | fun genl tm = let val vlist = subtract (op aconv) globals | 
| 29265 
5b4247055bd7
moved old add_term_vars, add_term_frees etc. to structure OldTerm;
 wenzelm parents: 
26928diff
changeset | 764 | (OldTerm.add_term_frees(tm,[])) | 
| 23150 | 765 | in fold_rev Forall vlist tm | 
| 766 | end | |
| 767 | (*-------------------------------------------------------------- | |
| 768 | * This actually isn't quite right, since it will think that | |
| 769 | * not-fully applied occs. of "f" in the context mean that the | |
| 770 | * current call is nested. The real solution is to pass in a | |
| 771 | * term "f v1..vn" which is a pattern that any full application | |
| 772 | * of "f" will match. | |
| 773 | *-------------------------------------------------------------*) | |
| 774 | val func_name = #1(dest_Const func) | |
| 775 | fun is_func (Const (name,_)) = (name = func_name) | |
| 776 | | is_func _ = false | |
| 777 | val rcontext = rev cntxt | |
| 778 | val cncl = HOLogic.dest_Trueprop o Thm.prop_of | |
| 779 | val antl = case rcontext of [] => [] | |
| 780 | | _ => [S.list_mk_conj(map cncl rcontext)] | |
| 781 | val TC = genl(S.list_mk_imp(antl, A)) | |
| 32429 
54758ca53fd6
modernized messages -- eliminated old Display.print_cterm;
 wenzelm parents: 
32091diff
changeset | 782 | val dummy = print_cterm "func:" (cterm_of thy func) | 
| 
54758ca53fd6
modernized messages -- eliminated old Display.print_cterm;
 wenzelm parents: 
32091diff
changeset | 783 | val dummy = print_cterm "TC:" (cterm_of thy (HOLogic.mk_Trueprop TC)) | 
| 23150 | 784 | val dummy = tc_list := (TC :: !tc_list) | 
| 33035 | 785 | val nestedp = is_some (S.find_term is_func TC) | 
| 23150 | 786 | val dummy = if nestedp then say "nested" else say "not_nested" | 
| 787 | val dummy = term_ref := ([func,TC]@(!term_ref)) | |
| 788 | val th' = if nestedp then raise RULES_ERR "solver" "nested function" | |
| 789 | else let val cTC = cterm_of thy | |
| 790 | (HOLogic.mk_Trueprop TC) | |
| 791 | in case rcontext of | |
| 792 | [] => SPEC_ALL(ASSUME cTC) | |
| 793 | | _ => MP (SPEC_ALL (ASSUME cTC)) | |
| 794 | (LIST_CONJ rcontext) | |
| 795 | end | |
| 796 | val th'' = th' RS thm | |
| 797 | in SOME (th'') | |
| 798 | end handle U.ERR _ => NONE (* FIXME handle THM as well?? *) | |
| 799 | in | |
| 800 | (if (is_cong thm) then cong_prover else restrict_prover) ss thm | |
| 801 | end | |
| 802 | val ctm = cprop_of th | |
| 29270 
0eade173f77e
moved old add_type_XXX, add_term_XXX etc. to structure OldTerm;
 wenzelm parents: 
29265diff
changeset | 803 | val names = OldTerm.add_term_names (term_of ctm, []) | 
| 23150 | 804 | val th1 = MetaSimplifier.rewrite_cterm(false,true,false) | 
| 805 | (prover names) (ss0 addsimps [cut_lemma'] addeqcongs congs) ctm | |
| 36945 | 806 | val th2 = Thm.equal_elim th1 th | 
| 23150 | 807 | in | 
| 33317 | 808 | (th2, filter_out restricted (!tc_list)) | 
| 23150 | 809 | end; | 
| 810 | ||
| 811 | ||
| 812 | fun prove strict (ptm, tac) = | |
| 813 | let | |
| 26626 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 814 | val thy = Thm.theory_of_cterm ptm; | 
| 
c6231d64d264
rep_cterm/rep_thm: no longer dereference theory_ref;
 wenzelm parents: 
23150diff
changeset | 815 | val t = Thm.term_of ptm; | 
| 36610 
bafd82950e24
renamed ProofContext.init to ProofContext.init_global to emphasize that this is not the real thing;
 wenzelm parents: 
35232diff
changeset | 816 | val ctxt = ProofContext.init_global thy |> Variable.auto_fixes t; | 
| 23150 | 817 | in | 
| 818 | if strict then Goal.prove ctxt [] [] t (K tac) | |
| 819 | else Goal.prove ctxt [] [] t (K tac) | |
| 820 | handle ERROR msg => (warning msg; raise RULES_ERR "prove" msg) | |
| 821 | end; | |
| 822 | ||
| 823 | end; |