src/HOL/Tools/split_rule.ML
changeset 11037 37716a82a3d9
parent 11025 a70b796d9af8
child 11040 194406da4e43
equal deleted inserted replaced
11036:3c30f7b97a50 11037:37716a82a3d9
     1 (*Attempts to remove occurrences of split, and pair-valued parameters*)
     1 (*  Title:      Tools/split_rule.ML
     2 val remove_split = rewrite_rule [split_conv RS eq_reflection] o split_all;
     2     ID:         $Id$
       
     3     Author:     Stefan Berghofer, David von Oheimb, and Markus Wenzel, TU Muenchen
       
     4     License:    GPL (GNU GENERAL PUBLIC LICENSE)
     3 
     5 
     4 local
     6 Some tools for managing tupled arguments and abstractions in rules.
       
     7 *)
       
     8 
       
     9 signature BASIC_SPLIT_RULE =
       
    10 sig
       
    11   val split_rule: thm -> thm
       
    12   val complete_split_rule: thm -> thm
       
    13 end;
       
    14 
       
    15 signature SPLIT_RULE =
       
    16 sig
       
    17   include BASIC_SPLIT_RULE
       
    18   val split_rule_var: term * thm -> thm
       
    19   val split_rule_goal: string list list -> thm -> thm
       
    20   val setup: (theory -> theory) list
       
    21 end;
       
    22 
       
    23 structure SplitRule: SPLIT_RULE =
       
    24 struct
       
    25 
       
    26 
       
    27 (** theory context references **)
       
    28 
       
    29 fun internal_split_const (Ta, Tb, Tc) =
       
    30   Const ("Product_Type.internal_split", [[Ta, Tb] ---> Tc, HOLogic.mk_prodT (Ta, Tb)] ---> Tc);
       
    31 
       
    32 val internal_split_def = thm "internal_split_def";
       
    33 val internal_split_conv = thm "internal_split_conv";
       
    34 
       
    35 
       
    36 
       
    37 (** split rules **)
       
    38 
       
    39 val eval_internal_split = hol_simplify [internal_split_def] o hol_simplify [internal_split_conv];
       
    40 val remove_internal_split = eval_internal_split o split_all;
       
    41 
     5 
    42 
     6 (*In ap_split S T u, term u expects separate arguments for the factors of S,
    43 (*In ap_split S T u, term u expects separate arguments for the factors of S,
     7   with result type T.  The call creates a new term expecting one argument
    44   with result type T.  The call creates a new term expecting one argument
     8   of type S.*)
    45   of type S.*)
     9 fun ap_split (Type ("*", [T1, T2])) T3 u =
    46 fun ap_split (Type ("*", [T1, T2])) T3 u =
    10       HOLogic.split_const (T1, T2, T3) $
    47       internal_split_const (T1, T2, T3) $
    11       Abs("v", T1,
    48       Abs ("v", T1,
    12           ap_split T2 T3
    49           ap_split T2 T3
    13              ((ap_split T1 (HOLogic.prodT_factors T2 ---> T3) (incr_boundvars 1 u)) $
    50              ((ap_split T1 (HOLogic.prodT_factors T2 ---> T3) (incr_boundvars 1 u)) $
    14               Bound 0))
    51               Bound 0))
    15   | ap_split T T3 u = u;
    52   | ap_split T T3 u = u;
    16 
    53 
    17 (*Curries any Var of function type in the rule*)
    54 (*Curries any Var of function type in the rule*)
    18 fun split_rule_var' (t as Var (v, Type ("fun", [T1, T2])), rl) =
    55 fun split_rule_var' (t as Var (v, Type ("fun", [T1, T2])), rl) =
    19       let val T' = HOLogic.prodT_factors T1 ---> T2
    56       let val T' = HOLogic.prodT_factors T1 ---> T2;
    20           val newt = ap_split T1 T2 (Var (v, T'))
    57           val newt = ap_split T1 T2 (Var (v, T'));
    21           val cterm = Thm.cterm_of (#sign (rep_thm rl))
    58           val cterm = Thm.cterm_of (#sign (Thm.rep_thm rl));
    22       in
    59       in Thm.instantiate ([], [(cterm t, cterm newt)]) rl end
    23           instantiate ([], [(cterm t, cterm newt)]) rl
       
    24       end
       
    25   | split_rule_var' (t, rl) = rl;
    60   | split_rule_var' (t, rl) = rl;
    26 
    61 
    27 (*** Complete splitting of partially splitted rules ***)
    62 
       
    63 (* complete splitting of partially splitted rules *)
    28 
    64 
    29 fun ap_split' (T::Ts) U u = Abs ("v", T, ap_split' Ts U
    65 fun ap_split' (T::Ts) U u = Abs ("v", T, ap_split' Ts U
    30       (ap_split T (flat (map HOLogic.prodT_factors Ts) ---> U)
    66       (ap_split T (flat (map HOLogic.prodT_factors Ts) ---> U)
    31         (incr_boundvars 1 u) $ Bound 0))
    67         (incr_boundvars 1 u) $ Bound 0))
    32   | ap_split' _ _ u = u;
    68   | ap_split' _ _ u = u;
    33 
    69 
    34 fun complete_split_rule_var ((t as Var (v, T), ts), (rl, vs)) =
    70 fun complete_split_rule_var ((t as Var (v, T), ts), (rl, vs)) =
    35       let
    71       let
    36         val cterm = Thm.cterm_of (#sign (rep_thm rl))
    72         val cterm = Thm.cterm_of (#sign (Thm.rep_thm rl))
    37         val (Us', U') = strip_type T;
    73         val (Us', U') = strip_type T;
    38         val Us = take (length ts, Us');
    74         val Us = take (length ts, Us');
    39         val U = drop (length ts, Us') ---> U';
    75         val U = drop (length ts, Us') ---> U';
    40         val T' = flat (map HOLogic.prodT_factors Us) ---> U;
    76         val T' = flat (map HOLogic.prodT_factors Us) ---> U;
    41         fun mk_tuple ((xs, insts), v as Var ((a, _), T)) =
    77         fun mk_tuple ((xs, insts), v as Var ((a, _), T)) =
    42               let
    78               let
    43                 val Ts = HOLogic.prodT_factors T;
    79                 val Ts = HOLogic.prodT_factors T;
    44                 val ys = variantlist (replicate (length Ts) a, xs);
    80                 val ys = Term.variantlist (replicate (length Ts) a, xs);
    45               in (xs @ ys, (cterm v, cterm (HOLogic.mk_tuple T
    81               in (xs @ ys, (cterm v, cterm (HOLogic.mk_tuple T
    46                 (map (Var o apfst (rpair 0)) (ys ~~ Ts))))::insts)
    82                 (map (Var o apfst (rpair 0)) (ys ~~ Ts))))::insts)
    47               end
    83               end
    48           | mk_tuple (x, _) = x;
    84           | mk_tuple (x, _) = x;
    49         val newt = ap_split' Us U (Var (v, T'));
    85         val newt = ap_split' Us U (Var (v, T'));
    50         val cterm = Thm.cterm_of (#sign (rep_thm rl));
    86         val cterm = Thm.cterm_of (#sign (Thm.rep_thm rl));
    51         val (vs', insts) = foldl mk_tuple ((vs, []), ts);
    87         val (vs', insts) = foldl mk_tuple ((vs, []), ts);
    52       in
    88       in
    53         (instantiate ([], [(cterm t, cterm newt)] @ insts) rl, vs')
    89         (instantiate ([], [(cterm t, cterm newt)] @ insts) rl, vs')
    54       end
    90       end
    55   | complete_split_rule_var (_, x) = x;
    91   | complete_split_rule_var (_, x) = x;
    57 fun collect_vars (vs, Abs (_, _, t)) = collect_vars (vs, t)
    93 fun collect_vars (vs, Abs (_, _, t)) = collect_vars (vs, t)
    58   | collect_vars (vs, t) = (case strip_comb t of
    94   | collect_vars (vs, t) = (case strip_comb t of
    59         (v as Var _, ts) => (v, ts)::vs
    95         (v as Var _, ts) => (v, ts)::vs
    60       | (t, ts) => foldl collect_vars (vs, ts));
    96       | (t, ts) => foldl collect_vars (vs, ts));
    61 
    97 
    62 in
       
    63 
    98 
    64 val split_rule_var = standard o remove_split o split_rule_var';
    99 val split_rule_var = Drule.standard o remove_internal_split o split_rule_var';
    65 
   100 
    66 (*Curries ALL function variables occurring in a rule's conclusion*)
   101 (*curries ALL function variables occurring in a rule's conclusion*)
    67 fun split_rule rl = standard (remove_split (foldr split_rule_var' (term_vars (concl_of rl), rl)));
   102 fun split_rule rl =
       
   103   foldr split_rule_var' (Term.term_vars (concl_of rl), rl)
       
   104   |> remove_internal_split
       
   105   |> Drule.standard;
    68 
   106 
    69 fun complete_split_rule rl =
   107 fun complete_split_rule rl =
    70   standard (remove_split (fst (foldr complete_split_rule_var
   108   fst (foldr complete_split_rule_var
    71     (collect_vars ([], concl_of rl),
   109     (collect_vars ([], concl_of rl),
    72      (rl, map (fst o fst o dest_Var) (term_vars (#prop (rep_thm rl))))))))
   110       (rl, map (fst o fst o dest_Var) (Term.term_vars (#prop (Thm.rep_thm rl))))))
    73 	|> RuleCases.save rl;
   111   |> remove_internal_split
       
   112   |> Drule.standard
       
   113   |> RuleCases.save rl;
       
   114 
       
   115 
       
   116 val split_rule_ss = HOL_basic_ss addsimps [split_conv, fst_conv, snd_conv];
       
   117 
       
   118 fun split_rule_goal xss rl =
       
   119   let
       
   120     fun one_split i (th, s) = Tactic.rule_by_tactic (pair_tac s i) th;
       
   121     fun one_goal (xs, i) th = foldl (one_split i) (th, xs);
       
   122   in
       
   123     Drule.standard (Simplifier.full_simplify split_rule_ss (Library.foldln one_goal xss rl))
       
   124     |> RuleCases.save rl
       
   125   end;
       
   126 
       
   127 
       
   128 (* attribute syntax *)
       
   129 
       
   130 fun complete_split x =
       
   131   Attrib.no_args (Drule.rule_attribute (K complete_split_rule)) x;
       
   132 
       
   133 fun split_format x =
       
   134   Attrib.syntax (Args.and_list1 (Scan.lift (Scan.repeat Args.name))
       
   135     >> (fn xss => Drule.rule_attribute (K (split_rule_goal xss)))) x;
       
   136 
       
   137 val split_attributes =
       
   138  [("complete_split", (complete_split, complete_split),
       
   139     "recursively split all pair-typed function arguments"),
       
   140   ("split_format", (split_format, split_format),
       
   141     "split given pair-typed subterms in premises")];
       
   142 
       
   143 
       
   144 
       
   145 (** theory setup **)
       
   146 
       
   147 val setup =
       
   148  [Attrib.add_attributes split_attributes];
       
   149 
    74 
   150 
    75 end;
   151 end;
    76 fun complete_split x = 
       
    77 	Attrib.no_args (Drule.rule_attribute (K complete_split_rule)) x;
       
    78 
   152 
    79 fun split_rule_goal xss rl = let 
   153 structure BasicSplitRule: BASIC_SPLIT_RULE = SplitRule;
    80 	val ss = HOL_basic_ss addsimps [split_conv, fst_conv, snd_conv]; 
   154 open BasicSplitRule;
    81 	fun one_split i (th,s) = rule_by_tactic (pair_tac s i) th;
       
    82 	fun one_goal (xs,i) th = foldl (one_split i) (th,xs);
       
    83         in standard (Simplifier.full_simplify ss (foldln one_goal xss rl))
       
    84 	   |> RuleCases.save rl
       
    85         end;
       
    86 fun split_format x = 
       
    87 	Attrib.syntax (Args.and_list1 (Scan.lift (Scan.repeat Args.name)) 
       
    88 	>> (fn xss => Drule.rule_attribute (K (split_rule_goal xss)))) x;
       
    89 
       
    90 val split_attributes = [Attrib.add_attributes 
       
    91 	[("complete_split", (complete_split, complete_split), 
       
    92           "recursively split all pair-typed function arguments"),
       
    93 	 ("split_format", (split_format, split_format), 
       
    94           "split given pair-typed subterms in premises")]];
       
    95