src/HOL/BNF/Tools/ctr_sugar_tactics.ML
author blanchet
Tue, 01 Oct 2013 14:05:25 +0200
changeset 55144 07028b08045f
parent 55143 src/HOL/BNF/Tools/bnf_ctr_sugar_tactics.ML@9fe1bd54d437
child 55145 b15cfc2864de
permissions -rw-r--r--
renamed ML files
blanchet@55144
     1
(*  Title:      HOL/BNF/Tools/ctr_sugar_tactics.ML
blanchet@50035
     2
    Author:     Jasmin Blanchette, TU Muenchen
blanchet@50035
     3
    Copyright   2012
blanchet@50035
     4
blanchet@52934
     5
Tactics for wrapping existing freely generated type's constructors.
blanchet@50035
     6
*)
blanchet@50035
     7
blanchet@55143
     8
signature CTR_SUGAR_TACTICS =
blanchet@50035
     9
sig
blanchet@50163
    10
  val mk_alternate_disc_def_tac: Proof.context -> int -> thm -> thm -> thm -> tactic
blanchet@54105
    11
  val mk_case_tac: Proof.context -> int -> int -> thm -> thm list -> thm list list -> tactic
wenzelm@52854
    12
  val mk_case_cong_tac: Proof.context -> thm -> thm list -> tactic
blanchet@54994
    13
  val mk_case_conv_if_tac: Proof.context -> int -> thm -> thm list -> thm list list ->
blanchet@54994
    14
    thm list list -> tactic
blanchet@50133
    15
  val mk_collapse_tac: Proof.context -> int -> thm -> thm list -> tactic
blanchet@50044
    16
  val mk_disc_exhaust_tac: int -> thm -> thm list -> tactic
wenzelm@52854
    17
  val mk_expand_tac: Proof.context -> int -> int list -> thm -> thm -> thm list ->
wenzelm@52854
    18
    thm list list list -> thm list list list -> tactic
wenzelm@52935
    19
  val mk_half_disc_exclude_tac: Proof.context -> int -> thm -> thm -> tactic
blanchet@50035
    20
  val mk_nchotomy_tac: int -> thm -> tactic
blanchet@50137
    21
  val mk_other_half_disc_exclude_tac: thm -> tactic
blanchet@55053
    22
  val mk_sel_exhaust_tac: int -> thm -> thm list -> tactic
blanchet@55054
    23
  val mk_split_tac: Proof.context -> thm -> thm list -> thm list list -> thm list list -> thm list
blanchet@55054
    24
    list list -> tactic
blanchet@50059
    25
  val mk_split_asm_tac: Proof.context -> thm -> tactic
blanchet@50152
    26
  val mk_unique_disc_def_tac: int -> thm -> tactic
blanchet@50035
    27
end;
blanchet@50035
    28
blanchet@55143
    29
structure Ctr_Sugar_Tactics : CTR_SUGAR_TACTICS =
blanchet@50035
    30
struct
blanchet@50035
    31
blanchet@50065
    32
open BNF_Util
blanchet@50044
    33
open BNF_Tactics
blanchet@50035
    34
blanchet@50501
    35
val meta_mp = @{thm meta_mp};
blanchet@50501
    36
blanchet@50227
    37
fun if_P_or_not_P_OF pos thm = thm RS (if pos then @{thm if_P} else @{thm if_not_P});
blanchet@50046
    38
blanchet@50035
    39
fun mk_nchotomy_tac n exhaust =
blanchet@53462
    40
  HEADGOAL (rtac allI THEN' rtac exhaust THEN'
blanchet@54103
    41
   EVERY' (maps (fn k => [rtac (mk_disjIN n k), REPEAT_DETERM o rtac exI, atac]) (1 upto n)));
blanchet@50035
    42
blanchet@50501
    43
fun mk_unique_disc_def_tac m uexhaust =
blanchet@53462
    44
  HEADGOAL (EVERY' [rtac iffI, rtac uexhaust, REPEAT_DETERM_N m o rtac exI, atac, rtac refl]);
blanchet@50152
    45
blanchet@50501
    46
fun mk_alternate_disc_def_tac ctxt k other_disc_def distinct uexhaust =
blanchet@53462
    47
  HEADGOAL (EVERY' ([rtac (other_disc_def RS @{thm arg_cong[of _ _ Not]} RS trans),
traytel@50645
    48
    rtac @{thm iffI_np}, REPEAT_DETERM o etac exE,
wenzelm@52935
    49
    hyp_subst_tac ctxt, SELECT_GOAL (unfold_thms_tac ctxt [not_ex]), REPEAT_DETERM o rtac allI,
blanchet@50501
    50
    rtac distinct, rtac uexhaust] @
blanchet@50189
    51
    (([etac notE, REPEAT_DETERM o rtac exI, atac], [REPEAT_DETERM o rtac exI, atac])
blanchet@53462
    52
     |> k = 1 ? swap |> op @)));
blanchet@50131
    53
wenzelm@52935
    54
fun mk_half_disc_exclude_tac ctxt m discD disc' =
blanchet@53462
    55
  HEADGOAL (dtac discD THEN' REPEAT_DETERM_N m o etac exE THEN' hyp_subst_tac ctxt THEN'
blanchet@53462
    56
    rtac disc');
blanchet@50043
    57
blanchet@53462
    58
fun mk_other_half_disc_exclude_tac half = HEADGOAL (etac @{thm contrapos_pn} THEN' etac half);
blanchet@50043
    59
blanchet@55053
    60
fun mk_disc_or_sel_exhaust_tac n exhaust destIs =
blanchet@53462
    61
  HEADGOAL (rtac exhaust THEN'
blanchet@55053
    62
    EVERY' (map2 (fn k => fn destI => dtac destI THEN'
blanchet@55053
    63
      select_prem_tac n (etac meta_mp) k THEN' atac) (1 upto n) destIs));
blanchet@55053
    64
blanchet@55053
    65
val mk_disc_exhaust_tac = mk_disc_or_sel_exhaust_tac;
blanchet@55053
    66
blanchet@55053
    67
fun mk_sel_exhaust_tac n disc_exhaust collapses =
blanchet@55057
    68
  mk_disc_or_sel_exhaust_tac n disc_exhaust collapses ORELSE
blanchet@55057
    69
  HEADGOAL (etac meta_mp THEN' resolve_tac collapses);
blanchet@50044
    70
blanchet@50499
    71
fun mk_collapse_tac ctxt m discD sels =
blanchet@53462
    72
  HEADGOAL (dtac discD THEN'
blanchet@53462
    73
    (if m = 0 then
blanchet@53462
    74
       atac
blanchet@53462
    75
     else
blanchet@53462
    76
       REPEAT_DETERM_N m o etac exE THEN' hyp_subst_tac ctxt THEN'
blanchet@53462
    77
       SELECT_GOAL (unfold_thms_tac ctxt sels) THEN' rtac refl));
blanchet@50045
    78
blanchet@52879
    79
fun mk_expand_tac ctxt n ms udisc_exhaust vdisc_exhaust uncollapses disc_excludesss
blanchet@52879
    80
    disc_excludesss' =
blanchet@50501
    81
  if ms = [0] then
blanchet@53462
    82
    HEADGOAL (rtac (@{thm trans_sym} OF (replicate 2 (the_single uncollapses))) THEN'
blanchet@53462
    83
      TRY o EVERY' [rtac udisc_exhaust, atac, rtac vdisc_exhaust, atac])
blanchet@50501
    84
  else
blanchet@52879
    85
    let val ks = 1 upto n in
blanchet@53462
    86
      HEADGOAL (rtac udisc_exhaust THEN'
blanchet@53462
    87
        EVERY' (map5 (fn k => fn m => fn disc_excludess => fn disc_excludess' =>
blanchet@53462
    88
            fn uuncollapse =>
blanchet@53462
    89
          EVERY' [rtac (uuncollapse RS trans) THEN' TRY o atac,
blanchet@53462
    90
            rtac sym, rtac vdisc_exhaust,
blanchet@53462
    91
            EVERY' (map4 (fn k' => fn disc_excludes => fn disc_excludes' => fn vuncollapse =>
blanchet@53462
    92
              EVERY'
blanchet@53462
    93
                (if k' = k then
blanchet@53462
    94
                   [rtac (vuncollapse RS trans), TRY o atac] @
blanchet@53462
    95
                   (if m = 0 then
blanchet@53462
    96
                      [rtac refl]
blanchet@53462
    97
                    else
blanchet@53462
    98
                      [if n = 1 then K all_tac else EVERY' [dtac meta_mp, atac, dtac meta_mp, atac],
blanchet@53462
    99
                       REPEAT_DETERM_N (Int.max (0, m - 1)) o etac conjE,
blanchet@53462
   100
                       asm_simp_tac (ss_only [] ctxt)])
blanchet@53462
   101
                 else
blanchet@53462
   102
                   [dtac (the_single (if k = n then disc_excludes else disc_excludes')),
blanchet@53462
   103
                    etac (if k = n then @{thm iff_contradict(1)} else @{thm iff_contradict(2)}),
blanchet@53462
   104
                    atac, atac]))
blanchet@53462
   105
              ks disc_excludess disc_excludess' uncollapses)])
blanchet@53462
   106
          ks ms disc_excludesss disc_excludesss' uncollapses))
blanchet@50501
   107
    end;
blanchet@50501
   108
blanchet@54104
   109
fun mk_case_same_ctr_tac ctxt injects =
blanchet@54104
   110
  REPEAT_DETERM o etac exE THEN' etac conjE THEN'
blanchet@54104
   111
    (case injects of
blanchet@54104
   112
      [] => atac
blanchet@54104
   113
    | [inject] => dtac (inject RS iffD1) THEN' REPEAT_DETERM o etac conjE THEN'
blanchet@54104
   114
        hyp_subst_tac ctxt THEN' rtac refl);
blanchet@54104
   115
blanchet@54104
   116
fun mk_case_distinct_ctrs_tac ctxt distincts =
blanchet@54104
   117
  REPEAT_DETERM o etac exE THEN' etac conjE THEN' full_simp_tac (ss_only distincts ctxt);
blanchet@54104
   118
blanchet@54105
   119
fun mk_case_tac ctxt n k case_def injects distinctss =
blanchet@54105
   120
  let
blanchet@54105
   121
    val case_def' = mk_unabs_def (n + 1) (case_def RS meta_eq_to_obj_eq);
blanchet@54105
   122
    val ks = 1 upto n;
blanchet@54105
   123
  in
blanchet@54105
   124
    HEADGOAL (rtac (case_def' RS trans) THEN' rtac @{thm the_equality} THEN'
blanchet@54105
   125
      rtac (mk_disjIN n k) THEN' REPEAT_DETERM o rtac exI THEN' rtac conjI THEN' rtac refl THEN'
blanchet@54105
   126
      rtac refl THEN'
blanchet@54104
   127
      EVERY' (map2 (fn k' => fn distincts =>
blanchet@54104
   128
        (if k' < n then etac disjE else K all_tac) THEN'
blanchet@54104
   129
        (if k' = k then mk_case_same_ctr_tac ctxt injects
blanchet@54104
   130
         else mk_case_distinct_ctrs_tac ctxt distincts)) ks distinctss))
blanchet@54104
   131
  end;
blanchet@54104
   132
blanchet@54994
   133
fun mk_case_conv_if_tac ctxt n uexhaust cases discss' selss =
blanchet@53462
   134
  HEADGOAL (rtac uexhaust THEN'
blanchet@53462
   135
    EVERY' (map3 (fn casex => fn if_discs => fn sels =>
blanchet@53462
   136
        EVERY' [hyp_subst_tac ctxt, SELECT_GOAL (unfold_thms_tac ctxt (if_discs @ sels)),
blanchet@53462
   137
          rtac casex])
blanchet@53462
   138
      cases (map2 (seq_conds if_P_or_not_P_OF n) (1 upto n) discss') selss));
blanchet@50046
   139
wenzelm@52854
   140
fun mk_case_cong_tac ctxt uexhaust cases =
blanchet@53462
   141
  HEADGOAL (rtac uexhaust THEN'
blanchet@53462
   142
    EVERY' (maps (fn casex => [dtac sym, asm_simp_tac (ss_only [casex] ctxt)]) cases));
blanchet@50058
   143
blanchet@55054
   144
fun mk_split_tac ctxt uexhaust cases selss injectss distinctsss =
blanchet@53462
   145
  HEADGOAL (rtac uexhaust) THEN
wenzelm@52935
   146
  ALLGOALS (fn k => (hyp_subst_tac ctxt THEN'
blanchet@55054
   147
     simp_tac (ss_only (@{thms simp_thms} @ cases @ nth selss (k - 1) @ nth injectss (k - 1) @
wenzelm@52854
   148
       flat (nth distinctsss (k - 1))) ctxt)) k) THEN
wenzelm@53074
   149
  ALLGOALS (blast_tac (put_claset (claset_of @{theory_context HOL}) ctxt));
blanchet@50047
   150
blanchet@50059
   151
val split_asm_thms = @{thms imp_conv_disj de_Morgan_conj de_Morgan_disj not_not not_ex};
blanchet@50059
   152
blanchet@50059
   153
fun mk_split_asm_tac ctxt split =
blanchet@53462
   154
  HEADGOAL (rtac (split RS trans)) THEN unfold_thms_tac ctxt split_asm_thms THEN
blanchet@53462
   155
  HEADGOAL (rtac refl);
blanchet@50059
   156
blanchet@50035
   157
end;