src/HOL/Tools/induct_method.ML
author wenzelm
Sun, 17 Sep 2000 22:50:10 +0200
changeset 10013 be4824b7505d
parent 10008 61eb9f3aa92a
child 10271 45b996639c45
permissions -rw-r--r--
made SML/NJ happy;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     1
(*  Title:      HOL/Tools/induct_method.ML
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     2
    ID:         $Id$
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     3
    Author:     Markus Wenzel, TU Muenchen
9230
wenzelm
parents: 9066
diff changeset
     4
    License:    GPL (GNU GENERAL PUBLIC LICENSE)
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     5
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
     6
Proof by cases and induction on types and sets.
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     7
*)
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     8
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
     9
signature INDUCT_METHOD =
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    10
sig
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    11
  val dest_global_rules: theory ->
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    12
    {type_cases: (string * thm) list, set_cases: (string * thm) list,
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    13
      type_induct: (string * thm) list, set_induct: (string * thm) list}
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    14
  val print_global_rules: theory -> unit
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    15
  val dest_local_rules: Proof.context ->
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    16
    {type_cases: (string * thm) list, set_cases: (string * thm) list,
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    17
      type_induct: (string * thm) list, set_induct: (string * thm) list}
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    18
  val print_local_rules: Proof.context -> unit
8431
e5f8ee756a8a export vars_of;
wenzelm
parents: 8400
diff changeset
    19
  val vars_of: term -> term list
8695
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
    20
  val concls_of: thm -> term list
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    21
  val cases_type_global: string -> theory attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    22
  val cases_set_global: string -> theory attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    23
  val cases_type_local: string -> Proof.context attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    24
  val cases_set_local: string -> Proof.context attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    25
  val induct_type_global: string -> theory attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    26
  val induct_set_global: string -> theory attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    27
  val induct_type_local: string -> Proof.context attribute
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    28
  val induct_set_local: string -> Proof.context attribute
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
    29
  val simp_case_tac: bool -> simpset -> int -> tactic
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    30
  val setup: (theory -> theory) list
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    31
end;
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    32
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    33
structure InductMethod: INDUCT_METHOD =
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    34
struct
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    35
8337
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
    36
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    37
(** global and local induct data **)
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
    38
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    39
(* rules *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    40
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    41
type rules = (string * thm) NetRules.T;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    42
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    43
fun eq_rule ((s1:string, th1), (s2, th2)) = s1 = s2 andalso Thm.eq_thm (th1, th2);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    44
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    45
val type_rules = NetRules.init eq_rule (Thm.concl_of o #2);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    46
val set_rules = NetRules.init eq_rule (Thm.major_prem_of o #2);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    47
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    48
fun lookup_rule (rs:rules) name = Library.assoc (NetRules.rules rs, name);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    49
10008
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    50
fun print_rules kind sg rs =
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    51
  let val thms = map snd (NetRules.rules rs)
10008
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    52
  in Pretty.writeln (Pretty.big_list kind (map (Display.pretty_thm_sg sg) thms)) end;
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    53
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    54
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    55
(* theory data kind 'HOL/induct_method' *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    56
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    57
structure GlobalInductArgs =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    58
struct
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    59
  val name = "HOL/induct_method";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    60
  type T = (rules * rules) * (rules * rules);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    61
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    62
  val empty = ((type_rules, set_rules), (type_rules, set_rules));
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    63
  val copy = I;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    64
  val prep_ext = I;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    65
  fun merge (((casesT1, casesS1), (inductT1, inductS1)),
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    66
      ((casesT2, casesS2), (inductT2, inductS2))) =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    67
    ((NetRules.merge (casesT1, casesT2), NetRules.merge (casesS1, casesS2)),
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    68
      (NetRules.merge (inductT1, inductT2), NetRules.merge (inductS1, inductS2)));
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    69
10008
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    70
  fun print sg ((casesT, casesS), (inductT, inductS)) =
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    71
    (print_rules "type cases:" sg casesT;
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    72
      print_rules "set cases:" sg casesS;
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    73
      print_rules "type induct:" sg inductT;
61eb9f3aa92a Display.pretty_thm_sg;
wenzelm
parents: 9914
diff changeset
    74
      print_rules "set induct:" sg inductS);
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    75
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    76
  fun dest ((casesT, casesS), (inductT, inductS)) =
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    77
    {type_cases = NetRules.rules casesT,
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    78
     set_cases = NetRules.rules casesS,
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    79
     type_induct = NetRules.rules inductT,
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    80
     set_induct = NetRules.rules inductS};
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    81
end;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    82
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    83
structure GlobalInduct = TheoryDataFun(GlobalInductArgs);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    84
val print_global_rules = GlobalInduct.print;
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
    85
val dest_global_rules = GlobalInductArgs.dest o GlobalInduct.get;
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    86
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    87
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    88
(* proof data kind 'HOL/induct_method' *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    89
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    90
structure LocalInductArgs =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    91
struct
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    92
  val name = "HOL/induct_method";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    93
  type T = GlobalInductArgs.T;
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
    94
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    95
  fun init thy = GlobalInduct.get thy;
10013
be4824b7505d made SML/NJ happy;
wenzelm
parents: 10008
diff changeset
    96
  fun print x = GlobalInductArgs.print (ProofContext.sign_of x);
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    97
end;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    98
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
    99
structure LocalInduct = ProofDataFun(LocalInductArgs);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   100
val print_local_rules = LocalInduct.print;
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   101
val dest_local_rules = GlobalInductArgs.dest o LocalInduct.get;
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   102
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   103
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   104
(* access rules *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   105
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   106
val get_cases = #1 o LocalInduct.get;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   107
val get_induct = #2 o LocalInduct.get;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   108
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   109
val lookup_casesT = lookup_rule o #1 o get_cases;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   110
val lookup_casesS = lookup_rule o #2 o get_cases;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   111
val lookup_inductT = lookup_rule o #1 o get_induct;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   112
val lookup_inductS = lookup_rule o #2 o get_induct;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   113
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   114
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   115
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   116
(** attributes **)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   117
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   118
local
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   119
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   120
fun mk_att f g name (x, thm) = (f (g (name, thm)) x, thm);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   121
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   122
fun add_casesT rule x = apfst (apfst (NetRules.insert rule)) x;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   123
fun add_casesS rule x = apfst (apsnd (NetRules.insert rule)) x;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   124
fun add_inductT rule x = apsnd (apfst (NetRules.insert rule)) x;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   125
fun add_inductS rule x = apsnd (apsnd (NetRules.insert rule)) x;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   126
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   127
in
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   128
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   129
val cases_type_global = mk_att GlobalInduct.map add_casesT;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   130
val cases_set_global = mk_att GlobalInduct.map add_casesS;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   131
val induct_type_global = mk_att GlobalInduct.map add_inductT;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   132
val induct_set_global = mk_att GlobalInduct.map add_inductS;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   133
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   134
val cases_type_local = mk_att LocalInduct.map add_casesT;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   135
val cases_set_local = mk_att LocalInduct.map add_casesS;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   136
val induct_type_local = mk_att LocalInduct.map add_inductT;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   137
val induct_set_local = mk_att LocalInduct.map add_inductS;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   138
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   139
end;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   140
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   141
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   142
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   143
(** misc utils **)
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   144
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   145
(* align lists *)
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   146
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   147
fun align_left msg xs ys =
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   148
  let val m = length xs and n = length ys
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   149
  in if m < n then error msg else (Library.take (n, xs) ~~ ys) end;
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   150
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   151
fun align_right msg xs ys =
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   152
  let val m = length xs and n = length ys
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   153
  in if m < n then error msg else (Library.drop (m - n, xs) ~~ ys) end;
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   154
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   155
8695
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   156
(* thms and terms *)
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   157
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   158
val concls_of = HOLogic.dest_conj o HOLogic.dest_Trueprop o Thm.concl_of;
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   159
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   160
fun vars_of tm =        (*ordered left-to-right, preferring right!*)
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   161
  Term.foldl_aterms (fn (ts, t as Var _) => t :: ts | (ts, _) => ts) ([], tm)
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   162
  |> Library.distinct |> rev;
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   163
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   164
fun type_name t =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   165
  #1 (Term.dest_Type (Term.type_of t))
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   166
    handle TYPE _ => raise TERM ("Type of term argument is too general", [t]);
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   167
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   168
fun prep_inst align cert (tm, ts) =
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   169
  let
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   170
    fun prep_var (x, Some t) = Some (cert x, cert t)
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   171
      | prep_var (_, None) = None;
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   172
  in
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   173
    align "Rule has fewer variables than instantiations given" (vars_of tm) ts
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   174
    |> mapfilter prep_var
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   175
  end;
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   176
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   177
8337
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   178
(* simplifying cases rules *)
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   179
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   180
local
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   181
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   182
(*delete needless equality assumptions*)
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   183
val refl_thin = prove_goal HOL.thy "!!P. [| a=a;  P |] ==> P"
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   184
     (fn _ => [assume_tac 1]);
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   185
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   186
val elim_rls = [asm_rl, FalseE, refl_thin, conjE, exE, Pair_inject];
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   187
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   188
val elim_tac = REPEAT o Tactic.eresolve_tac elim_rls;
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   189
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   190
in
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   191
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   192
fun simp_case_tac solved ss i =
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   193
  EVERY' [elim_tac, asm_full_simp_tac ss, elim_tac, REPEAT o bound_hyp_subst_tac] i
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   194
  THEN_MAYBE (if solved then no_tac else all_tac);
8337
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   195
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   196
end;
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   197
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   198
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   199
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   200
(** cases method **)
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   201
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   202
(*
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   203
  rule selection:
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   204
        cases         - classical case split
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   205
        cases t       - datatype exhaustion
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   206
  <x:A> cases ...     - set elimination
8451
614f18139d47 tuned comments;
wenzelm
parents: 8431
diff changeset
   207
  ...   cases ... R   - explicit rule
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   208
*)
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   209
9066
b1e874e38dab theorems [cases type: bool] = case_split;
wenzelm
parents: 8815
diff changeset
   210
val case_split = RuleCases.name ["True", "False"] case_split_thm;
b1e874e38dab theorems [cases type: bool] = case_split;
wenzelm
parents: 8815
diff changeset
   211
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   212
local
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   213
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   214
(* FIXME
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   215
fun cases_vars thm =
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   216
  (case try (vars_of o hd o Logic.strip_assums_hyp o Library.last_elem o Thm.prems_of) thm of
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   217
    None => raise THM ("Malformed cases rule", 0, [thm])
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   218
  | Some xs => xs);
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   219
*)
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   220
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   221
fun simplified_cases ctxt cases thm =
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   222
  let
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   223
    val nprems = Thm.nprems_of thm;
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   224
    val opt_cases =
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   225
      Library.replicate (nprems - Int.min (nprems, length cases)) None @
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   226
      map Some (Library.take (nprems, cases));
8337
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   227
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   228
    val tac = simp_case_tac true (Simplifier.get_local_simpset ctxt);
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   229
    fun simp ((i, c), (th, cs)) =
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   230
      (case try (Tactic.rule_by_tactic (tac i)) th of
9313
b5a29408dc39 fixed simplified_cases;
wenzelm
parents: 9299
diff changeset
   231
        None => (th, c :: cs)
b5a29408dc39 fixed simplified_cases;
wenzelm
parents: 9299
diff changeset
   232
      | Some th' => (th', None :: cs));
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   233
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   234
    val (thm', opt_cases') = foldr simp (1 upto Thm.nprems_of thm ~~ opt_cases, (thm, []));
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   235
  in (thm', mapfilter I opt_cases') end;
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   236
9624
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   237
fun cases_tac (ctxt, ((simplified, open_parms), args)) facts =
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   238
  let
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   239
    val sg = ProofContext.sign_of ctxt;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   240
    val cert = Thm.cterm_of sg;
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   241
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   242
    fun inst_rule insts thm =
9914
67e9b7239548 case args: align_right;
wenzelm
parents: 9893
diff changeset
   243
      (align_left "Rule has fewer premises than arguments given" (Thm.prems_of thm) insts
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   244
        |> (flat o map (prep_inst align_left cert))
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   245
        |> Drule.cterm_instantiate) thm;
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   246
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   247
    fun find_cases th =
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   248
      NetRules.may_unify (#2 (get_cases ctxt))
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   249
        (Logic.strip_assums_concl (#prop (Thm.rep_thm th)));
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   250
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   251
    val rules =
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   252
      (case (args, facts) of
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   253
        (([], None), []) => [RuleCases.add case_split]
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   254
      | ((insts, None), []) =>
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   255
          let
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   256
            val name = type_name (hd (flat (map (mapfilter I) insts)))
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   257
              handle Library.LIST _ => error "Unable to figure out type cases rule"
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   258
          in
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   259
            (case lookup_casesT ctxt name of
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   260
              None => error ("No cases rule for type: " ^ quote name)
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   261
            | Some thm => [(inst_rule insts thm, RuleCases.get thm)])
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   262
          end
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   263
      | (([], None), th :: _) => map (RuleCases.add o #2) (find_cases th)
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   264
      | ((insts, None), th :: _) =>
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   265
          (case find_cases th of        (*may instantiate first rule only!*)
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   266
            (_, thm) :: _ => [(inst_rule insts thm, RuleCases.get thm)]
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   267
          | [] => [])
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   268
      | (([], Some thm), _) => [RuleCases.add thm]
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   269
      | ((insts, Some thm), _) => [(inst_rule insts thm, RuleCases.get thm)]);
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   270
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   271
    val cond_simp = if simplified then simplified_cases ctxt else rpair;
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   272
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   273
    fun prep_rule (thm, cases) =
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   274
      Seq.map (cond_simp cases) (Method.multi_resolves facts [thm]);
9624
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   275
  in Method.resolveq_cases_tac open_parms (Seq.flat (Seq.map prep_rule (Seq.of_list rules))) end;
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   276
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   277
in
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   278
8671
6ce91a80f616 HEADGOAL;
wenzelm
parents: 8540
diff changeset
   279
val cases_meth = Method.METHOD_CASES o (HEADGOAL oo cases_tac);
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   280
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   281
end;
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   282
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   283
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   284
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   285
(** induct method **)
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   286
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   287
(*
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   288
  rule selection:
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   289
        induct         - mathematical induction
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   290
        induct x       - datatype induction
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   291
  <x:A> induct ...     - set induction
8451
614f18139d47 tuned comments;
wenzelm
parents: 8431
diff changeset
   292
  ...   induct ... R   - explicit rule
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   293
*)
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   294
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   295
local
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   296
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   297
infix 1 THEN_ALL_NEW_CASES;
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   298
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   299
fun (tac1 THEN_ALL_NEW_CASES tac2) i st =
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   300
  st |> Seq.THEN (tac1 i, (fn (st', cases) =>
8540
3a45bc1ff175 tuned degenerate cases / induct;
wenzelm
parents: 8451
diff changeset
   301
    Seq.map (rpair cases) (Seq.INTERVAL tac2 i (i + nprems_of st' - nprems_of st) st')));
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   302
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   303
8330
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   304
fun induct_rule ctxt t =
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   305
  let val name = type_name t in
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   306
    (case lookup_inductT ctxt name of
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   307
      None => error ("No induct rule for type: " ^ quote name)
8332
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   308
    | Some thm => (name, thm))
8330
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   309
  end;
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   310
8332
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   311
fun join_rules [(_, thm)] = thm
8330
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   312
  | join_rules raw_thms =
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   313
      let
8332
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   314
        val thms = (map (apsnd Drule.freeze_all) raw_thms);
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   315
        fun eq_prems ((_, th1), (_, th2)) =
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   316
          Term.aconvs (Thm.prems_of th1, Thm.prems_of th2);
8330
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   317
      in
8332
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   318
        (case Library.gen_distinct eq_prems thms of
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   319
          [(_, thm)] =>
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   320
            let
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   321
              val cprems = Drule.cprems_of thm;
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   322
              val asms = map Thm.assume cprems;
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   323
              fun strip (_, th) = Drule.implies_elim_list th asms;
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   324
            in
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   325
              foldr1 (fn (th, th') => [th, th'] MRS conjI) (map strip thms)
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   326
              |> Drule.implies_intr_list cprems
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   327
              |> Drule.standard
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   328
            end
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   329
        | [] => error "No rule given"
88fe0f1a480f join_rules: compatibility check;
wenzelm
parents: 8330
diff changeset
   330
        | bads => error ("Incompatible rules for " ^ commas_quote (map #1 bads)))
8330
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   331
      end;
c411706dc503 join induct rules;
wenzelm
parents: 8315
diff changeset
   332
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   333
9624
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   334
fun induct_tac (ctxt, ((stripped, open_parms), args)) facts =
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   335
  let
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   336
    val sg = ProofContext.sign_of ctxt;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   337
    val cert = Thm.cterm_of sg;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   338
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   339
    fun inst_rule insts thm =
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   340
      (align_right "Rule has fewer conclusions than arguments given" (concls_of thm) insts
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   341
        |> (flat o map (prep_inst align_right cert))
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   342
        |> Drule.cterm_instantiate) thm;
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   343
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   344
    fun find_induct th =
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   345
      NetRules.may_unify (#2 (get_induct ctxt))
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   346
        (Logic.strip_assums_concl (#prop (Thm.rep_thm th)));
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   347
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   348
    val rules =
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   349
      (case (args, facts) of
8540
3a45bc1ff175 tuned degenerate cases / induct;
wenzelm
parents: 8451
diff changeset
   350
        (([], None), []) => []
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   351
      | ((insts, None), []) =>
8695
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   352
          let val thms = map (induct_rule ctxt o last_elem o mapfilter I) insts
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   353
            handle Library.LIST _ => error "Unable to figure out type induction rule"
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   354
          in [(inst_rule insts (join_rules thms), RuleCases.get (#2 (hd thms)))] end
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   355
      | (([], None), th :: _) => map (RuleCases.add o #2) (find_induct th)
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   356
      | ((insts, None), th :: _) =>
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   357
          (case find_induct th of       (*may instantiate first rule only!*)
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   358
            (_, thm) :: _ => [(inst_rule insts thm, RuleCases.get thm)]
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   359
          | [] => [])
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   360
      | (([], Some thm), _) => [RuleCases.add thm]
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   361
      | ((insts, Some thm), _) => [(inst_rule insts thm, RuleCases.get thm)]);
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   362
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   363
    fun prep_rule (thm, cases) =
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   364
      Seq.map (rpair cases) (Method.multi_resolves facts [thm]);
9624
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   365
    val tac = Method.resolveq_cases_tac open_parms
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   366
      (Seq.flat (Seq.map prep_rule (Seq.of_list rules)));
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   367
  in
8688
63b267d41b96 induct stripped: match_tac;
wenzelm
parents: 8671
diff changeset
   368
    if stripped then tac THEN_ALL_NEW_CASES (REPEAT o Tactic.match_tac [impI, allI, ballI])
8376
f5628700ab9a added dest_global/local_rules;
wenzelm
parents: 8344
diff changeset
   369
    else tac
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   370
  end;
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   371
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   372
in
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   373
8671
6ce91a80f616 HEADGOAL;
wenzelm
parents: 8540
diff changeset
   374
val induct_meth = Method.METHOD_CASES o (HEADGOAL oo induct_tac);
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   375
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   376
end;
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   377
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   378
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   379
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   380
(** concrete syntax **)
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   381
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   382
val casesN = "cases";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   383
val inductN = "induct";
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   384
8337
5b6430edf06d added con_elim_s(olved_)tac;
wenzelm
parents: 8332
diff changeset
   385
val simplifiedN = "simplified";
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   386
val strippedN = "stripped";
9624
de254f375477 changed 'opaque' option to 'open' (opaque is default);
wenzelm
parents: 9597
diff changeset
   387
val openN = "open";
8344
4417e588d9f7 induct: "stripped" option;
wenzelm
parents: 8337
diff changeset
   388
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   389
val typeN = "type";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   390
val setN = "set";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   391
val ruleN = "rule";
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   392
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   393
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   394
(* attributes *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   395
8815
187547eae4c5 use Args.colon / Args.parens;
wenzelm
parents: 8695
diff changeset
   396
fun spec k = (Args.$$$ k -- Args.colon) |-- Args.!!! Args.name;
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   397
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   398
fun attrib sign_of add_type add_set = Scan.depend (fn x =>
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   399
  let val sg = sign_of x in
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   400
    spec typeN >> (add_type o Sign.intern_tycon sg) ||
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   401
    spec setN  >> (add_set o Sign.intern_const sg)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   402
  end >> pair x);
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   403
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   404
val cases_attr =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   405
  (Attrib.syntax (attrib Theory.sign_of cases_type_global cases_set_global),
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   406
   Attrib.syntax (attrib ProofContext.sign_of cases_type_local cases_set_local));
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   407
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   408
val induct_attr =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   409
  (Attrib.syntax (attrib Theory.sign_of induct_type_global induct_set_global),
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   410
   Attrib.syntax (attrib ProofContext.sign_of induct_type_local induct_set_local));
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   411
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   412
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   413
(* methods *)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   414
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   415
local
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   416
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   417
fun err k get name =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   418
  (case get name of Some x => x
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   419
  | None => error ("No rule for " ^ k ^ " " ^ quote name));
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   420
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   421
fun rule get_type get_set =
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   422
  Scan.depend (fn ctxt =>
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   423
    let val sg = ProofContext.sign_of ctxt in
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   424
      spec typeN >> (err typeN (get_type ctxt) o Sign.intern_tycon sg) ||
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   425
      spec setN >> (err setN (get_set ctxt) o Sign.intern_const sg)
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   426
    end >> pair ctxt) ||
8815
187547eae4c5 use Args.colon / Args.parens;
wenzelm
parents: 8695
diff changeset
   427
  Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.local_thm;
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   428
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   429
val cases_rule = rule lookup_casesT lookup_casesS;
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   430
val induct_rule = rule lookup_inductT lookup_inductS;
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   431
8815
187547eae4c5 use Args.colon / Args.parens;
wenzelm
parents: 8695
diff changeset
   432
val kind = (Args.$$$ typeN || Args.$$$ setN || Args.$$$ ruleN) -- Args.colon;
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   433
val term = Scan.unless (Scan.lift kind) Args.local_term;
8695
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   434
val term_dummy = Scan.unless (Scan.lift kind)
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   435
  (Scan.lift (Args.$$$ "_") >> K None || Args.local_term >> Some);
6446
583add9799c3 may specify induction predicates as well;
wenzelm
parents: 6442
diff changeset
   436
9597
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   437
val instss = Args.and_list (Scan.repeat1 term_dummy);
938a99cc55f7 cases: support multiple insts;
wenzelm
parents: 9313
diff changeset
   438
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   439
in
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   440
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   441
val cases_args = Method.syntax
9803
bc883b390d91 use Args.mode;
wenzelm
parents: 9624
diff changeset
   442
  (Args.mode simplifiedN -- Args.mode openN -- (instss -- Scan.option cases_rule));
9299
c5cda71de65d added simp_case_tac;
wenzelm
parents: 9230
diff changeset
   443
8695
850e84526745 export concl_of;
wenzelm
parents: 8688
diff changeset
   444
val induct_args = Method.syntax
9803
bc883b390d91 use Args.mode;
wenzelm
parents: 9624
diff changeset
   445
  (Args.mode strippedN -- Args.mode openN -- (instss -- Scan.option induct_rule));
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   446
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   447
end;
6446
583add9799c3 may specify induction predicates as well;
wenzelm
parents: 6442
diff changeset
   448
583add9799c3 may specify induction predicates as well;
wenzelm
parents: 6442
diff changeset
   449
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   450
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   451
(** theory setup **)
6446
583add9799c3 may specify induction predicates as well;
wenzelm
parents: 6442
diff changeset
   452
8278
5928c72b7057 induct: tuned syntax;
wenzelm
parents: 8154
diff changeset
   453
val setup =
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   454
  [GlobalInduct.init, LocalInduct.init,
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   455
   Attrib.add_attributes
9893
93d2fde0306c tuned msg;
wenzelm
parents: 9803
diff changeset
   456
    [(casesN, cases_attr, "declaration of cases rule for type or set"),
93d2fde0306c tuned msg;
wenzelm
parents: 9803
diff changeset
   457
     (inductN, induct_attr, "declaration of induction rule for type or set")],
8308
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   458
   Method.add_methods
45e11d3ccbe4 cases/induct attributes;
wenzelm
parents: 8295
diff changeset
   459
    [("cases", cases_meth oo cases_args, "case analysis on types or sets"),
9066
b1e874e38dab theorems [cases type: bool] = case_split;
wenzelm
parents: 8815
diff changeset
   460
     ("induct", induct_meth oo induct_args, "induction on types or sets")],
b1e874e38dab theorems [cases type: bool] = case_split;
wenzelm
parents: 8815
diff changeset
   461
   (#1 o PureThy.add_thms [(("case_split", case_split), [])])];
6442
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   462
6a95ceaa977e Proof by induction on types / set / functions.
wenzelm
parents:
diff changeset
   463
end;