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