src/HOL/Tools/split_rule.ML
author haftmann
Tue Nov 24 17:28:25 2009 +0100 (2009-11-24)
changeset 33955 fff6f11b1f09
parent 33368 b1cf34f1855c
child 33957 e9afca2118d4
permissions -rw-r--r--
curried take/drop
haftmann@24584
     1
(*  Title:      HOL/Tools/split_rule.ML
wenzelm@11037
     2
    Author:     Stefan Berghofer, David von Oheimb, and Markus Wenzel, TU Muenchen
wenzelm@11037
     3
wenzelm@15661
     4
Some tools for managing tupled arguments and abstractions in rules.
wenzelm@11037
     5
*)
wenzelm@11037
     6
wenzelm@11037
     7
signature BASIC_SPLIT_RULE =
wenzelm@11037
     8
sig
wenzelm@11037
     9
  val split_rule: thm -> thm
wenzelm@11037
    10
  val complete_split_rule: thm -> thm
wenzelm@11037
    11
end;
oheimb@11025
    12
wenzelm@11037
    13
signature SPLIT_RULE =
wenzelm@11037
    14
sig
wenzelm@11037
    15
  include BASIC_SPLIT_RULE
wenzelm@19735
    16
  val split_rule_var: term -> thm -> thm
wenzelm@27208
    17
  val split_rule_goal: Proof.context -> string list list -> thm -> thm
wenzelm@18708
    18
  val setup: theory -> theory
wenzelm@11037
    19
end;
wenzelm@11037
    20
wenzelm@11037
    21
structure SplitRule: SPLIT_RULE =
wenzelm@11037
    22
struct
wenzelm@11037
    23
wenzelm@11037
    24
wenzelm@19735
    25
wenzelm@11037
    26
(** theory context references **)
wenzelm@11037
    27
wenzelm@11838
    28
val split_conv = thm "split_conv";
wenzelm@11838
    29
val fst_conv = thm "fst_conv";
wenzelm@11838
    30
val snd_conv = thm "snd_conv";
wenzelm@11838
    31
wenzelm@11037
    32
fun internal_split_const (Ta, Tb, Tc) =
wenzelm@11037
    33
  Const ("Product_Type.internal_split", [[Ta, Tb] ---> Tc, HOLogic.mk_prodT (Ta, Tb)] ---> Tc);
wenzelm@11037
    34
wenzelm@11037
    35
val internal_split_def = thm "internal_split_def";
wenzelm@11037
    36
val internal_split_conv = thm "internal_split_conv";
wenzelm@11037
    37
wenzelm@11037
    38
wenzelm@11037
    39
wenzelm@11037
    40
(** split rules **)
wenzelm@11037
    41
wenzelm@11037
    42
val eval_internal_split = hol_simplify [internal_split_def] o hol_simplify [internal_split_conv];
wenzelm@11037
    43
val remove_internal_split = eval_internal_split o split_all;
wenzelm@11037
    44
oheimb@11025
    45
oheimb@11025
    46
(*In ap_split S T u, term u expects separate arguments for the factors of S,
oheimb@11025
    47
  with result type T.  The call creates a new term expecting one argument
oheimb@11025
    48
  of type S.*)
oheimb@11025
    49
fun ap_split (Type ("*", [T1, T2])) T3 u =
wenzelm@11037
    50
      internal_split_const (T1, T2, T3) $
wenzelm@11037
    51
      Abs ("v", T1,
oheimb@11025
    52
          ap_split T2 T3
haftmann@32287
    53
             ((ap_split T1 (HOLogic.flatten_tupleT T2 ---> T3) (incr_boundvars 1 u)) $
oheimb@11025
    54
              Bound 0))
oheimb@11025
    55
  | ap_split T T3 u = u;
oheimb@11025
    56
oheimb@11025
    57
(*Curries any Var of function type in the rule*)
wenzelm@19735
    58
fun split_rule_var' (t as Var (v, Type ("fun", [T1, T2]))) rl =
haftmann@32287
    59
      let val T' = HOLogic.flatten_tupleT T1 ---> T2;
wenzelm@11037
    60
          val newt = ap_split T1 T2 (Var (v, T'));
wenzelm@19735
    61
          val cterm = Thm.cterm_of (Thm.theory_of_thm rl);
wenzelm@11037
    62
      in Thm.instantiate ([], [(cterm t, cterm newt)]) rl end
wenzelm@19735
    63
  | split_rule_var' t rl = rl;
oheimb@11025
    64
wenzelm@11037
    65
wenzelm@11037
    66
(* complete splitting of partially splitted rules *)
oheimb@11025
    67
oheimb@11025
    68
fun ap_split' (T::Ts) U u = Abs ("v", T, ap_split' Ts U
haftmann@32288
    69
      (ap_split T (maps HOLogic.flatten_tupleT Ts ---> U)
oheimb@11025
    70
        (incr_boundvars 1 u) $ Bound 0))
oheimb@11025
    71
  | ap_split' _ _ u = u;
oheimb@11025
    72
wenzelm@19735
    73
fun complete_split_rule_var (t as Var (v, T), ts) (rl, vs) =
oheimb@11025
    74
      let
wenzelm@19735
    75
        val cterm = Thm.cterm_of (Thm.theory_of_thm rl)
oheimb@11025
    76
        val (Us', U') = strip_type T;
haftmann@33955
    77
        val Us = (uncurry take) (length ts, Us');
haftmann@33955
    78
        val U = (uncurry drop) (length ts, Us') ---> U';
haftmann@32288
    79
        val T' = maps HOLogic.flatten_tupleT Us ---> U;
wenzelm@19735
    80
        fun mk_tuple (v as Var ((a, _), T)) (xs, insts) =
oheimb@11025
    81
              let
haftmann@32287
    82
                val Ts = HOLogic.flatten_tupleT T;
wenzelm@20071
    83
                val ys = Name.variant_list xs (replicate (length Ts) a);
haftmann@32342
    84
              in (xs @ ys, (cterm v, cterm (HOLogic.mk_ptuple (HOLogic.flat_tupleT_paths T) T
oheimb@11025
    85
                (map (Var o apfst (rpair 0)) (ys ~~ Ts))))::insts)
oheimb@11025
    86
              end
wenzelm@19735
    87
          | mk_tuple _ x = x;
oheimb@11025
    88
        val newt = ap_split' Us U (Var (v, T'));
wenzelm@19735
    89
        val cterm = Thm.cterm_of (Thm.theory_of_thm rl);
wenzelm@19735
    90
        val (vs', insts) = fold mk_tuple ts (vs, []);
oheimb@11025
    91
      in
oheimb@11025
    92
        (instantiate ([], [(cterm t, cterm newt)] @ insts) rl, vs')
oheimb@11025
    93
      end
wenzelm@19735
    94
  | complete_split_rule_var _ x = x;
oheimb@11025
    95
wenzelm@19735
    96
fun collect_vars (Abs (_, _, t)) = collect_vars t
wenzelm@19735
    97
  | collect_vars t =
wenzelm@19735
    98
      (case strip_comb t of
wenzelm@19735
    99
        (v as Var _, ts) => cons (v, ts)
wenzelm@19735
   100
      | (t, ts) => fold collect_vars ts);
oheimb@11025
   101
wenzelm@11037
   102
wenzelm@19735
   103
val split_rule_var = (Drule.standard o remove_internal_split) oo split_rule_var';
oheimb@11025
   104
wenzelm@11037
   105
(*curries ALL function variables occurring in a rule's conclusion*)
wenzelm@11037
   106
fun split_rule rl =
wenzelm@29265
   107
  fold_rev split_rule_var' (OldTerm.term_vars (concl_of rl)) rl
wenzelm@11037
   108
  |> remove_internal_split
wenzelm@11037
   109
  |> Drule.standard;
oheimb@11025
   110
wenzelm@19735
   111
(*curries ALL function variables*)
oheimb@11025
   112
fun complete_split_rule rl =
wenzelm@19735
   113
  let
wenzelm@19735
   114
    val prop = Thm.prop_of rl;
wenzelm@19735
   115
    val xs = Term.fold_aterms (fn Var ((x, _), _) => insert (op =) x | _ => I) prop [];
wenzelm@19735
   116
    val vars = collect_vars prop [];
wenzelm@19735
   117
  in
wenzelm@19735
   118
    fst (fold_rev complete_split_rule_var vars (rl, xs))
wenzelm@19735
   119
    |> remove_internal_split
wenzelm@19735
   120
    |> Drule.standard
wenzelm@33368
   121
    |> Rule_Cases.save rl
wenzelm@19735
   122
  end;
wenzelm@11037
   123
wenzelm@11037
   124
wenzelm@27208
   125
fun pair_tac ctxt s =
wenzelm@27239
   126
  res_inst_tac ctxt [(("p", 0), s)] @{thm PairE}
wenzelm@27208
   127
  THEN' hyp_subst_tac
wenzelm@27208
   128
  THEN' K prune_params_tac;
haftmann@26352
   129
wenzelm@11037
   130
val split_rule_ss = HOL_basic_ss addsimps [split_conv, fst_conv, snd_conv];
wenzelm@11037
   131
wenzelm@27208
   132
fun split_rule_goal ctxt xss rl =
wenzelm@11037
   133
  let
wenzelm@27208
   134
    fun one_split i s = Tactic.rule_by_tactic (pair_tac ctxt s i);
wenzelm@19735
   135
    fun one_goal (i, xs) = fold (one_split (i + 1)) xs;
wenzelm@11037
   136
  in
haftmann@18050
   137
    rl
wenzelm@19735
   138
    |> fold_index one_goal xss
haftmann@18050
   139
    |> Simplifier.full_simplify split_rule_ss
wenzelm@19735
   140
    |> Drule.standard
wenzelm@33368
   141
    |> Rule_Cases.save rl
wenzelm@11037
   142
  end;
wenzelm@11037
   143
wenzelm@30722
   144
wenzelm@11037
   145
(* attribute syntax *)
wenzelm@11037
   146
wenzelm@27882
   147
(* FIXME dynamically scoped due to Args.name_source/pair_tac *)
wenzelm@15661
   148
wenzelm@11037
   149
val setup =
wenzelm@30722
   150
  Attrib.setup @{binding split_format}
wenzelm@30722
   151
    (Scan.lift
wenzelm@30722
   152
     (Args.parens (Args.$$$ "complete") >> K (Thm.rule_attribute (K complete_split_rule)) ||
wenzelm@30722
   153
      OuterParse.and_list1 (Scan.repeat Args.name_source)
wenzelm@30722
   154
        >> (fn xss => Thm.rule_attribute (fn context =>
wenzelm@30722
   155
            split_rule_goal (Context.proof_of context) xss))))
wenzelm@30528
   156
    "split pair-typed subterms in premises, or function arguments" #>
wenzelm@30528
   157
  Attrib.setup @{binding split_rule} (Scan.succeed (Thm.rule_attribute (K split_rule)))
wenzelm@30528
   158
    "curries ALL function variables occurring in a rule's conclusion";
oheimb@11025
   159
oheimb@11025
   160
end;
oheimb@11025
   161
wenzelm@11037
   162
structure BasicSplitRule: BASIC_SPLIT_RULE = SplitRule;
wenzelm@11037
   163
open BasicSplitRule;