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