src/Pure/Isar/rule_cases.ML
author kleing
Tue, 13 May 2003 08:59:21 +0200
changeset 14024 213dcc39358f
parent 13668 11397ea8b438
child 14404 4952c5a92e04
permissions -rw-r--r--
HOL-Real -> HOL-Complex
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/Isar/rule_cases.ML
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     2
    ID:         $Id$
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     3
    Author:     Markus Wenzel, TU Muenchen
8807
wenzelm
parents: 8636
diff changeset
     4
    License:    GPL (GNU GENERAL PUBLIC LICENSE)
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     5
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     6
Manage local contexts of rules.
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     7
*)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     8
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     9
signature RULE_CASES =
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    10
sig
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    11
  val consumes: int -> 'a attribute
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    12
  val consumes_default: int -> 'a attribute
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    13
  val name: string list -> thm -> thm
8427
wenzelm
parents: 8400
diff changeset
    14
  val case_names: string list -> 'a attribute
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    15
  val save: thm -> thm -> thm
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    16
  val get: thm -> string list * int
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    17
  val add: thm -> thm * (string list * int)
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    18
  type T
12166
5fc22b8c03e9 added empty;
wenzelm
parents: 11993
diff changeset
    19
  val empty: T
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
    20
  val hhf_nth_subgoal: Sign.sg -> int * term -> term
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
    21
  val make: int option -> term option -> Sign.sg * term -> string list -> (string * T) list
8427
wenzelm
parents: 8400
diff changeset
    22
  val rename_params: string list list -> thm -> thm
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    23
  val params: string list list -> 'a attribute
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    24
end;
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    25
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    26
structure RuleCases: RULE_CASES =
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    27
struct
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    28
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    29
(* names *)
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    30
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    31
val consumes_tagN = "consumes";
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    32
val cases_tagN = "cases";
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    33
val case_conclN = "case";
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    34
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    35
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    36
(* number of consumed facts *)
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    37
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    38
fun lookup_consumes thm =
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    39
  let fun err () = raise THM ("Malformed 'consumes' tag of theorem", 0, [thm]) in
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    40
    (case Library.assoc (Thm.tags_of_thm thm, consumes_tagN) of
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    41
      None => None
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    42
    | Some [s] => (case Syntax.read_nat s of Some n => Some n | _ => err ())
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    43
    | _ => err ())
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    44
  end;
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    45
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    46
fun put_consumes None th = th
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    47
  | put_consumes (Some n) th = th
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    48
      |> Drule.untag_rule consumes_tagN
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    49
      |> Drule.tag_rule (consumes_tagN, [Library.string_of_int n]);
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    50
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    51
val save_consumes = put_consumes o lookup_consumes;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    52
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    53
fun consumes n x = Drule.rule_attribute (K (put_consumes (Some n))) x;
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    54
fun consumes_default n x = if Library.is_some (lookup_consumes (#2 x)) then x else consumes n x;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    55
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    56
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    57
(* case names *)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    58
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    59
fun put_case_names None thm = thm
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    60
  | put_case_names (Some names) thm =
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    61
      thm
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    62
      |> Drule.untag_rule cases_tagN
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    63
      |> Drule.tag_rule (cases_tagN, names);
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    64
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    65
fun lookup_case_names thm = Library.assoc (Thm.tags_of_thm thm, cases_tagN);
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    66
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    67
val save_case_names = put_case_names o lookup_case_names;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    68
val name = put_case_names o Some;
8427
wenzelm
parents: 8400
diff changeset
    69
fun case_names ss = Drule.rule_attribute (K (name ss));
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    70
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    71
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    72
(* access hints *)
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    73
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    74
fun save thm = save_case_names thm o save_consumes thm;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    75
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    76
fun get thm =
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    77
  let
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    78
    val n = if_none (lookup_consumes thm) 0;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    79
    val ss =
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    80
      (case lookup_case_names thm of
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    81
        None => map Library.string_of_int (1 upto (Thm.nprems_of thm - n))
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    82
      | Some ss => ss);
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    83
  in (ss, n) end;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    84
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    85
fun add thm = (thm, get thm);
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    86
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    87
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    88
(* prepare cases *)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    89
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    90
type T =
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    91
 {fixes: (string * typ) list,
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    92
  assumes: (string * term list) list,
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    93
  binds: (indexname * term option) list};
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    94
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    95
val hypsN = "hyps";
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    96
val premsN = "prems";
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    97
12166
5fc22b8c03e9 added empty;
wenzelm
parents: 11993
diff changeset
    98
val empty = {fixes = [], assumes = [], binds = []};
5fc22b8c03e9 added empty;
wenzelm
parents: 11993
diff changeset
    99
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   100
fun nth_subgoal(i,prop) =
13668
11397ea8b438 Removed Logic.skip_flexpairs.
berghofe
parents: 13629
diff changeset
   101
  hd (#1 (Logic.strip_prems (i, [], prop)));
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   102
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   103
fun hhf_nth_subgoal sg = Drule.norm_hhf sg o nth_subgoal
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   104
  
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   105
(* open_params = None
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   106
   ==> all parameters are "open", ie their default names are used.
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   107
   open_params = Some k
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   108
   ==> only the last k parameters, the ones coming from the original
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   109
   goal, not from the induction rule, are "open"
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   110
*)
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   111
fun prep_case open_params split sg prop name i =
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   112
  let
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   113
    val Bi = hhf_nth_subgoal sg (i,prop);
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   114
    val all_xs = Logic.strip_params Bi
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   115
    val n = length all_xs - (if_none open_params 0)
13629
a46362d2b19b take/drop -> splitAt
nipkow
parents: 13596
diff changeset
   116
    val (ind_xs, goal_xs) = splitAt(n,all_xs)
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   117
    val rename = if is_none open_params then I else apfst Syntax.internal
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   118
    val xs = map rename ind_xs @ goal_xs
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
   119
    val asms = map (curry Term.list_abs xs) (Logic.strip_assums_hyp Bi);
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   120
    val named_asms =
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   121
      (case split of None => [("", asms)]
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   122
      | Some t =>
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   123
          let val h = length (Logic.strip_assums_hyp(nth_subgoal(i,t)))
13629
a46362d2b19b take/drop -> splitAt
nipkow
parents: 13596
diff changeset
   124
              val (ps,qs) = splitAt(h, asms)
a46362d2b19b take/drop -> splitAt
nipkow
parents: 13596
diff changeset
   125
          in [(hypsN, ps), (premsN, qs)] end);
10872
87bb4462c434 make_raw: do not AutoBind.drop_judgment;
wenzelm
parents: 10830
diff changeset
   126
    val concl = Term.list_abs (xs, Logic.strip_assums_concl Bi);
12809
787ecc2ac737 RuleCases.make interface based on term instead of thm;
wenzelm
parents: 12761
diff changeset
   127
    val bind = ((case_conclN, 0), Some (ObjectLogic.drop_judgment sg concl));
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   128
  in (name, {fixes = xs, assumes = named_asms, binds = [bind]}) end;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   129
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   130
fun make open_params split (sg, prop) names =
13668
11397ea8b438 Removed Logic.skip_flexpairs.
berghofe
parents: 13629
diff changeset
   131
  let val nprems = Logic.count_prems (prop, 0) in
13596
ee5f79b210c1 modified induct method
nipkow
parents: 13425
diff changeset
   132
    foldr (fn (name, (cases, i)) => (prep_case open_params split sg prop name i :: cases, i - 1))
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   133
      (Library.drop (length names - nprems, names), ([], length names)) |> #1
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
   134
  end;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   135
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   136
8427
wenzelm
parents: 8400
diff changeset
   137
(* params *)
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   138
11002
e33dfe9bde39 added foldln
oheimb
parents: 10886
diff changeset
   139
fun rename_params xss thm = foldln Thm.rename_params_rule xss thm
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
   140
  |> save thm;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   141
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   142
fun params xss = Drule.rule_attribute (K (rename_params xss));
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   143
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   144
end;