src/Provers/induct_method.ML
author dixon
Sun, 27 Feb 2005 00:00:40 +0100
changeset 15550 806214035275
parent 15531 08c8dad8e399
child 15570 8d8c70b41bab
permissions -rw-r--r--
lucas - added more comments and an extra type to clarify the code.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     1
(*  Title:      Provers/induct_method.ML
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     2
    ID:         $Id$
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     3
    Author:     Markus Wenzel, TU Muenchen
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     4
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
     5
Proof by cases and induction on sets and types.
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     6
*)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     7
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     8
signature INDUCT_METHOD_DATA =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
     9
sig
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    10
  val dest_concls: term -> term list
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    11
  val cases_default: thm
11996
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
    12
  val local_impI: thm
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    13
  val conjI: thm
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    14
  val atomize: thm list
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    15
  val rulify1: thm list
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    16
  val rulify2: thm list
12240
0760eda193c4 induct method: localize rews for rule;
wenzelm
parents: 12168
diff changeset
    17
  val localize: thm list
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    18
end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    19
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    20
signature INDUCT_METHOD =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    21
sig
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    22
  val setup: (theory -> theory) list
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    23
end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    24
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    25
functor InductMethodFun(Data: INDUCT_METHOD_DATA): INDUCT_METHOD =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    26
struct
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    27
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    28
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    29
(** misc utils **)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    30
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    31
(* align lists *)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    32
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    33
fun align_left msg xs ys =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    34
  let val m = length xs and n = length ys
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    35
  in if m < n then raise ERROR_MESSAGE msg else (Library.take (n, xs) ~~ ys) end;
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    36
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    37
fun align_right msg xs ys =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    38
  let val m = length xs and n = length ys
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    39
  in if m < n then raise ERROR_MESSAGE msg else (Library.drop (m - n, xs) ~~ ys) end;
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    40
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    41
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    42
(* prep_inst *)
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    43
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    44
fun prep_inst align cert tune (tm, ts) =
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    45
  let
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
    46
    fun prep_var (x, SOME t) =
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    47
          let
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    48
            val cx = cert x;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    49
            val {T = xT, sign, ...} = Thm.rep_cterm cx;
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
    50
            val ct = cert (tune t);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    51
          in
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
    52
            if Sign.typ_instance sign (#T (Thm.rep_cterm ct), xT) then SOME (cx, ct)
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    53
            else raise ERROR_MESSAGE (Pretty.string_of (Pretty.block
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    54
             [Pretty.str "Ill-typed instantiation:", Pretty.fbrk,
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    55
              Display.pretty_cterm ct, Pretty.str " ::", Pretty.brk 1,
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    56
              Display.pretty_ctyp (#T (Thm.crep_cterm ct))]))
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    57
          end
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
    58
      | prep_var (_, NONE) = NONE;
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    59
    val xs = InductAttrib.vars_of tm;
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    60
  in
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    61
    align "Rule has fewer variables than instantiations given" xs ts
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    62
    |> mapfilter prep_var
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    63
  end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    64
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    65
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    66
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    67
(** cases method **)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    68
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    69
(*
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    70
  rule selection scheme:
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    71
          cases         - classical case split
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    72
    <x:A> cases ...     - set cases
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    73
          cases t       - type cases
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    74
    ...   cases ... R   - explicit rule
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    75
*)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    76
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    77
local
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    78
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
    79
fun resolveq_cases_tac make ruleq i st =
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
    80
  ruleq |> Seq.map (fn (rule, (cases, facts)) =>
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
    81
    (Method.insert_tac facts THEN' Tactic.rtac rule) i st
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
    82
    |> Seq.map (rpair (make (Thm.sign_of_thm rule, Thm.prop_of rule) cases)))
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
    83
  |> Seq.flat;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
    84
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
    85
fun find_casesT ctxt ((SOME t :: _) :: _) = InductAttrib.find_casesT ctxt (fastype_of t)
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    86
  | find_casesT _ _ = [];
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    87
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    88
fun find_casesS ctxt (fact :: _) = InductAttrib.find_casesS ctxt fact
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    89
  | find_casesS _ _ = [];
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    90
13597
a8230e035e96 fixes !!-bound vars in induction statement automatically
nipkow
parents: 13425
diff changeset
    91
fun cases_tac (ctxt, (is_open, (insts, opt_rule))) facts =
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    92
  let
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    93
    val sg = ProofContext.sign_of ctxt;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    94
    val cert = Thm.cterm_of sg;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    95
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    96
    fun inst_rule r =
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    97
      if null insts then RuleCases.add r
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
    98
      else (align_left "Rule has fewer premises than arguments given" (Thm.prems_of r) insts
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
    99
        |> (flat o map (prep_inst align_left cert I))
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   100
        |> Drule.cterm_instantiate) r |> rpair (RuleCases.get r);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   101
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   102
    val ruleq =
12852
c6a8e310aec5 cases: really append cases_default;
wenzelm
parents: 12799
diff changeset
   103
      (case opt_rule of
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   104
        NONE =>
12852
c6a8e310aec5 cases: really append cases_default;
wenzelm
parents: 12799
diff changeset
   105
          let val rules = find_casesS ctxt facts @ find_casesT ctxt insts @ [Data.cases_default] in
12053
7e2e84e503ce Method.trace ctxt;
wenzelm
parents: 11996
diff changeset
   106
            Method.trace ctxt rules;
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   107
            Seq.flat (Seq.map (Seq.try inst_rule) (Seq.of_list rules))
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   108
          end
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   109
      | SOME r => Seq.single (inst_rule r));
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   110
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   111
    fun prep_rule (th, (cases, n)) = Seq.map (apsnd (rpair (drop (n, facts))) o rpair cases)
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   112
      (Method.multi_resolves (take (n, facts)) [th]);
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   113
  in resolveq_cases_tac (RuleCases.make is_open NONE) (Seq.flat (Seq.map prep_rule ruleq)) end;
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   114
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   115
in
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   116
12852
c6a8e310aec5 cases: really append cases_default;
wenzelm
parents: 12799
diff changeset
   117
val cases_meth = Method.METHOD_CASES o ((Seq.DETERM o HEADGOAL) oo cases_tac);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   118
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   119
end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   120
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   121
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   122
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   123
(** induct method **)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   124
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   125
(*
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   126
  rule selection scheme:
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   127
    <x:A> induct ...     - set induction
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   128
          induct x       - type induction
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   129
    ...   induct ... R   - explicit rule
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   130
*)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   131
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   132
local
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   133
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   134
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   135
(* atomize and rulify *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   136
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   137
fun atomize_term sg =
13197
0567f4fd1415 Changed interface of MetaSimplifier.rewrite_term.
berghofe
parents: 13105
diff changeset
   138
  ObjectLogic.drop_judgment sg o MetaSimplifier.rewrite_term sg Data.atomize [];
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   139
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   140
fun rulified_term thm =
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   141
  let val sg = Thm.sign_of_thm thm in
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   142
    Thm.prop_of thm
13197
0567f4fd1415 Changed interface of MetaSimplifier.rewrite_term.
berghofe
parents: 13105
diff changeset
   143
    |> MetaSimplifier.rewrite_term sg Data.rulify1 []
0567f4fd1415 Changed interface of MetaSimplifier.rewrite_term.
berghofe
parents: 13105
diff changeset
   144
    |> MetaSimplifier.rewrite_term sg Data.rulify2 []
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   145
    |> pair sg
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   146
  end;
11756
8d8a87f350d6 use ObjectLogic stuff;
wenzelm
parents: 11735
diff changeset
   147
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   148
val atomize_tac = Tactic.rewrite_goal_tac Data.atomize;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   149
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   150
val rulify_tac =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   151
  Tactic.rewrite_goal_tac Data.rulify1 THEN'
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   152
  Tactic.rewrite_goal_tac Data.rulify2 THEN'
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   153
  Tactic.norm_hhf_tac;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   154
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   155
val localize = Tactic.norm_hhf_rule o Tactic.simplify false Data.localize;
12162
7c74a52da110 proper handling of mutual rules (esp. for sets);
wenzelm
parents: 12053
diff changeset
   156
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   157
11996
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   158
(* imp_intr --- limited to atomic prems *)
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   159
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   160
fun imp_intr i raw_th =
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   161
  let
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   162
    val th = Thm.permute_prems (i - 1) 1 raw_th;
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   163
    val cprems = Drule.cprems_of th;
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   164
    val As = take (length cprems - 1, cprems);
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   165
    val C = Thm.cterm_of (Thm.sign_of_thm th) (Var (("C", #maxidx (Thm.rep_thm th) + 1), propT));
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   166
    val dummy_st = Drule.mk_triv_goal (Drule.list_implies (As, C));
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   167
  in th COMP Thm.lift_rule (dummy_st, 1) Data.local_impI end;
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   168
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   169
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   170
(* join multi-rules *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   171
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   172
val eq_prems = curry (Term.aconvs o pairself Thm.prems_of);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   173
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   174
fun join_rules [] = []
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   175
  | join_rules [th] = [th]
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   176
  | join_rules (rules as r :: rs) =
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   177
      if not (forall (eq_prems r) rs) then []
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   178
      else
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   179
        let
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   180
          val th :: ths = map Drule.freeze_all rules;
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   181
          val cprems = Drule.cprems_of th;
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   182
          val asms = map Thm.assume cprems;
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   183
        in
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   184
          [foldr1 (fn (x, x') => [x, x'] MRS Data.conjI)
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   185
            (map (fn x => Drule.implies_elim_list x asms) (th :: ths))
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   186
          |> Drule.implies_intr_list cprems
12305
3c3f98b3d9e7 join_rules RuleCases.save;
wenzelm
parents: 12240
diff changeset
   187
          |> Drule.standard'
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 13197
diff changeset
   188
          |> RuleCases.save r]
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   189
        end;
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   190
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   191
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   192
(* divinate rule instantiation (cannot handle pending goal parameters) *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   193
11808
c724a9093ebe dest_env: norm_term on rhs;
wenzelm
parents: 11790
diff changeset
   194
fun dest_env sign (env as Envir.Envir {asol, iTs, ...}) =
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   195
  let
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   196
    val pairs = Vartab.dest asol;
11808
c724a9093ebe dest_env: norm_term on rhs;
wenzelm
parents: 11790
diff changeset
   197
    val ts = map (Thm.cterm_of sign o Envir.norm_term env o #2) pairs;
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   198
    val xs = map2 (Thm.cterm_of sign o Var) (map #1 pairs, map (#T o Thm.rep_cterm) ts);
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   199
  in (map (apsnd (Thm.ctyp_of sign)) (Vartab.dest iTs), xs ~~ ts) end;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   200
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   201
fun divinate_inst rule i st =
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   202
  let
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   203
    val {sign, maxidx, ...} = Thm.rep_thm st;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   204
    val goal = List.nth (Thm.prems_of st, i - 1);  (*exception Subscript*)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   205
    val params = rev (rename_wrt_term goal (Logic.strip_params goal));  (*as they are printed :-*)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   206
  in
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   207
    if not (null params) then
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   208
      (warning ("Cannot determine rule instantiation due to pending parameter(s): " ^
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   209
        commas (map (Sign.string_of_term sign o Syntax.mark_boundT) params));
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   210
      Seq.single rule)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   211
    else
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   212
      let
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   213
        val rule' = Thm.incr_indexes (maxidx + 1) rule;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   214
        val concl = Logic.strip_assums_concl goal;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   215
      in
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   216
        Unify.smash_unifiers (sign, Envir.empty (#maxidx (Thm.rep_thm rule')),
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   217
          [(Thm.concl_of rule', concl)])
12162
7c74a52da110 proper handling of mutual rules (esp. for sets);
wenzelm
parents: 12053
diff changeset
   218
        |> Seq.map (fn env => Drule.instantiate (dest_env sign env) rule')
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   219
      end
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   220
  end handle Subscript => Seq.empty;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   221
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   222
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   223
(* compose tactics with cases *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   224
11996
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   225
fun internalize k th = if k > 0 then internalize (k - 1) (imp_intr k th) else th;
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   226
13597
a8230e035e96 fixes !!-bound vars in induction statement automatically
nipkow
parents: 13425
diff changeset
   227
fun resolveq_cases_tac' make is_open ruleq i st =
11996
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   228
  ruleq |> Seq.map (fn (rule, (cases, k, more_facts)) => st
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   229
    |> (Method.insert_tac more_facts THEN' atomize_tac) i
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   230
    |> Seq.map (fn st' => divinate_inst (internalize k rule) i st' |> Seq.map (fn rule' =>
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   231
          st' |> Tactic.rtac rule' i
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   232
          |> Seq.map (rpair (make is_open (SOME (Thm.prop_of rule')) (rulified_term rule') cases)))
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   233
      |> Seq.flat)
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   234
    |> Seq.flat)
14404
4952c5a92e04 Transitive_Closure: added consumes and case_names attributes
nipkow
parents: 13597
diff changeset
   235
  |> Seq.flat;
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   236
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   237
infix 1 THEN_ALL_NEW_CASES;
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   238
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   239
fun (tac1 THEN_ALL_NEW_CASES tac2) i st =
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   240
  st |> Seq.THEN (tac1 i, (fn (st', cases) =>
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   241
    Seq.map (rpair cases) (Seq.INTERVAL tac2 i (i + nprems_of st' - nprems_of st) st')));
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   242
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   243
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   244
(* find rules *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   245
15235
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   246
(* rename all outermost !!-bound vars of type T in all premises of thm to x,
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   247
   possibly indexed to avoid clashes *)
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   248
fun rename [[SOME(Free(x,Type(T,_)))]] thm =
15235
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   249
  let
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   250
    fun index i [] = []
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   251
      | index i (y::ys) = if x=y then x^string_of_int i :: index (i+1) ys
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   252
                          else y :: index i ys;
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   253
    fun rename_params [] = []
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   254
      | rename_params ((y,Type(U,_))::ys) =
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   255
          (if U=T then x else y)::rename_params ys
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   256
      | rename_params ((y,_)::ys) = y::rename_params ys;
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   257
    fun rename_asm (A:term):term = 
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   258
      let val xs = rename_params (Logic.strip_params A)
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   259
          val xs' = case filter (equal x) xs of
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   260
                      [] => xs | [_] => xs | _ => index 1 xs
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   261
      in Logic.list_rename_params (xs',A) end;
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   262
    fun rename_prop (p:term) =
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   263
      let val (As,C) = Logic.strip_horn p
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   264
      in Logic.list_implies(map rename_asm As, C) end;
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   265
    val cp' = cterm_fun rename_prop (cprop_of thm);
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   266
    val thm' = equal_elim (reflexive cp') thm
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   267
  in Thm.put_name_tags (Thm.get_name_tags thm) thm' end
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   268
  | rename _ thm = thm;
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   269
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   270
fun find_inductT ctxt insts =
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   271
  foldr multiply (insts |> mapfilter (fn [] => NONE | ts => last_elem ts)
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   272
    |> map (InductAttrib.find_inductT ctxt o fastype_of), [[]])
15235
614a804d7116 Induction now preserves the name of the induction variable.
nipkow
parents: 14981
diff changeset
   273
  |> map join_rules |> flat |> map (rename insts);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   274
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   275
fun find_inductS ctxt (fact :: _) = InductAttrib.find_inductS ctxt fact
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   276
  | find_inductS _ _ = [];
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   277
11790
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   278
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   279
(* main tactic *)
42393a11642d simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents: 11781
diff changeset
   280
13597
a8230e035e96 fixes !!-bound vars in induction statement automatically
nipkow
parents: 13425
diff changeset
   281
fun induct_tac (ctxt, (is_open, (insts, opt_rule))) facts =
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   282
  let
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   283
    val sg = ProofContext.sign_of ctxt;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   284
    val cert = Thm.cterm_of sg;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   285
13105
3d1e7a199bdc use eq_thm_prop instead of slightly inadequate eq_thm;
wenzelm
parents: 12852
diff changeset
   286
    fun rule_versions r = Seq.cons (r, Seq.filter (not o curry Thm.eq_thm r)
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   287
        (Seq.make (fn () => SOME (localize r, Seq.empty))))
12168
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   288
      |> Seq.map (rpair (RuleCases.get r));
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   289
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   290
    val inst_rule = apfst (fn r =>
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   291
      if null insts then r
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   292
      else (align_right "Rule has fewer conclusions than arguments given"
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   293
          (Data.dest_concls (Thm.concl_of r)) insts
12799
5472afdd3bd3 MetaSimplifier.rewrite_term replaces slow Tactic.rewrite_cterm;
wenzelm
parents: 12305
diff changeset
   294
        |> (flat o map (prep_inst align_right cert (atomize_term sg)))
12168
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   295
        |> Drule.cterm_instantiate) r);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   296
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   297
    val ruleq =
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   298
      (case opt_rule of
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   299
        NONE =>
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   300
          let val rules = find_inductS ctxt facts @ find_inductT ctxt insts in
12168
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   301
            conditional (null rules) (fn () => error "Unable to figure out induct rule");
12053
7e2e84e503ce Method.trace ctxt;
wenzelm
parents: 11996
diff changeset
   302
            Method.trace ctxt rules;
12168
dc93c2e82205 induct: rule_versions produces localized variants;
wenzelm
parents: 12162
diff changeset
   303
            rules |> Seq.THEN (Seq.of_list, Seq.THEN (rule_versions, Seq.try inst_rule))
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   304
          end
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   305
      | SOME r => r |> Seq.THEN (rule_versions, Seq.single o inst_rule));
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   306
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   307
    fun prep_rule (th, (cases, n)) =
11996
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   308
      Seq.map (rpair (cases, n - length facts, drop (n, facts)))
b409a8cbe1fb induct: internalize ``missing'' consumes-facts from goal state
wenzelm
parents: 11984
diff changeset
   309
        (Method.multi_resolves (take (n, facts)) [th]);
13597
a8230e035e96 fixes !!-bound vars in induction statement automatically
nipkow
parents: 13425
diff changeset
   310
    val tac = resolveq_cases_tac' RuleCases.make is_open (Seq.flat (Seq.map prep_rule ruleq));
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   311
  in tac THEN_ALL_NEW_CASES rulify_tac end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   312
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   313
in
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   314
12852
c6a8e310aec5 cases: really append cases_default;
wenzelm
parents: 12799
diff changeset
   315
val induct_meth = Method.RAW_METHOD_CASES o ((Seq.DETERM o HEADGOAL) oo induct_tac);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   316
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   317
end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   318
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   319
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   320
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   321
(** concrete syntax **)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   322
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   323
val openN = "open";
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   324
val ruleN = "rule";
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   325
val ofN = "of";
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   326
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   327
local
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   328
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   329
fun check k get name =
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   330
  (case get name of SOME x => x
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   331
  | NONE => error ("No rule for " ^ k ^ " " ^ quote name));
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   332
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   333
fun spec k = (Args.$$$ k -- Args.colon) |-- Args.!!! Args.name;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   334
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   335
fun rule get_type get_set =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   336
  Scan.depend (fn ctxt =>
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   337
    let val sg = ProofContext.sign_of ctxt in
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   338
      spec InductAttrib.typeN >> (check InductAttrib.typeN (get_type ctxt) o
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   339
        Sign.certify_tyname sg o Sign.intern_tycon sg) ||
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   340
      spec InductAttrib.setN >> (check InductAttrib.setN (get_set ctxt) o
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   341
        Sign.certify_const sg o Sign.intern_const sg)
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   342
    end >> pair ctxt) ||
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   343
  Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.local_thm;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   344
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   345
val cases_rule = rule InductAttrib.lookup_casesT InductAttrib.lookup_casesS;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   346
val induct_rule = rule InductAttrib.lookup_inductT InductAttrib.lookup_inductS;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   347
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   348
val kind_inst =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   349
  (Args.$$$ InductAttrib.typeN || Args.$$$ InductAttrib.setN || Args.$$$ ruleN || Args.$$$ ofN)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   350
    -- Args.colon;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   351
val term = Scan.unless (Scan.lift kind_inst) Args.local_term;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   352
val term_dummy = Scan.unless (Scan.lift kind_inst)
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15235
diff changeset
   353
  (Scan.lift (Args.$$$ "_") >> K NONE || Args.local_term >> SOME);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   354
13425
119ae829ad9b support for split assumptions in cases (hyps vs. prems);
wenzelm
parents: 13197
diff changeset
   355
val instss = Args.and_list (Scan.repeat term_dummy);
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   356
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   357
in
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   358
11735
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   359
val cases_args = Method.syntax (Args.mode openN -- (instss -- Scan.option cases_rule));
60c0fa10bfc2 removed vars_of, concls_of;
wenzelm
parents: 11670
diff changeset
   360
val induct_args = Method.syntax (Args.mode openN -- (instss -- Scan.option induct_rule));
11670
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   361
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   362
end;
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   363
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   364
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   365
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   366
(** theory setup **)
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   367
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   368
val setup =
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   369
  [Method.add_methods
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   370
    [(InductAttrib.casesN, cases_meth oo cases_args, "case analysis on types or sets"),
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   371
     (InductAttrib.inductN, induct_meth oo induct_args, "induction on types or sets")]];
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   372
59f79df42d1f proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff changeset
   373
end;