src/HOL/Tools/datatype_package.ML
changeset 8672 1f51c411da5a
parent 8645 40036a2ab646
child 8686 5893f2952e4f
     1.1 --- a/src/HOL/Tools/datatype_package.ML	Wed Apr 05 21:02:31 2000 +0200
     1.2 +++ b/src/HOL/Tools/datatype_package.ML	Wed Apr 05 21:05:20 2000 +0200
     1.3 @@ -169,46 +169,65 @@
     1.4  
     1.5  (* generic induction tactic for datatypes *)
     1.6  
     1.7 -fun induct_tac s i state =
     1.8 +fun gen_induct_tac (vars, opt_rule) i state =
     1.9    let
    1.10 -    val vars = Syntax.read_idents s;
    1.11      val (_, _, Bi, _) = dest_state (state, i);
    1.12      val {sign, ...} = rep_thm state;
    1.13 -    val tn = find_tname (hd vars) Bi;
    1.14 -    val {induction, ...} = datatype_info_sg_err sign tn;
    1.15 +    val (rule, rule_name) =
    1.16 +      (case opt_rule of
    1.17 +        Some r => (r, "Induction rule")
    1.18 +      | None =>
    1.19 +          let val tn = find_tname (hd vars) Bi
    1.20 +          in (#induction (datatype_info_sg_err sign tn), "Induction rule for type " ^ tn) end);
    1.21      val ind_vnames = map (fn (_ $ Var (ixn, _)) =>
    1.22        implode (tl (explode (Syntax.string_of_vname ixn))))
    1.23 -        (HOLogic.dest_conj (HOLogic.dest_Trueprop (concl_of induction)));
    1.24 +        (HOLogic.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of rule)));
    1.25      val insts = (ind_vnames ~~ vars) handle LIST _ =>
    1.26 -      error ("Induction rule for type " ^ tn ^ " has different number of variables")
    1.27 -  in
    1.28 -    occs_in_prems (res_inst_tac insts induction) vars i state
    1.29 -  end;
    1.30 +      error (rule_name ^ " has different number of variables");
    1.31 +  in occs_in_prems (Tactic.res_inst_tac insts rule) vars i state end;
    1.32 +
    1.33 +fun induct_tac s = gen_induct_tac (Syntax.read_idents s, None);
    1.34  
    1.35  
    1.36  (* generic case tactic for datatypes *)
    1.37  
    1.38 -fun case_tac aterm i state =
    1.39 -  let val name = infer_tname state i aterm in
    1.40 -    if name = HOLogic.boolN then res_inst_tac [("P", aterm)] case_split_thm i state
    1.41 -    else
    1.42 -      let
    1.43 -        val {exhaustion, ...} = datatype_info_sg_err (Thm.sign_of_thm state) name;
    1.44 -        val _ $ Var (ixn, _) $ _ = HOLogic.dest_Trueprop
    1.45 -          (hd (Logic.strip_assums_hyp (hd (prems_of exhaustion))));
    1.46 -        val exh_vname = implode (tl (explode (Syntax.string_of_vname ixn)))
    1.47 -      in res_inst_tac [(exh_vname, aterm)] exhaustion i state end
    1.48 -  end;
    1.49 +fun case_inst_tac t rule i state =
    1.50 +  let
    1.51 +    val _ $ Var (ixn, _) $ _ = HOLogic.dest_Trueprop
    1.52 +      (hd (Logic.strip_assums_hyp (hd (Thm.prems_of rule))));
    1.53 +    val exh_vname = implode (tl (explode (Syntax.string_of_vname ixn)));
    1.54 +  in Tactic.res_inst_tac [(exh_vname, t)] rule i state end;
    1.55 +
    1.56 +fun gen_case_tac (t, Some rule) i state = case_inst_tac t rule i state
    1.57 +  | gen_case_tac (t, None) i state =
    1.58 +      let val tn = infer_tname state i t in
    1.59 +        if tn = HOLogic.boolN then Tactic.res_inst_tac [("P", t)] case_split_thm i state
    1.60 +        else case_inst_tac t (#exhaustion (datatype_info_sg_err (Thm.sign_of_thm state) tn)) i state
    1.61 +      end;
    1.62 +
    1.63 +fun case_tac t = gen_case_tac (t, None);
    1.64 +
    1.65  
    1.66  
    1.67  (** Isar tactic emulations **)
    1.68  
    1.69 -fun tactic_syntax tac = #2 oo Method.syntax (Args.goal_spec HEADGOAL -- Scan.lift Args.name >>
    1.70 -  (fn (quant, s) => Method.METHOD (fn facts => quant (Method.insert_tac facts THEN' tac s))));
    1.71 +local
    1.72 +
    1.73 +val rule_spec = Scan.option (Scan.lift (Args.$$$ "rule" -- Args.$$$ ":") |-- Attrib.local_thm);
    1.74 +
    1.75 +fun tactic_syntax args tac =
    1.76 +  #2 oo Method.syntax (Args.goal_spec HEADGOAL -- (Scan.lift args -- rule_spec) >>
    1.77 +    (fn (quant, x) => Method.METHOD (fn facts => quant (Method.insert_tac facts THEN' tac x))));
    1.78 +
    1.79 +in
    1.80  
    1.81  val tactic_emulations =
    1.82 - [("induct_tac", tactic_syntax induct_tac, "induct_tac emulation (dynamic instantiation!)"),
    1.83 -  ("case_tac", tactic_syntax case_tac, "case_tac emulation (dynamic instantiation!)")];
    1.84 + [("induct_tac", tactic_syntax (Scan.repeat1 Args.name) gen_induct_tac,
    1.85 +    "induct_tac emulation (dynamic instantiation!)"),
    1.86 +  ("case_tac", tactic_syntax Args.name gen_case_tac,
    1.87 +    "case_tac emulation (dynamic instantiation!)")];
    1.88 +
    1.89 +end;
    1.90  
    1.91  
    1.92  
    1.93 @@ -253,7 +272,8 @@
    1.94        | proj i n thm =
    1.95            (if i + 1 < n then (fn th => th RS conjunct1) else I)
    1.96              (Library.funpow i (fn th => th RS conjunct2) thm)
    1.97 -          |> Drule.standard;
    1.98 +          |> Drule.standard
    1.99 +          |> RuleCases.name (RuleCases.get thm);
   1.100  
   1.101      fun add (ths, (name, {index, descr, induction, exhaustion, ...}: datatype_info)) =
   1.102        (("", proj index (length descr) induction), [InductMethod.induct_type_global name]) ::