src/Pure/Isar/rule_cases.ML
author wenzelm
Sat, 15 Oct 2005 00:08:10 +0200
changeset 17861 28d3483afbbc
parent 17361 008b14a7afc4
child 18050 652c95961a8b
permissions -rw-r--r--
export strip_params;
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
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     4
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     5
Manage local contexts of rules.
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     6
*)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     7
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     8
signature RULE_CASES =
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
     9
sig
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    10
  val consumes: int -> 'a attribute
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    11
  val consumes_default: int -> 'a attribute
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    12
  val name: string list -> thm -> thm
8427
wenzelm
parents: 8400
diff changeset
    13
  val case_names: string list -> 'a attribute
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    14
  val save: thm -> thm -> thm
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    15
  val get: thm -> string list * int
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    16
  val add: thm -> thm * (string list * int)
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    17
  type T
17861
28d3483afbbc export strip_params;
wenzelm
parents: 17361
diff changeset
    18
  val strip_params: term -> (string * typ) list
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
    19
  val make: bool -> term option -> theory * term -> string list -> (string * T option) list
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
    20
  val simple: bool -> theory * term -> string -> string * T option
8427
wenzelm
parents: 8400
diff changeset
    21
  val rename_params: string list list -> thm -> thm
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    22
  val params: string list list -> 'a attribute
16390
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
    23
  type tactic
17113
3b67c1809e1c added NO_CASES;
wenzelm
parents: 16390
diff changeset
    24
  val NO_CASES: Tactical.tactic -> tactic
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    25
end;
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    26
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    27
structure RuleCases: RULE_CASES =
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    28
struct
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    29
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    30
(* names *)
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    31
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    32
val consumes_tagN = "consumes";
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    33
val cases_tagN = "cases";
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    34
val case_conclN = "case";
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
    35
val case_hypsN = "hyps";
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
    36
val case_premsN = "prems";
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    37
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
    38
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    39
(* number of consumed facts *)
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    40
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    41
fun lookup_consumes thm =
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    42
  let fun err () = raise THM ("Malformed 'consumes' tag of theorem", 0, [thm]) in
17184
3d80209e9a53 use AList operations;
wenzelm
parents: 17167
diff changeset
    43
    (case AList.lookup (op =) (Thm.tags_of_thm thm) (consumes_tagN) of
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    44
      NONE => NONE
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    45
    | SOME [s] => (case Syntax.read_nat s of SOME n => SOME n | _ => err ())
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    46
    | _ => err ())
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    47
  end;
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    48
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    49
fun put_consumes NONE th = th
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    50
  | put_consumes (SOME n) th = th
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    51
      |> Drule.untag_rule consumes_tagN
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    52
      |> Drule.tag_rule (consumes_tagN, [Library.string_of_int n]);
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    53
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    54
val save_consumes = put_consumes o lookup_consumes;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    55
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    56
fun consumes n x = Drule.rule_attribute (K (put_consumes (SOME n))) x;
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
    57
fun consumes_default n x =
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
    58
  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
    59
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    60
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    61
(* case names *)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    62
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    63
fun put_case_names NONE thm = thm
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    64
  | put_case_names (SOME names) thm =
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    65
      thm
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    66
      |> Drule.untag_rule cases_tagN
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    67
      |> Drule.tag_rule (cases_tagN, names);
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    68
17184
3d80209e9a53 use AList operations;
wenzelm
parents: 17167
diff changeset
    69
fun lookup_case_names thm = AList.lookup (op =) (Thm.tags_of_thm thm) cases_tagN;
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    70
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    71
val save_case_names = put_case_names o lookup_case_names;
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    72
val name = put_case_names o SOME;
8427
wenzelm
parents: 8400
diff changeset
    73
fun case_names ss = Drule.rule_attribute (K (name ss));
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    74
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    75
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    76
(* access hints *)
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    77
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    78
fun save thm = save_case_names thm o save_consumes thm;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    79
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    80
fun get thm =
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    81
  let
15973
wenzelm
parents: 15574
diff changeset
    82
    val n = if_none (lookup_consumes thm) 0;
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    83
    val ss =
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    84
      (case lookup_case_names thm of
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    85
        NONE => map Library.string_of_int (1 upto (Thm.nprems_of thm - n))
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
    86
      | SOME ss => ss);
12761
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    87
  in (ss, n) end;
b0c39f9837af save: be slightly more about absent tags;
wenzelm
parents: 12166
diff changeset
    88
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    89
fun add thm = (thm, get thm);
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
    90
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    91
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    92
(* prepare cases *)
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
    93
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    94
type T =
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    95
 {fixes: (string * typ) list,
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    96
  assumes: (string * term list) list,
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    97
  binds: (indexname * term option) list};
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
    98
17861
28d3483afbbc export strip_params;
wenzelm
parents: 17361
diff changeset
    99
val strip_params =
28d3483afbbc export strip_params;
wenzelm
parents: 17361
diff changeset
   100
  Logic.strip_params #> map (fn (x, T) => (the_default x (try Syntax.dest_skolem x), T));
17167
7667a85b53f1 unskolem local vars;
wenzelm
parents: 17113
diff changeset
   101
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   102
fun prep_case is_open thy (split, raw_prop) name =
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   103
  let
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   104
    val prop = Drule.norm_hhf thy raw_prop;
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   105
17861
28d3483afbbc export strip_params;
wenzelm
parents: 17361
diff changeset
   106
    val xs = strip_params prop;
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   107
    val rename = if is_open then I else map (apfst Syntax.internal);
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   108
    val named_xs =
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   109
      (case split of
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   110
        NONE => rename xs
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   111
      | SOME t =>
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   112
          let val (us, vs) = splitAt (length (Logic.strip_params t), xs)
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   113
          in rename us @ vs end);
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   114
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   115
    val asms = map (curry Term.list_abs named_xs) (Logic.strip_assums_hyp prop);
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 12809
diff changeset
   116
    val named_asms =
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   117
      (case split of
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   118
        NONE => [("", asms)]
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 14981
diff changeset
   119
      | SOME t =>
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   120
          let val (hyps, prems) = splitAt (length (Logic.strip_assums_hyp t), asms)
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   121
          in [(case_hypsN, hyps), (case_premsN, prems)] end);
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   122
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   123
    val concl = Term.list_abs (named_xs, Logic.strip_assums_concl prop);
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   124
    val bind = ((case_conclN, 0), SOME (ObjectLogic.drop_judgment thy concl));
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   125
  in (name, SOME {fixes = named_xs, assumes = named_asms, binds = [bind]}) end;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   126
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   127
fun make is_open split (thy, prop) names =
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   128
  let
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   129
    val nprems = Logic.count_prems (prop, 0);
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   130
    fun add_case name (cases, i) =
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   131
      ((case try (fn () =>
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   132
          (Option.map (curry Logic.nth_prem i) split, Logic.nth_prem (i, prop))) () of
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   133
        NONE => (name, NONE)
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   134
      | SOME sp => prep_case is_open thy sp name) :: cases, i - 1);
16148
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   135
  in
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   136
    fold_rev add_case (Library.drop (length names - nprems, names)) ([], length names)
5f15a14122dc make: T option -- actually remove undefined cases;
wenzelm
parents: 15973
diff changeset
   137
    |> #1
10811
98f52cb93d93 support ?case binding;
wenzelm
parents: 10530
diff changeset
   138
  end;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   139
17361
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   140
fun simple is_open (thy, prop) = prep_case is_open thy (NONE, prop);
008b14a7afc4 added simple;
wenzelm
parents: 17184
diff changeset
   141
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   142
8427
wenzelm
parents: 8400
diff changeset
   143
(* params *)
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   144
11002
e33dfe9bde39 added foldln
oheimb
parents: 10886
diff changeset
   145
fun rename_params xss thm = foldln Thm.rename_params_rule xss thm
10530
df079a585e6d added consumes, consumes_default;
wenzelm
parents: 10407
diff changeset
   146
  |> save thm;
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   147
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   148
fun params xss = Drule.rule_attribute (K (rename_params xss));
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   149
16390
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
   150
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
   151
(* tactics with cases *)
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
   152
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
   153
type tactic = thm -> (thm * (string * T option) list) Seq.seq;
305ce441869d added type tactic;
wenzelm
parents: 16148
diff changeset
   154
17113
3b67c1809e1c added NO_CASES;
wenzelm
parents: 16390
diff changeset
   155
fun NO_CASES tac = Seq.map (rpair []) o tac;
3b67c1809e1c added NO_CASES;
wenzelm
parents: 16390
diff changeset
   156
8364
0eb9ee70c8f8 added Isar/rule_cases.ML;
wenzelm
parents:
diff changeset
   157
end;
17113
3b67c1809e1c added NO_CASES;
wenzelm
parents: 16390
diff changeset
   158
3b67c1809e1c added NO_CASES;
wenzelm
parents: 16390
diff changeset
   159
val NO_CASES = RuleCases.NO_CASES;