src/Tools/induct.ML
changeset 24861 cc669ca5f382
parent 24832 64cd13299d39
child 24865 62c48c4bee48
equal deleted inserted replaced
24860:ceb634874e0c 24861:cc669ca5f382
    16 signature INDUCT =
    16 signature INDUCT =
    17 sig
    17 sig
    18   (*rule declarations*)
    18   (*rule declarations*)
    19   val vars_of: term -> term list
    19   val vars_of: term -> term list
    20   val dest_rules: Proof.context ->
    20   val dest_rules: Proof.context ->
    21     {type_cases: (string * thm) list, set_cases: (string * thm) list,
    21     {type_cases: (string * thm) list, pred_cases: (string * thm) list,
    22       type_induct: (string * thm) list, set_induct: (string * thm) list,
    22       type_induct: (string * thm) list, pred_induct: (string * thm) list,
    23       type_coinduct: (string * thm) list, set_coinduct: (string * thm) list}
    23       type_coinduct: (string * thm) list, pred_coinduct: (string * thm) list}
    24   val print_rules: Proof.context -> unit
    24   val print_rules: Proof.context -> unit
    25   val lookup_casesT: Proof.context -> string -> thm option
    25   val lookup_casesT: Proof.context -> string -> thm option
    26   val lookup_casesS: Proof.context -> string -> thm option
    26   val lookup_casesP: Proof.context -> string -> thm option
    27   val lookup_inductT: Proof.context -> string -> thm option
    27   val lookup_inductT: Proof.context -> string -> thm option
    28   val lookup_inductS: Proof.context -> string -> thm option
    28   val lookup_inductP: Proof.context -> string -> thm option
    29   val lookup_coinductT: Proof.context -> string -> thm option
    29   val lookup_coinductT: Proof.context -> string -> thm option
    30   val lookup_coinductS: Proof.context -> string -> thm option
    30   val lookup_coinductP: Proof.context -> string -> thm option
    31   val find_casesT: Proof.context -> typ -> thm list
    31   val find_casesT: Proof.context -> typ -> thm list
    32   val find_casesS: Proof.context -> term -> thm list
    32   val find_casesP: Proof.context -> term -> thm list
    33   val find_inductT: Proof.context -> typ -> thm list
    33   val find_inductT: Proof.context -> typ -> thm list
    34   val find_inductS: Proof.context -> term -> thm list
    34   val find_inductP: Proof.context -> term -> thm list
    35   val find_coinductT: Proof.context -> typ -> thm list
    35   val find_coinductT: Proof.context -> typ -> thm list
    36   val find_coinductS: Proof.context -> term -> thm list
    36   val find_coinductP: Proof.context -> term -> thm list
    37   val cases_type: string -> attribute
    37   val cases_type: string -> attribute
    38   val cases_set: string -> attribute
    38   val cases_pred: string -> attribute
    39   val induct_type: string -> attribute
    39   val induct_type: string -> attribute
    40   val induct_set: string -> attribute
    40   val induct_pred: string -> attribute
    41   val coinduct_type: string -> attribute
    41   val coinduct_type: string -> attribute
    42   val coinduct_set: string -> attribute
    42   val coinduct_pred: string -> attribute
    43   val casesN: string
    43   val casesN: string
    44   val inductN: string
    44   val inductN: string
    45   val coinductN: string
    45   val coinductN: string
    46   val typeN: string
    46   val typeN: string
       
    47   val predN: string
    47   val setN: string
    48   val setN: string
    48   (*proof methods*)
    49   (*proof methods*)
    49   val fix_tac: Proof.context -> int -> (string * typ) list -> int -> tactic
    50   val fix_tac: Proof.context -> int -> (string * typ) list -> int -> tactic
    50   val add_defs: (string option * term) option list -> Proof.context ->
    51   val add_defs: (string option * term) option list -> Proof.context ->
    51     (term option list * thm list) * Proof.context
    52     (term option list * thm list) * Proof.context
   128   val empty =
   129   val empty =
   129     ((init_rules (left_var_prem o #2), init_rules (Thm.major_prem_of o #2)),
   130     ((init_rules (left_var_prem o #2), init_rules (Thm.major_prem_of o #2)),
   130      (init_rules (right_var_concl o #2), init_rules (Thm.major_prem_of o #2)),
   131      (init_rules (right_var_concl o #2), init_rules (Thm.major_prem_of o #2)),
   131      (init_rules (left_var_concl o #2), init_rules (Thm.concl_of o #2)));
   132      (init_rules (left_var_concl o #2), init_rules (Thm.concl_of o #2)));
   132   val extend = I;
   133   val extend = I;
   133   fun merge _ (((casesT1, casesS1), (inductT1, inductS1), (coinductT1, coinductS1)),
   134   fun merge _ (((casesT1, casesP1), (inductT1, inductP1), (coinductT1, coinductP1)),
   134       ((casesT2, casesS2), (inductT2, inductS2), (coinductT2, coinductS2))) =
   135       ((casesT2, casesP2), (inductT2, inductP2), (coinductT2, coinductP2))) =
   135     ((NetRules.merge (casesT1, casesT2), NetRules.merge (casesS1, casesS2)),
   136     ((NetRules.merge (casesT1, casesT2), NetRules.merge (casesP1, casesP2)),
   136       (NetRules.merge (inductT1, inductT2), NetRules.merge (inductS1, inductS2)),
   137       (NetRules.merge (inductT1, inductT2), NetRules.merge (inductP1, inductP2)),
   137       (NetRules.merge (coinductT1, coinductT2), NetRules.merge (coinductS1, coinductS2)));
   138       (NetRules.merge (coinductT1, coinductT2), NetRules.merge (coinductP1, coinductP2)));
   138 );
   139 );
   139 
   140 
   140 val get_local = Induct.get o Context.Proof;
   141 val get_local = Induct.get o Context.Proof;
   141 
   142 
   142 fun dest_rules ctxt =
   143 fun dest_rules ctxt =
   143   let val ((casesT, casesS), (inductT, inductS), (coinductT, coinductS)) = get_local ctxt in
   144   let val ((casesT, casesP), (inductT, inductP), (coinductT, coinductP)) = get_local ctxt in
   144     {type_cases = NetRules.rules casesT,
   145     {type_cases = NetRules.rules casesT,
   145      set_cases = NetRules.rules casesS,
   146      pred_cases = NetRules.rules casesP,
   146      type_induct = NetRules.rules inductT,
   147      type_induct = NetRules.rules inductT,
   147      set_induct = NetRules.rules inductS,
   148      pred_induct = NetRules.rules inductP,
   148      type_coinduct = NetRules.rules coinductT,
   149      type_coinduct = NetRules.rules coinductT,
   149      set_coinduct = NetRules.rules coinductS}
   150      pred_coinduct = NetRules.rules coinductP}
   150   end;
   151   end;
   151 
   152 
   152 fun print_rules ctxt =
   153 fun print_rules ctxt =
   153   let val ((casesT, casesS), (inductT, inductS), (coinductT, coinductS)) = get_local ctxt in
   154   let val ((casesT, casesP), (inductT, inductP), (coinductT, coinductP)) = get_local ctxt in
   154    [pretty_rules ctxt "coinduct type:" coinductT,
   155    [pretty_rules ctxt "coinduct type:" coinductT,
   155     pretty_rules ctxt "coinduct set:" coinductS,
   156     pretty_rules ctxt "coinduct pred:" coinductP,
   156     pretty_rules ctxt "induct type:" inductT,
   157     pretty_rules ctxt "induct type:" inductT,
   157     pretty_rules ctxt "induct set:" inductS,
   158     pretty_rules ctxt "induct pred:" inductP,
   158     pretty_rules ctxt "cases type:" casesT,
   159     pretty_rules ctxt "cases type:" casesT,
   159     pretty_rules ctxt "cases set:" casesS]
   160     pretty_rules ctxt "cases pred:" casesP]
   160     |> Pretty.chunks |> Pretty.writeln
   161     |> Pretty.chunks |> Pretty.writeln
   161   end;
   162   end;
   162 
   163 
   163 val _ = OuterSyntax.add_parsers [
   164 val _ = OuterSyntax.add_parsers [
   164   OuterSyntax.improper_command "print_induct_rules" "print induction and cases rules"
   165   OuterSyntax.improper_command "print_induct_rules" "print induction and cases rules"
   167 
   168 
   168 
   169 
   169 (* access rules *)
   170 (* access rules *)
   170 
   171 
   171 val lookup_casesT = lookup_rule o #1 o #1 o get_local;
   172 val lookup_casesT = lookup_rule o #1 o #1 o get_local;
   172 val lookup_casesS = lookup_rule o #2 o #1 o get_local;
   173 val lookup_casesP = lookup_rule o #2 o #1 o get_local;
   173 val lookup_inductT = lookup_rule o #1 o #2 o get_local;
   174 val lookup_inductT = lookup_rule o #1 o #2 o get_local;
   174 val lookup_inductS = lookup_rule o #2 o #2 o get_local;
   175 val lookup_inductP = lookup_rule o #2 o #2 o get_local;
   175 val lookup_coinductT = lookup_rule o #1 o #3 o get_local;
   176 val lookup_coinductT = lookup_rule o #1 o #3 o get_local;
   176 val lookup_coinductS = lookup_rule o #2 o #3 o get_local;
   177 val lookup_coinductP = lookup_rule o #2 o #3 o get_local;
   177 
   178 
   178 
   179 
   179 fun find_rules which how ctxt x =
   180 fun find_rules which how ctxt x =
   180   map snd (NetRules.retrieve (which (get_local ctxt)) (how x));
   181   map snd (NetRules.retrieve (which (get_local ctxt)) (how x));
   181 
   182 
   182 val find_casesT = find_rules (#1 o #1) encode_type;
   183 val find_casesT = find_rules (#1 o #1) encode_type;
   183 val find_casesS = find_rules (#2 o #1) I;
   184 val find_casesP = find_rules (#2 o #1) I;
   184 val find_inductT = find_rules (#1 o #2) encode_type;
   185 val find_inductT = find_rules (#1 o #2) encode_type;
   185 val find_inductS = find_rules (#2 o #2) I;
   186 val find_inductP = find_rules (#2 o #2) I;
   186 val find_coinductT = find_rules (#1 o #3) encode_type;
   187 val find_coinductT = find_rules (#1 o #3) encode_type;
   187 val find_coinductS = find_rules (#2 o #3) I;
   188 val find_coinductP = find_rules (#2 o #3) I;
   188 
   189 
   189 
   190 
   190 
   191 
   191 (** attributes **)
   192 (** attributes **)
   192 
   193 
   198 fun map1 f (x, y, z) = (f x, y, z);
   199 fun map1 f (x, y, z) = (f x, y, z);
   199 fun map2 f (x, y, z) = (x, f y, z);
   200 fun map2 f (x, y, z) = (x, f y, z);
   200 fun map3 f (x, y, z) = (x, y, f z);
   201 fun map3 f (x, y, z) = (x, y, f z);
   201 
   202 
   202 fun add_casesT rule x = map1 (apfst (NetRules.insert rule)) x;
   203 fun add_casesT rule x = map1 (apfst (NetRules.insert rule)) x;
   203 fun add_casesS rule x = map1 (apsnd (NetRules.insert rule)) x;
   204 fun add_casesP rule x = map1 (apsnd (NetRules.insert rule)) x;
   204 fun add_inductT rule x = map2 (apfst (NetRules.insert rule)) x;
   205 fun add_inductT rule x = map2 (apfst (NetRules.insert rule)) x;
   205 fun add_inductS rule x = map2 (apsnd (NetRules.insert rule)) x;
   206 fun add_inductP rule x = map2 (apsnd (NetRules.insert rule)) x;
   206 fun add_coinductT rule x = map3 (apfst (NetRules.insert rule)) x;
   207 fun add_coinductT rule x = map3 (apfst (NetRules.insert rule)) x;
   207 fun add_coinductS rule x = map3 (apsnd (NetRules.insert rule)) x;
   208 fun add_coinductP rule x = map3 (apsnd (NetRules.insert rule)) x;
   208 
   209 
   209 fun consumes0 x = RuleCases.consumes_default 0 x;
   210 fun consumes0 x = RuleCases.consumes_default 0 x;
   210 fun consumes1 x = RuleCases.consumes_default 1 x;
   211 fun consumes1 x = RuleCases.consumes_default 1 x;
   211 
   212 
   212 in
   213 in
   213 
   214 
   214 val cases_type = mk_att add_casesT consumes0;
   215 val cases_type = mk_att add_casesT consumes0;
   215 val cases_set = mk_att add_casesS consumes1;
   216 val cases_pred = mk_att add_casesP consumes1;
   216 val induct_type = mk_att add_inductT consumes0;
   217 val induct_type = mk_att add_inductT consumes0;
   217 val induct_set = mk_att add_inductS consumes1;
   218 val induct_pred = mk_att add_inductP consumes1;
   218 val coinduct_type = mk_att add_coinductT consumes0;
   219 val coinduct_type = mk_att add_coinductT consumes0;
   219 val coinduct_set = mk_att add_coinductS consumes1;
   220 val coinduct_pred = mk_att add_coinductP consumes1;
   220 
   221 
   221 end;
   222 end;
   222 
   223 
   223 
   224 
   224 
   225 
   227 val casesN = "cases";
   228 val casesN = "cases";
   228 val inductN = "induct";
   229 val inductN = "induct";
   229 val coinductN = "coinduct";
   230 val coinductN = "coinduct";
   230 
   231 
   231 val typeN = "type";
   232 val typeN = "type";
       
   233 val predN = "pred";
   232 val setN = "set";
   234 val setN = "set";
   233 
   235 
   234 local
   236 local
   235 
   237 
   236 fun spec k arg =
   238 fun spec k arg =
   237   Scan.lift (Args.$$$ k -- Args.colon) |-- arg ||
   239   Scan.lift (Args.$$$ k -- Args.colon) |-- arg ||
   238   Scan.lift (Args.$$$ k) >> K "";
   240   Scan.lift (Args.$$$ k) >> K "";
   239 
   241 
   240 fun attrib add_type add_set =
   242 fun attrib add_type add_pred = Attrib.syntax
   241   Attrib.syntax (spec typeN Args.tyname >> add_type || spec setN Args.const >> add_set);
   243  (spec typeN Args.tyname >> add_type ||
   242 
   244   spec predN Args.const >> add_pred ||
   243 val cases_att = attrib cases_type cases_set;
   245   spec setN Args.const >> add_pred);
   244 val induct_att = attrib induct_type induct_set;
   246 
   245 val coinduct_att = attrib coinduct_type coinduct_set;
   247 val cases_att = attrib cases_type cases_pred;
       
   248 val induct_att = attrib induct_type induct_pred;
       
   249 val coinduct_att = attrib coinduct_type coinduct_pred;
   246 
   250 
   247 in
   251 in
   248 
   252 
   249 val attrib_setup = Attrib.add_attributes
   253 val attrib_setup = Attrib.add_attributes
   250  [(casesN, cases_att, "declaration of cases rule for type or set"),
   254  [(casesN, cases_att, "declaration of cases rule for type or predicate/set"),
   251   (inductN, induct_att, "declaration of induction rule for type or set"),
   255   (inductN, induct_att, "declaration of induction rule for type or predicate/set"),
   252   (coinductN, coinduct_att, "declaration of coinduction rule for type or set")];
   256   (coinductN, coinduct_att, "declaration of coinduction rule for type or predicate/set")];
   253 
   257 
   254 end;
   258 end;
   255 
   259 
   256 
   260 
   257 
   261 
   312 (** cases method **)
   316 (** cases method **)
   313 
   317 
   314 (*
   318 (*
   315   rule selection scheme:
   319   rule selection scheme:
   316           cases         - default case split
   320           cases         - default case split
   317     `x:A` cases ...     - set cases
   321     `A t` cases ...     - predicate/set cases
   318           cases t       - type cases
   322           cases t       - type cases
   319     ...   cases ... r   - explicit rule
   323     ...   cases ... r   - explicit rule
   320 *)
   324 *)
   321 
   325 
   322 local
   326 local
   323 
   327 
   324 fun get_casesT ctxt ((SOME t :: _) :: _) = find_casesT ctxt (Term.fastype_of t)
   328 fun get_casesT ctxt ((SOME t :: _) :: _) = find_casesT ctxt (Term.fastype_of t)
   325   | get_casesT _ _ = [];
   329   | get_casesT _ _ = [];
   326 
   330 
   327 fun get_casesS ctxt (fact :: _) = find_casesS ctxt (Thm.concl_of fact)
   331 fun get_casesP ctxt (fact :: _) = find_casesP ctxt (Thm.concl_of fact)
   328   | get_casesS _ _ = [];
   332   | get_casesP _ _ = [];
   329 
   333 
   330 in
   334 in
   331 
   335 
   332 fun cases_tac ctxt is_open insts opt_rule facts =
   336 fun cases_tac ctxt is_open insts opt_rule facts =
   333   let
   337   let
   343 
   347 
   344     val ruleq =
   348     val ruleq =
   345       (case opt_rule of
   349       (case opt_rule of
   346         SOME r => Seq.single (inst_rule r)
   350         SOME r => Seq.single (inst_rule r)
   347       | NONE =>
   351       | NONE =>
   348           (get_casesS ctxt facts @ get_casesT ctxt insts @ [Data.cases_default])
   352           (get_casesP ctxt facts @ get_casesT ctxt insts @ [Data.cases_default])
   349           |> tap (trace_rules ctxt casesN)
   353           |> tap (trace_rules ctxt casesN)
   350           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   354           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   351   in
   355   in
   352     fn i => fn st =>
   356     fn i => fn st =>
   353       ruleq
   357       ruleq
   549 
   553 
   550 (* induct_tac *)
   554 (* induct_tac *)
   551 
   555 
   552 (*
   556 (*
   553   rule selection scheme:
   557   rule selection scheme:
   554     `x:A` induct ...     - set induction
   558     `A x` induct ...     - predicate/set induction
   555           induct x       - type induction
   559           induct x       - type induction
   556     ...   induct ... r   - explicit rule
   560     ...   induct ... r   - explicit rule
   557 *)
   561 *)
   558 
   562 
   559 local
   563 local
   561 fun get_inductT ctxt insts =
   565 fun get_inductT ctxt insts =
   562   fold_rev multiply (insts |> map_filter (fn [] => NONE | ts => List.last ts)
   566   fold_rev multiply (insts |> map_filter (fn [] => NONE | ts => List.last ts)
   563     |> map (find_inductT ctxt o Term.fastype_of)) [[]]
   567     |> map (find_inductT ctxt o Term.fastype_of)) [[]]
   564   |> filter_out (forall PureThy.is_internal);
   568   |> filter_out (forall PureThy.is_internal);
   565 
   569 
   566 fun get_inductS ctxt (fact :: _) = map single (find_inductS ctxt (Thm.concl_of fact))
   570 fun get_inductP ctxt (fact :: _) = map single (find_inductP ctxt (Thm.concl_of fact))
   567   | get_inductS _ _ = [];
   571   | get_inductP _ _ = [];
   568 
   572 
   569 in
   573 in
   570 
   574 
   571 fun induct_tac ctxt is_open def_insts arbitrary taking opt_rule facts =
   575 fun induct_tac ctxt is_open def_insts arbitrary taking opt_rule facts =
   572   let
   576   let
   587 
   591 
   588     val ruleq =
   592     val ruleq =
   589       (case opt_rule of
   593       (case opt_rule of
   590         SOME rs => Seq.single (inst_rule (RuleCases.strict_mutual_rule ctxt rs))
   594         SOME rs => Seq.single (inst_rule (RuleCases.strict_mutual_rule ctxt rs))
   591       | NONE =>
   595       | NONE =>
   592           (get_inductS ctxt facts @
   596           (get_inductP ctxt facts @
   593             map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts))
   597             map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts))
   594           |> map_filter (RuleCases.mutual_rule ctxt)
   598           |> map_filter (RuleCases.mutual_rule ctxt)
   595           |> tap (trace_rules ctxt inductN o map #2)
   599           |> tap (trace_rules ctxt inductN o map #2)
   596           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   600           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   597 
   601 
   625 
   629 
   626 (** coinduct method **)
   630 (** coinduct method **)
   627 
   631 
   628 (*
   632 (*
   629   rule selection scheme:
   633   rule selection scheme:
   630     goal "x:A" coinduct ...   - set coinduction
   634     goal "A x" coinduct ...   - predicate/set coinduction
   631                coinduct x     - type coinduction
   635                coinduct x     - type coinduction
   632                coinduct ... r - explicit rule
   636                coinduct ... r - explicit rule
   633 *)
   637 *)
   634 
   638 
   635 local
   639 local
   636 
   640 
   637 fun get_coinductT ctxt (SOME t :: _) = find_coinductT ctxt (Term.fastype_of t)
   641 fun get_coinductT ctxt (SOME t :: _) = find_coinductT ctxt (Term.fastype_of t)
   638   | get_coinductT _ _ = [];
   642   | get_coinductT _ _ = [];
   639 
   643 
   640 fun get_coinductS ctxt goal = find_coinductS ctxt (Logic.strip_assums_concl goal);
   644 fun get_coinductP ctxt goal = find_coinductP ctxt (Logic.strip_assums_concl goal);
       
   645 
       
   646 fun main_prop_of th =
       
   647   if RuleCases.get_consumes th > 0 then Thm.major_prem_of th else Thm.concl_of th;
   641 
   648 
   642 in
   649 in
   643 
   650 
   644 fun coinduct_tac ctxt is_open inst taking opt_rule facts =
   651 fun coinduct_tac ctxt is_open inst taking opt_rule facts =
   645   let
   652   let
   647     val thy = ProofContext.theory_of ctxt;
   654     val thy = ProofContext.theory_of ctxt;
   648     val cert = Thm.cterm_of thy;
   655     val cert = Thm.cterm_of thy;
   649 
   656 
   650     fun inst_rule r =
   657     fun inst_rule r =
   651       if null inst then `RuleCases.get r
   658       if null inst then `RuleCases.get r
   652       else Drule.cterm_instantiate (prep_inst thy align_left I (Thm.concl_of r, inst)) r
   659       else Drule.cterm_instantiate (prep_inst thy align_right I (main_prop_of r, inst)) r
   653         |> pair (RuleCases.get r);
   660         |> pair (RuleCases.get r);
   654 
   661 
   655     fun ruleq goal =
   662     fun ruleq goal =
   656       (case opt_rule of
   663       (case opt_rule of
   657         SOME r => Seq.single (inst_rule r)
   664         SOME r => Seq.single (inst_rule r)
   658       | NONE =>
   665       | NONE =>
   659           (get_coinductS ctxt goal @ get_coinductT ctxt inst)
   666           (get_coinductP ctxt goal @ get_coinductT ctxt inst)
   660           |> tap (trace_rules ctxt coinductN)
   667           |> tap (trace_rules ctxt coinductN)
   661           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   668           |> Seq.of_list |> Seq.maps (Seq.try inst_rule));
   662   in
   669   in
   663     SUBGOAL_CASES (fn (goal, i) => fn st =>
   670     SUBGOAL_CASES (fn (goal, i) => fn st =>
   664       ruleq goal
   671       ruleq goal
   691   Scan.lift (Args.$$$ k -- Args.colon) |-- Scan.repeat arg :|--
   698   Scan.lift (Args.$$$ k -- Args.colon) |-- Scan.repeat arg :|--
   692     (fn names => Scan.peek (fn context => Scan.succeed (names |> map (fn name =>
   699     (fn names => Scan.peek (fn context => Scan.succeed (names |> map (fn name =>
   693       (case get (Context.proof_of context) name of SOME x => x
   700       (case get (Context.proof_of context) name of SOME x => x
   694       | NONE => error ("No rule for " ^ k ^ " " ^ quote name))))));
   701       | NONE => error ("No rule for " ^ k ^ " " ^ quote name))))));
   695 
   702 
   696 fun rule get_type get_set =
   703 fun rule get_type get_pred =
   697   named_rule typeN Args.tyname get_type ||
   704   named_rule typeN Args.tyname get_type ||
   698   named_rule setN Args.const get_set ||
   705   named_rule predN Args.const get_pred ||
       
   706   named_rule setN Args.const get_pred ||
   699   Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms;
   707   Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms;
   700 
   708 
   701 val cases_rule = rule lookup_casesT lookup_casesS >> single_rule;
   709 val cases_rule = rule lookup_casesT lookup_casesP >> single_rule;
   702 val induct_rule = rule lookup_inductT lookup_inductS;
   710 val induct_rule = rule lookup_inductT lookup_inductP;
   703 val coinduct_rule = rule lookup_coinductT lookup_coinductS >> single_rule;
   711 val coinduct_rule = rule lookup_coinductT lookup_coinductP >> single_rule;
   704 
   712 
   705 val inst = Scan.lift (Args.$$$ "_") >> K NONE || Args.term >> SOME;
   713 val inst = Scan.lift (Args.$$$ "_") >> K NONE || Args.term >> SOME;
   706 
   714 
   707 val def_inst =
   715 val def_inst =
   708   ((Scan.lift (Args.name --| (Args.$$$ "\\<equiv>" || Args.$$$ "==")) >> SOME)
   716   ((Scan.lift (Args.name --| (Args.$$$ "\\<equiv>" || Args.$$$ "==")) >> SOME)
   712 val free = Scan.state -- Args.term >> (fn (_, Free v) => v | (context, t) =>
   720 val free = Scan.state -- Args.term >> (fn (_, Free v) => v | (context, t) =>
   713   error ("Bad free variable: " ^ ProofContext.string_of_term (Context.proof_of context) t));
   721   error ("Bad free variable: " ^ ProofContext.string_of_term (Context.proof_of context) t));
   714 
   722 
   715 fun unless_more_args scan = Scan.unless (Scan.lift
   723 fun unless_more_args scan = Scan.unless (Scan.lift
   716   ((Args.$$$ arbitraryN || Args.$$$ takingN || Args.$$$ typeN ||
   724   ((Args.$$$ arbitraryN || Args.$$$ takingN || Args.$$$ typeN ||
   717     Args.$$$ setN || Args.$$$ ruleN) -- Args.colon)) scan;
   725     Args.$$$ predN || Args.$$$ setN || Args.$$$ ruleN) -- Args.colon)) scan;
   718 
   726 
   719 val arbitrary = Scan.optional (Scan.lift (Args.$$$ arbitraryN -- Args.colon) |--
   727 val arbitrary = Scan.optional (Scan.lift (Args.$$$ arbitraryN -- Args.colon) |--
   720   Args.and_list1 (Scan.repeat (unless_more_args free))) [];
   728   Args.and_list1 (Scan.repeat (unless_more_args free))) [];
   721 
   729 
   722 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |--
   730 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |--
   753 (** theory setup **)
   761 (** theory setup **)
   754 
   762 
   755 val setup =
   763 val setup =
   756   attrib_setup #>
   764   attrib_setup #>
   757   Method.add_methods
   765   Method.add_methods
   758     [(casesN, cases_meth, "case analysis on types or sets"),
   766     [(casesN, cases_meth, "case analysis on types or predicates/sets"),
   759      (inductN, induct_meth, "induction on types or sets"),
   767      (inductN, induct_meth, "induction on types or predicates/sets"),
   760      (coinductN, coinduct_meth, "coinduction on types or sets")];
   768      (coinductN, coinduct_meth, "coinduction on types or predicates/sets")];
   761 
   769 
   762 end;
   770 end;