src/HOL/Tools/split_rule.ML
author wenzelm
Sat, 14 Jun 2008 23:19:51 +0200
changeset 27208 5fe899199f85
parent 26352 7f50b708376c
child 27239 f2f42f9fa09d
permissions -rw-r--r--
proper context for tactics derived from res_inst_tac;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
24584
01e83ffa6c54 fixed title
haftmann
parents: 22278
diff changeset
     1
(*  Title:      HOL/Tools/split_rule.ML
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     2
    ID:         $Id$
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     3
    Author:     Stefan Berghofer, David von Oheimb, and Markus Wenzel, TU Muenchen
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     4
15661
9ef583b08647 reverted renaming of Some/None in comments and strings;
wenzelm
parents: 15574
diff changeset
     5
Some tools for managing tupled arguments and abstractions in rules.
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     6
*)
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     7
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     8
signature BASIC_SPLIT_RULE =
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
     9
sig
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    10
  val split_rule: thm -> thm
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    11
  val complete_split_rule: thm -> thm
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    12
end;
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    13
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    14
signature SPLIT_RULE =
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    15
sig
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    16
  include BASIC_SPLIT_RULE
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    17
  val split_rule_var: term -> thm -> thm
27208
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
    18
  val split_rule_goal: Proof.context -> string list list -> thm -> thm
18708
4b3dadb4fe33 setup: theory -> theory;
wenzelm
parents: 18629
diff changeset
    19
  val setup: theory -> theory
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    20
end;
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    21
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    22
structure SplitRule: SPLIT_RULE =
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    23
struct
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    24
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    25
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    26
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    27
(** theory context references **)
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    28
11838
02d75712061d got rid of ML proof scripts for Product_Type;
wenzelm
parents: 11045
diff changeset
    29
val split_conv = thm "split_conv";
02d75712061d got rid of ML proof scripts for Product_Type;
wenzelm
parents: 11045
diff changeset
    30
val fst_conv = thm "fst_conv";
02d75712061d got rid of ML proof scripts for Product_Type;
wenzelm
parents: 11045
diff changeset
    31
val snd_conv = thm "snd_conv";
02d75712061d got rid of ML proof scripts for Product_Type;
wenzelm
parents: 11045
diff changeset
    32
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    33
fun internal_split_const (Ta, Tb, Tc) =
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    34
  Const ("Product_Type.internal_split", [[Ta, Tb] ---> Tc, HOLogic.mk_prodT (Ta, Tb)] ---> Tc);
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    35
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    36
val internal_split_def = thm "internal_split_def";
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    37
val internal_split_conv = thm "internal_split_conv";
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    38
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    39
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    40
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    41
(** split rules **)
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    42
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    43
val eval_internal_split = hol_simplify [internal_split_def] o hol_simplify [internal_split_conv];
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    44
val remove_internal_split = eval_internal_split o split_all;
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    45
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    46
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    47
(*In ap_split S T u, term u expects separate arguments for the factors of S,
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    48
  with result type T.  The call creates a new term expecting one argument
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    49
  of type S.*)
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    50
fun ap_split (Type ("*", [T1, T2])) T3 u =
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    51
      internal_split_const (T1, T2, T3) $
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    52
      Abs ("v", T1,
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    53
          ap_split T2 T3
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    54
             ((ap_split T1 (HOLogic.prodT_factors T2 ---> T3) (incr_boundvars 1 u)) $
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    55
              Bound 0))
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    56
  | ap_split T T3 u = u;
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    57
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    58
(*Curries any Var of function type in the rule*)
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    59
fun split_rule_var' (t as Var (v, Type ("fun", [T1, T2]))) rl =
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    60
      let val T' = HOLogic.prodT_factors T1 ---> T2;
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    61
          val newt = ap_split T1 T2 (Var (v, T'));
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    62
          val cterm = Thm.cterm_of (Thm.theory_of_thm rl);
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    63
      in Thm.instantiate ([], [(cterm t, cterm newt)]) rl end
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    64
  | split_rule_var' t rl = rl;
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    65
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    66
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
    67
(* complete splitting of partially splitted rules *)
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    68
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    69
fun ap_split' (T::Ts) U u = Abs ("v", T, ap_split' Ts U
15570
8d8c70b41bab Move towards standard functions.
skalberg
parents: 15531
diff changeset
    70
      (ap_split T (List.concat (map HOLogic.prodT_factors Ts) ---> U)
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    71
        (incr_boundvars 1 u) $ Bound 0))
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    72
  | ap_split' _ _ u = u;
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    73
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    74
fun complete_split_rule_var (t as Var (v, T), ts) (rl, vs) =
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    75
      let
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    76
        val cterm = Thm.cterm_of (Thm.theory_of_thm rl)
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    77
        val (Us', U') = strip_type T;
15570
8d8c70b41bab Move towards standard functions.
skalberg
parents: 15531
diff changeset
    78
        val Us = Library.take (length ts, Us');
8d8c70b41bab Move towards standard functions.
skalberg
parents: 15531
diff changeset
    79
        val U = Library.drop (length ts, Us') ---> U';
8d8c70b41bab Move towards standard functions.
skalberg
parents: 15531
diff changeset
    80
        val T' = List.concat (map HOLogic.prodT_factors Us) ---> U;
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    81
        fun mk_tuple (v as Var ((a, _), T)) (xs, insts) =
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    82
              let
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    83
                val Ts = HOLogic.prodT_factors T;
20071
8f3e1ddb50e6 replaced Term.variant(list) by Name.variant(_list);
wenzelm
parents: 19735
diff changeset
    84
                val ys = Name.variant_list xs (replicate (length Ts) a);
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    85
              in (xs @ ys, (cterm v, cterm (HOLogic.mk_tuple T
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    86
                (map (Var o apfst (rpair 0)) (ys ~~ Ts))))::insts)
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    87
              end
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    88
          | mk_tuple _ x = x;
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    89
        val newt = ap_split' Us U (Var (v, T'));
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    90
        val cterm = Thm.cterm_of (Thm.theory_of_thm rl);
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    91
        val (vs', insts) = fold mk_tuple ts (vs, []);
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    92
      in
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    93
        (instantiate ([], [(cterm t, cterm newt)] @ insts) rl, vs')
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    94
      end
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    95
  | complete_split_rule_var _ x = x;
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
    96
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    97
fun collect_vars (Abs (_, _, t)) = collect_vars t
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    98
  | collect_vars t =
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
    99
      (case strip_comb t of
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   100
        (v as Var _, ts) => cons (v, ts)
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   101
      | (t, ts) => fold collect_vars ts);
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   102
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   103
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   104
val split_rule_var = (Drule.standard o remove_internal_split) oo split_rule_var';
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   105
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   106
(*curries ALL function variables occurring in a rule's conclusion*)
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   107
fun split_rule rl =
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   108
  fold_rev split_rule_var' (Term.term_vars (concl_of rl)) rl
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   109
  |> remove_internal_split
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   110
  |> Drule.standard;
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   111
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   112
(*curries ALL function variables*)
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   113
fun complete_split_rule rl =
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   114
  let
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   115
    val prop = Thm.prop_of rl;
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   116
    val xs = Term.fold_aterms (fn Var ((x, _), _) => insert (op =) x | _ => I) prop [];
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   117
    val vars = collect_vars prop [];
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   118
  in
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   119
    fst (fold_rev complete_split_rule_var vars (rl, xs))
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   120
    |> remove_internal_split
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   121
    |> Drule.standard
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   122
    |> RuleCases.save rl
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   123
  end;
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   124
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   125
27208
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   126
fun pair_tac ctxt s =
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   127
  RuleInsts.res_inst_tac ctxt [(("p", 0), s)] @{thm PairE}
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   128
  THEN' hyp_subst_tac
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   129
  THEN' K prune_params_tac;
26352
haftmann
parents: 25979
diff changeset
   130
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   131
val split_rule_ss = HOL_basic_ss addsimps [split_conv, fst_conv, snd_conv];
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   132
27208
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   133
fun split_rule_goal ctxt xss rl =
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   134
  let
27208
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   135
    fun one_split i s = Tactic.rule_by_tactic (pair_tac ctxt s i);
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   136
    fun one_goal (i, xs) = fold (one_split (i + 1)) xs;
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   137
  in
18050
652c95961a8b fold_index replacing foldln
haftmann
parents: 15661
diff changeset
   138
    rl
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   139
    |> fold_index one_goal xss
18050
652c95961a8b fold_index replacing foldln
haftmann
parents: 15661
diff changeset
   140
    |> Simplifier.full_simplify split_rule_ss
19735
ff13585fbdab complete_split_rule: all Vars;
wenzelm
parents: 18728
diff changeset
   141
    |> Drule.standard
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   142
    |> RuleCases.save rl
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   143
  end;
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   144
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   145
(* attribute syntax *)
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   146
15661
9ef583b08647 reverted renaming of Some/None in comments and strings;
wenzelm
parents: 15574
diff changeset
   147
(* FIXME dynamically scoped due to Args.name/pair_tac *)
9ef583b08647 reverted renaming of Some/None in comments and strings;
wenzelm
parents: 15574
diff changeset
   148
25979
3297781f8141 tuned attribute syntax -- no need for eta-expansion;
wenzelm
parents: 24584
diff changeset
   149
val split_format = Attrib.syntax
11045
971a50fda146 fixed syntax of 'split_format';
wenzelm
parents: 11040
diff changeset
   150
  (Scan.lift (Args.parens (Args.$$$ "complete"))
18728
6790126ab5f6 simplified type attribute;
wenzelm
parents: 18708
diff changeset
   151
    >> K (Thm.rule_attribute (K complete_split_rule)) ||
11045
971a50fda146 fixed syntax of 'split_format';
wenzelm
parents: 11040
diff changeset
   152
  Args.and_list1 (Scan.lift (Scan.repeat Args.name))
27208
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   153
    >> (fn xss => Thm.rule_attribute (fn context =>
5fe899199f85 proper context for tactics derived from res_inst_tac;
wenzelm
parents: 26352
diff changeset
   154
        split_rule_goal (Context.proof_of context) xss)));
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   155
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   156
val setup =
18708
4b3dadb4fe33 setup: theory -> theory;
wenzelm
parents: 18629
diff changeset
   157
  Attrib.add_attributes
18728
6790126ab5f6 simplified type attribute;
wenzelm
parents: 18708
diff changeset
   158
    [("split_format", split_format,
22278
70a7cd02fec1 Added split_rule attribute.
berghofe
parents: 20071
diff changeset
   159
      "split pair-typed subterms in premises, or function arguments"),
70a7cd02fec1 Added split_rule attribute.
berghofe
parents: 20071
diff changeset
   160
     ("split_rule", Attrib.no_args (Thm.rule_attribute (K split_rule)),
70a7cd02fec1 Added split_rule attribute.
berghofe
parents: 20071
diff changeset
   161
      "curries ALL function variables occurring in a rule's conclusion")];
11025
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   162
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   163
end;
a70b796d9af8 converted to Isar therory, adding attributes complete_split and split_format
oheimb
parents:
diff changeset
   164
11037
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   165
structure BasicSplitRule: BASIC_SPLIT_RULE = SplitRule;
37716a82a3d9 module setup;
wenzelm
parents: 11025
diff changeset
   166
open BasicSplitRule;