src/HOL/BNF/Tools/bnf_ctr_sugar_tactics.ML
author blanchet
Fri Jun 07 09:30:13 2013 +0200 (2013-06-07)
changeset 52334 705bc4f5fc70
parent 52325 a74e0a4741df
child 52966 3777ba39c660
permissions -rw-r--r--
tuning
blanchet@51797
     1
(*  Title:      HOL/BNF/Tools/bnf_ctr_sugar_tactics.ML
blanchet@49020
     2
    Author:     Jasmin Blanchette, TU Muenchen
blanchet@49020
     3
    Copyright   2012
blanchet@49020
     4
blanchet@51797
     5
Tactics for wrapping existing freely generated type's constructors.
blanchet@49020
     6
*)
blanchet@49020
     7
blanchet@51797
     8
signature BNF_CTR_SUGAR_TACTICS =
blanchet@49020
     9
sig
blanchet@49148
    10
  val mk_alternate_disc_def_tac: Proof.context -> int -> thm -> thm -> thm -> tactic
wenzelm@51717
    11
  val mk_case_cong_tac: Proof.context -> thm -> thm list -> tactic
blanchet@49594
    12
  val mk_case_conv_tac: Proof.context -> int -> thm -> thm list -> thm list list -> thm list list ->
blanchet@49153
    13
    tactic
blanchet@49118
    14
  val mk_collapse_tac: Proof.context -> int -> thm -> thm list -> tactic
blanchet@49029
    15
  val mk_disc_exhaust_tac: int -> thm -> thm list -> tactic
wenzelm@51717
    16
  val mk_expand_tac: Proof.context -> int -> int list -> thm -> thm -> thm list ->
wenzelm@51717
    17
    thm list list list -> thm list list list -> tactic
wenzelm@51798
    18
  val mk_half_disc_exclude_tac: Proof.context -> int -> thm -> thm -> tactic
blanchet@49020
    19
  val mk_nchotomy_tac: int -> thm -> tactic
blanchet@49122
    20
  val mk_other_half_disc_exclude_tac: thm -> tactic
wenzelm@51717
    21
  val mk_split_tac: Proof.context ->
wenzelm@51717
    22
    thm -> thm list -> thm list list -> thm list list list -> tactic
blanchet@49044
    23
  val mk_split_asm_tac: Proof.context -> thm -> tactic
blanchet@49137
    24
  val mk_unique_disc_def_tac: int -> thm -> tactic
blanchet@49020
    25
end;
blanchet@49020
    26
blanchet@51797
    27
structure BNF_Ctr_Sugar_Tactics : BNF_CTR_SUGAR_TACTICS =
blanchet@49020
    28
struct
blanchet@49020
    29
blanchet@49050
    30
open BNF_Util
blanchet@49029
    31
open BNF_Tactics
blanchet@49020
    32
blanchet@49486
    33
val meta_mp = @{thm meta_mp};
blanchet@49486
    34
blanchet@49212
    35
fun if_P_or_not_P_OF pos thm = thm RS (if pos then @{thm if_P} else @{thm if_not_P});
blanchet@49031
    36
blanchet@49020
    37
fun mk_nchotomy_tac n exhaust =
blanchet@52325
    38
  HEADGOAL (rtac allI THEN' rtac exhaust THEN'
blanchet@52325
    39
   EVERY'  (maps (fn k => [rtac (mk_disjIN n k), REPEAT_DETERM o rtac exI, atac]) (1 upto n)));
blanchet@49020
    40
blanchet@49486
    41
fun mk_unique_disc_def_tac m uexhaust =
blanchet@52325
    42
  HEADGOAL (EVERY' [rtac iffI, rtac uexhaust, REPEAT_DETERM_N m o rtac exI, atac, rtac refl]);
blanchet@49137
    43
blanchet@49486
    44
fun mk_alternate_disc_def_tac ctxt k other_disc_def distinct uexhaust =
blanchet@52325
    45
  HEADGOAL (EVERY' ([rtac (other_disc_def RS @{thm arg_cong[of _ _ Not]} RS trans),
traytel@49630
    46
    rtac @{thm iffI_np}, REPEAT_DETERM o etac exE,
wenzelm@51798
    47
    hyp_subst_tac ctxt, SELECT_GOAL (unfold_thms_tac ctxt [not_ex]), REPEAT_DETERM o rtac allI,
blanchet@49486
    48
    rtac distinct, rtac uexhaust] @
blanchet@49174
    49
    (([etac notE, REPEAT_DETERM o rtac exI, atac], [REPEAT_DETERM o rtac exI, atac])
blanchet@52325
    50
     |> k = 1 ? swap |> op @)));
blanchet@49116
    51
wenzelm@51798
    52
fun mk_half_disc_exclude_tac ctxt m discD disc' =
blanchet@52325
    53
  HEADGOAL (dtac discD THEN' REPEAT_DETERM_N m o etac exE THEN' hyp_subst_tac ctxt THEN'
blanchet@52325
    54
    rtac disc');
blanchet@49028
    55
blanchet@52325
    56
fun mk_other_half_disc_exclude_tac half = HEADGOAL (etac @{thm contrapos_pn} THEN' etac half);
blanchet@49028
    57
blanchet@49029
    58
fun mk_disc_exhaust_tac n exhaust discIs =
blanchet@52325
    59
  HEADGOAL (rtac exhaust THEN'
blanchet@52325
    60
    EVERY' (map2 (fn k => fn discI =>
blanchet@52325
    61
      dtac discI THEN' select_prem_tac n (etac meta_mp) k THEN' atac) (1 upto n) discIs));
blanchet@49029
    62
blanchet@49484
    63
fun mk_collapse_tac ctxt m discD sels =
blanchet@52325
    64
  HEADGOAL (dtac discD THEN'
blanchet@52325
    65
    (if m = 0 then
blanchet@52325
    66
       atac
blanchet@52325
    67
     else
blanchet@52325
    68
       REPEAT_DETERM_N m o etac exE THEN' hyp_subst_tac ctxt THEN'
blanchet@52325
    69
       SELECT_GOAL (unfold_thms_tac ctxt sels) THEN' rtac refl));
blanchet@49030
    70
blanchet@51742
    71
fun mk_expand_tac ctxt n ms udisc_exhaust vdisc_exhaust uncollapses disc_excludesss
blanchet@51742
    72
    disc_excludesss' =
blanchet@49486
    73
  if ms = [0] then
blanchet@52325
    74
    HEADGOAL (rtac (@{thm trans_sym} OF (replicate 2 (the_single uncollapses))) THEN'
blanchet@52325
    75
      TRY o EVERY' [rtac udisc_exhaust, atac, rtac vdisc_exhaust, atac])
blanchet@49486
    76
  else
blanchet@51742
    77
    let val ks = 1 upto n in
blanchet@52325
    78
      HEADGOAL (rtac udisc_exhaust THEN'
blanchet@52325
    79
        EVERY' (map5 (fn k => fn m => fn disc_excludess => fn disc_excludess' =>
blanchet@52325
    80
            fn uuncollapse =>
blanchet@52325
    81
          EVERY' [rtac (uuncollapse RS trans) THEN' TRY o atac,
blanchet@52325
    82
            rtac sym, rtac vdisc_exhaust,
blanchet@52325
    83
            EVERY' (map4 (fn k' => fn disc_excludes => fn disc_excludes' => fn vuncollapse =>
blanchet@52325
    84
              EVERY'
blanchet@52325
    85
                (if k' = k then
blanchet@52325
    86
                   [rtac (vuncollapse RS trans), TRY o atac] @
blanchet@52325
    87
                   (if m = 0 then
blanchet@52325
    88
                      [rtac refl]
blanchet@52325
    89
                    else
blanchet@52325
    90
                      [if n = 1 then K all_tac else EVERY' [dtac meta_mp, atac, dtac meta_mp, atac],
blanchet@52325
    91
                       REPEAT_DETERM_N (Int.max (0, m - 1)) o etac conjE,
blanchet@52325
    92
                       asm_simp_tac (ss_only [] ctxt)])
blanchet@52325
    93
                 else
blanchet@52325
    94
                   [dtac (the_single (if k = n then disc_excludes else disc_excludes')),
blanchet@52325
    95
                    etac (if k = n then @{thm iff_contradict(1)} else @{thm iff_contradict(2)}),
blanchet@52325
    96
                    atac, atac]))
blanchet@52325
    97
              ks disc_excludess disc_excludess' uncollapses)])
blanchet@52325
    98
          ks ms disc_excludesss disc_excludesss' uncollapses))
blanchet@49486
    99
    end;
blanchet@49486
   100
blanchet@49594
   101
fun mk_case_conv_tac ctxt n uexhaust cases discss' selss =
blanchet@52325
   102
  HEADGOAL (rtac uexhaust THEN'
blanchet@52325
   103
    EVERY' (map3 (fn casex => fn if_discs => fn sels =>
blanchet@52325
   104
        EVERY' [hyp_subst_tac ctxt, SELECT_GOAL (unfold_thms_tac ctxt (if_discs @ sels)),
blanchet@52325
   105
          rtac casex])
blanchet@52325
   106
      cases (map2 (seq_conds if_P_or_not_P_OF n) (1 upto n) discss') selss));
blanchet@49031
   107
wenzelm@51717
   108
fun mk_case_cong_tac ctxt uexhaust cases =
blanchet@52325
   109
  HEADGOAL (rtac uexhaust THEN'
blanchet@52325
   110
    EVERY' (maps (fn casex => [dtac sym, asm_simp_tac (ss_only [casex] ctxt)]) cases));
blanchet@49043
   111
blanchet@49586
   112
(* TODO: More precise "simp_thms"; get rid of "blast_tac" *)
wenzelm@51717
   113
fun mk_split_tac ctxt uexhaust cases injectss distinctsss =
blanchet@52325
   114
  HEADGOAL (rtac uexhaust) THEN
wenzelm@51798
   115
  ALLGOALS (fn k => (hyp_subst_tac ctxt THEN'
blanchet@49484
   116
     simp_tac (ss_only (@{thms simp_thms} @ cases @ nth injectss (k - 1) @
wenzelm@51717
   117
       flat (nth distinctsss (k - 1))) ctxt)) k) THEN
wenzelm@51937
   118
  ALLGOALS (blast_tac (put_claset (claset_of @{theory_context HOL}) ctxt));
blanchet@49032
   119
blanchet@49044
   120
val split_asm_thms = @{thms imp_conv_disj de_Morgan_conj de_Morgan_disj not_not not_ex};
blanchet@49044
   121
blanchet@49044
   122
fun mk_split_asm_tac ctxt split =
blanchet@52325
   123
  HEADGOAL (rtac (split RS trans)) THEN unfold_thms_tac ctxt split_asm_thms THEN
blanchet@52325
   124
  HEADGOAL (rtac refl);
blanchet@49044
   125
blanchet@49020
   126
end;