1structure reductionEval :> reductionEval = 2struct 3 4open HolKernel Parse boolLib simpLib Traverse BasicProvers 5open chap3Theory normal_orderTheory termSyntax 6 7structure Parse = struct 8val (Type,Term) = parse_from_grammars normal_orderTheory.normal_order_grammars 9end 10 11fun ERR f msg = mk_HOL_ERR "reductionEval" f msg 12val betastar_t = ``(-b->*)`` 13val normorderstar_t = ``(-n->*)`` 14val beta_t = ``(-b->)`` 15val normorder_t = ``(-n->)`` 16val lameq_t = ``(==) : term -> term -> bool`` 17 18fun rtc_po t = let 19 open relationTheory Travrules 20 infix |> fun x |> f = f x 21 fun rwt th = th |> REWRITE_RULE [reflexive_def, transitive_def] 22 |> ISPEC t 23in 24 mk_preorder (rwt transitive_RTC, rwt reflexive_RTC) 25end 26 27val [lameq_beta,lameq_refl,lameq_sym,lameq_trans, 28 lameq_APPl, lameq_APPr, lameq_LAM] = CONJUNCTS chap2Theory.lameq_rules 29 30val lameq_APPcong = chap2Theory.lameq_app_cong 31 32val lameq_po = let 33 open relationTheory Travrules 34in 35 mk_preorder (lameq_trans, lameq_refl) 36end 37 38fun dest_binop t = let 39 val (fx,y) = dest_comb t 40 val (f,x) = dest_comb fx 41in 42 (f,x,y) 43end 44 45 46val betastar_po = rtc_po beta_t 47val normstar_po = rtc_po ``(-n->)`` 48 49val equality_po = let 50 open Travrules 51 val TRAVRULES {relations,...} = EQ_tr 52in 53 hd relations 54end 55 56 57(* ---------------------------------------------------------------------- 58 A reducer for beta-reduction. 59 ---------------------------------------------------------------------- *) 60 61 62val congs = [lameq_APPcong, SPEC_ALL lameq_LAM, 63 chap2Theory.Yf_cong, 64 REWRITE_RULE [GSYM AND_IMP_INTRO] 65 (last (CONJUNCTS chap2Theory.lemma2_12))] 66 67val user_rewrites = ref (SSFRAG {dprocs = [], ac = [], rewrs = [], 68 congs = [], filter = NONE, 69 name = SOME "betasimps", convs = []}) 70fun add_rwts (ths : (string * thm) list) = 71 user_rewrites := 72 simpLib.merge_ss [!user_rewrites, simpLib.rewrites (map #2 ths)] 73 74open chap2Theory head_reductionTheory 75val BETA_rsd = {refl = GEN_ALL lameq_refl, trans = lameq_trans, 76 weakenings = [lameq_weaken_cong, lameq_has_bnf_cong, 77 lameq_bnf_of_cong], 78 subsets = [ccbeta_lameq, betastar_lameq, whstar_lameq, 79 normorder_lameq, nstar_lameq], 80 rewrs = [lameq_S, lameq_K, lameq_I, lameq_C, 81 lameq_B, lameq_beta]} 82 83val BETA_CONG_ss = 84 SSFRAG {dprocs = [], ac = [], rewrs = [], congs = congs, filter = NONE, 85 name = NONE, convs = []} 86val BETA_RWTS_ss = rewrites [termTheory.lemma14b, 87 normal_orderTheory.nstar_betastar_bnf, 88 betastar_lameq_bnf, lameq_refl] 89 90val BETA_ss = 91 simpLib.merge_ss [relsimp_ss BETA_rsd, BETA_CONG_ss, BETA_RWTS_ss] 92 93fun betafy ss = 94 simpLib.add_relsimp BETA_rsd ss ++ BETA_RWTS_ss ++ 95 !user_rewrites ++ BETA_CONG_ss 96fun bsrw_ss() = betafy(srw_ss()) 97 98val {export = export_betarwt,...} = 99 ThmSetData.new_exporter "betasimp" (K add_rwts) 100fun bstore_thm (trip as (n,t,tac)) = store_thm trip before export_betarwt n 101 102(* ---------------------------------------------------------------------- 103 A reducer for weak head reduction. 104 ---------------------------------------------------------------------- *) 105 106fun whfy ss = let 107 open relationTheory head_reductionTheory termTheory 108 val congs = [wh_app_congL, whstar_substitutive] 109in 110 add_relsimp {refl = RTC_REFL 111 |> INST_TYPE [alpha |-> termSyntax.term_ty] 112 |> Q.INST [`R` |-> `(-w->)`] 113 |> Q.GEN `x`, 114 trans = transitive_RTC 115 |> REWRITE_RULE [transitive_def] 116 |> Q.ISPEC `(-w->)`, 117 weakenings = [wh_weaken_cong], 118 subsets = [], 119 rewrs = [MATCH_MP RTC_SINGLE 120 (SPEC_ALL (CONJUNCT1 weak_head_rules))]} ss ++ 121 SSFRAG {dprocs = [], ac = [], rewrs = [lemma14b, bnf_whnf], congs = congs, 122 filter = NONE, name = NONE, convs = []} 123end 124 125(* ---------------------------------------------------------------------- 126 normorder_step 127 128 Given a term t of type ``:term``, try to deduce a normal order reduction 129 step, returning a thm looking like 130 131 |- t -n-> t' 132 133 raises a HOL_ERR if it can't do it. This may mean t is in bnf. 134 ---------------------------------------------------------------------- *) 135 136open termSyntax 137val [nbeta,nlam_cong,nleft,nright] = CONJUNCTS normorder_rules 138val is_abs_t = mk_thy_const{Thy = "chap2", Name = "is_abs", 139 Ty = term_ty --> bool} 140val bnf_t = mk_thy_const{Thy = "chap2", Name = "bnf", 141 Ty = term_ty --> bool} 142 143fun normorder_step solver t = let 144 val _ = Trace.trace (2, Trace.LZ_TEXT (fn () => "Attempting no1 on "^ 145 term_to_string t)) 146in 147 case total dest_APP t of 148 NONE => let 149 in 150 case total dest_LAM t of 151 NONE => raise ERR "normorder_step" "No visible reduction" 152 | SOME (v,bdy) => let 153 val subth = normorder_step solver bdy 154 in 155 MP (SPECL [v,bdy,rand(concl subth)] nlam_cong) subth 156 end 157 end 158 | SOME(M1,M2) => let 159 in 160 case total dest_LAM M1 of 161 NONE => let 162 val isnt_ABS_th = solver (mk_neg(mk_comb(is_abs_t,M1))) 163 in 164 case total (normorder_step solver) M1 of 165 NONE => let 166 val bnf_th = solver (mk_comb(bnf_t,M1)) 167 val subth = normorder_step solver M2 168 in 169 MP (SPECL [M1,M2,rand (concl subth)] nright) 170 (LIST_CONJ [subth,bnf_th,isnt_ABS_th]) 171 end 172 | SOME subth => 173 MP (SPECL [M1,rand(concl subth),M2] nleft) 174 (CONJ subth isnt_ABS_th) 175 end 176 | SOME(v,body) => SPECL [v,body,M2] nbeta 177 end 178end 179 180 181 182val [noredLAM, noredbeta, noredAPP, noredVAR] = CONJUNCTS noreduct_thm 183val noreduct_t = mk_thy_const{Name = "noreduct", Thy = "normal_order", 184 Ty = term_ty --> optionSyntax.mk_option term_ty} 185val (opmap_SOME,opmap_NONE) = CONJ_PAIR optionTheory.OPTION_MAP_DEF 186val Mv_t = mk_var("M", term_ty) 187val Nv_t = mk_var("N", term_ty) 188 189fun noreduct_CONV solver t = let 190 val (f,arg) = dest_comb t 191 val _ = same_const noreduct_t f orelse 192 raise ERR "noreduct_CONV" "Inapplicable" 193 fun recurse t = 194 case total dest_LAM t of 195 SOME (v, body) => let 196 val subth = recurse body 197 val c = REWR_CONV noredLAM THENC 198 RAND_CONV (K subth) THENC 199 FIRST_CONV [REWR_CONV opmap_SOME, REWR_CONV opmap_NONE] 200 in 201 c (mk_comb(noreduct_t, t)) 202 end 203 | NONE => let 204 in 205 case total dest_APP t of 206 NONE => if is_VAR t then REWR_CONV noredVAR (mk_comb(noreduct_t, t)) 207 else raise ERR "noreduct_CONV" "No good normorder reduct" 208 | SOME (M1, M2) => let 209 in 210 case total dest_LAM M1 of 211 SOME (v, body) => REWR_CONV noredbeta (mk_comb(noreduct_t, t)) 212 | NONE => let 213 val isnt_ABS = solver (mk_neg(mk_comb(is_abs_t, M1))) 214 val M1th = recurse M1 215 val eqn = MP (INST [Mv_t |-> M1, Nv_t |-> M2] noredAPP') 216 isnt_ABS 217 val c = REWRITE_CONV [optionTheory.option_case_def, 218 M1th] 219 val eqn' = CONV_RULE (RAND_CONV c) eqn 220 in 221 if is_comb (rand (concl M1th)) then 222 CONV_RULE (RAND_CONV BETA_CONV) eqn' 223 else let 224 val M2th = recurse M2 225 in 226 CONV_RULE 227 (RAND_CONV 228 (REWRITE_CONV [optionTheory.OPTION_MAP_DEF, 229 M2th])) 230 eqn' 231 end 232 end 233 end 234 end 235in 236 recurse arg 237end 238 239val nopath_t = prim_mk_const{Thy = "normal_order", Name = "nopath"} 240fun nopath_CONV solver t = let 241 val (f, x) = dest_comb t 242 val _ = aconv f nopath_t orelse raise ERR "nopath_CONV" "Inapplicable" 243 val subth = noreduct_CONV solver (mk_comb(noreduct_t, x)) 244in 245 REWR_CONV nopath_def THENC 246 REWRITE_CONV [subth, optionTheory.option_case_def] THENC 247 TRY_CONV BETA_CONV 248end t 249 250val bnf_imp_noreduct = GEN_ALL (#2 (EQ_IMP_RULE noreduct_bnf)) 251val nstar_imp_memnopath = GEN_ALL (#1 (EQ_IMP_RULE normstar_nopath)) 252fun normstar_filter (th,c) = 253 [(th,c), (EQT_INTRO (MATCH_MP bnf_imp_noreduct (EQT_ELIM th)),c)] 254 handle HOL_ERR _ => 255 [(th,c), (EQT_INTRO (MATCH_MP nstar_imp_memnopath (EQT_ELIM th)),c)] 256 handle HOL_ERR _ => [(th,c)] 257 258fun mngcnv cnv solver stack t = cnv (solver stack) t 259val NORMSTAR_ss = SSFRAG { 260 ac = [], congs = [], 261 convs = [{conv = mngcnv nopath_CONV, key = SOME([], mk_comb(nopath_t, Mv_t)), 262 name = "nopath_CONV", trace = 2}, 263 {conv = mngcnv noreduct_CONV, 264 key = SOME([], mk_comb(noreduct_t, Mv_t)), 265 name = "noreduct_CONV", trace = 2}], 266 filter = SOME normstar_filter, dprocs = [], name = SOME "NORMSTAR_ss", 267 rewrs = [normstar_nopath, termTheory.lemma14b]}; 268 269(* ---------------------------------------------------------------------- 270 unvarify_tac 271 272 Turns a goal of the form M -b->* N into one where free term variables 273 in N have turned into lambda-variables (i.e., HOL terms of the form 274 VAR s). This may put N into bnf, allowing the betastar reduction 275 congruence to fire. If the resulting goal is provable, so too was 276 the original because of substitutivity of beta-reduction. 277 ---------------------------------------------------------------------- *) 278 279fun goalnames (asl, w) = let 280 val fvs = FVL (w::asl) empty_tmset 281 fun foldthis(t,acc) = HOLset.add(acc, #1 (dest_var t)) 282in 283 HOLset.listItems (HOLset.foldl foldthis (HOLset.empty String.compare) fvs) 284end 285 286fun unvarify_tac th (w as (asl,g)) = let 287 val (f,x,y) = dest_binop g 288 val y_fvs = free_vars y 289 val y_fvs = filter (fn t => type_of t = term_ty) y_fvs 290 val (strs, sets) = 291 List.foldl binderLib.find_avoids (empty_tmset, empty_tmset) (g::asl) 292 val finite_sets = List.mapPartial (total pred_setSyntax.dest_finite) asl 293 fun filterthis t = not (is_var t) orelse mem t finite_sets 294 val sets = List.filter filterthis (HOLset.listItems sets) 295 fun do_them (strs,sets) ys (w as (asl,g)) = 296 case ys of 297 [] => ALL_TAC w 298 | y::rest => let 299 val newname = Lexis.gen_variant Lexis.tmvar_vary 300 (goalnames w) 301 (#1 (dest_var y) ^ "s") 302 val sets = List.filter (fn t => rand t <> y) sets 303 val new_tac = let 304 open pred_setSyntax 305 in 306 if null sets then 307 if HOLset.isEmpty strs then ALL_TAC 308 else let 309 val avoid_t = mk_set (HOLset.listItems strs) 310 in 311 binderLib.NEW_TAC newname avoid_t 312 end 313 else if HOLset.isEmpty strs then let 314 val avoid_t = List.foldl mk_union (hd sets) (tl sets) 315 in 316 binderLib.NEW_TAC newname avoid_t 317 end 318 else let 319 val base = mk_set (HOLset.listItems strs) 320 val avoid_t = List.foldl mk_union base sets 321 in 322 binderLib.NEW_TAC newname avoid_t 323 end 324 end 325 val newname_t = mk_var(newname, stringSyntax.string_ty) 326 val inst1 = [y |-> mk_comb(VAR_t, newname_t)] 327 val (_, M, N) = dest_binop g 328 val x'_base = Term.subst inst1 M 329 val y'_base = Term.subst inst1 N 330 val x' = list_mk_comb(SUB_t, [y,newname_t,x'_base]) 331 val y' = list_mk_comb(SUB_t, [y,newname_t,y'_base]) 332 val g' = list_mk_comb(f, [x',y']) 333 in 334 new_tac THEN SUBGOAL_THEN (mk_eq(g,g')) SUBST1_TAC THENL [ 335 ASM_SIMP_TAC (srw_ss()) [termTheory.lemma14b], 336 MATCH_MP_TAC th THEN 337 do_them (HOLset.add(strs,newname_t), sets) rest 338 ] 339 end w 340in 341 do_them (strs,sets) y_fvs 342end w 343 344 345end 346