src/HOL/Tools/coinduction.ML
changeset 59158 05cb83f083b9
parent 59058 a78612c67ec0
child 59498 50b60f501b05
equal deleted inserted replaced
59157:949829bae42a 59158:05cb83f083b9
    11   val coinduction_tac: Proof.context -> term list -> thm option -> thm list -> cases_tactic
    11   val coinduction_tac: Proof.context -> term list -> thm option -> thm list -> cases_tactic
    12 end;
    12 end;
    13 
    13 
    14 structure Coinduction : COINDUCTION =
    14 structure Coinduction : COINDUCTION =
    15 struct
    15 struct
    16 
       
    17 open Ctr_Sugar_Util
       
    18 open Ctr_Sugar_General_Tactics
       
    19 
    16 
    20 fun filter_in_out _ [] = ([], [])
    17 fun filter_in_out _ [] = ([], [])
    21   | filter_in_out P (x :: xs) =
    18   | filter_in_out P (x :: xs) =
    22       let
    19       let
    23         val (ins, outs) = filter_in_out P xs;
    20         val (ins, outs) = filter_in_out P xs;
    77               HOLogic.mk_eq (Free (name, T), rhs))
    74               HOLogic.mk_eq (Free (name, T), rhs))
    78             names Ts raw_eqs;
    75             names Ts raw_eqs;
    79           val phi = eqs @ map (HOLogic.dest_Trueprop o prop_of) prems
    76           val phi = eqs @ map (HOLogic.dest_Trueprop o prop_of) prems
    80             |> try (Library.foldr1 HOLogic.mk_conj)
    77             |> try (Library.foldr1 HOLogic.mk_conj)
    81             |> the_default @{term True}
    78             |> the_default @{term True}
    82             |> list_exists_free vars
    79             |> Ctr_Sugar_Util.list_exists_free vars
    83             |> Term.map_abs_vars (Variable.revert_fixed ctxt)
    80             |> Term.map_abs_vars (Variable.revert_fixed ctxt)
    84             |> fold_rev Term.absfree (names ~~ Ts)
    81             |> fold_rev Term.absfree (names ~~ Ts)
    85             |> certify ctxt;
    82             |> Ctr_Sugar_Util.certify ctxt;
    86           val thm = cterm_instantiate_pos [SOME phi] raw_thm;
    83           val thm = Ctr_Sugar_Util.cterm_instantiate_pos [SOME phi] raw_thm;
    87           val e = length eqs;
    84           val e = length eqs;
    88           val p = length prems;
    85           val p = length prems;
    89         in
    86         in
    90           HEADGOAL (EVERY' [resolve_tac [thm],
    87           HEADGOAL (EVERY' [resolve_tac [thm],
    91             EVERY' (map (fn var =>
    88             EVERY' (map (fn var =>
    92               resolve_tac [cterm_instantiate_pos [NONE, SOME (certify ctxt var)] exI]) vars),
    89               resolve_tac
    93             if p = 0 then CONJ_WRAP' (K (resolve_tac [refl])) eqs
    90                 [Ctr_Sugar_Util.cterm_instantiate_pos
       
    91                   [NONE, SOME (Ctr_Sugar_Util.certify ctxt var)] exI]) vars),
       
    92             if p = 0 then Ctr_Sugar_Util.CONJ_WRAP' (K (resolve_tac [refl])) eqs
    94             else
    93             else
    95               REPEAT_DETERM_N e o (resolve_tac [conjI] THEN' resolve_tac [refl]) THEN'
    94               REPEAT_DETERM_N e o (resolve_tac [conjI] THEN' resolve_tac [refl]) THEN'
    96               CONJ_WRAP' (resolve_tac o single) prems,
    95               Ctr_Sugar_Util.CONJ_WRAP' (resolve_tac o single) prems,
    97             K (ALLGOALS_SKIP skip
    96             K (ALLGOALS_SKIP skip
    98                (REPEAT_DETERM_N (length vars) o (eresolve_tac [exE] THEN' rotate_tac ~1) THEN'
    97                (REPEAT_DETERM_N (length vars) o (eresolve_tac [exE] THEN' rotate_tac ~1) THEN'
    99                DELETE_PREMS_AFTER 0 (Subgoal.FOCUS (fn {prems, params, context = ctxt, ...} =>
    98                DELETE_PREMS_AFTER 0 (Subgoal.FOCUS (fn {prems, params, context = ctxt, ...} =>
   100                  (case prems of
    99                  (case prems of
   101                    [] => all_tac
   100                    [] => all_tac
   108                          member (fn (t, (_, t')) => t aconv (term_of t')) params t;
   107                          member (fn (t, (_, t')) => t aconv (term_of t')) params t;
   109                         val (eqs, assms') = filter_in_out (is_local_var o lhs_of_eq o prop_of) eqs;
   108                         val (eqs, assms') = filter_in_out (is_local_var o lhs_of_eq o prop_of) eqs;
   110                         val assms = assms' @ drop e inv_thms
   109                         val assms = assms' @ drop e inv_thms
   111                       in
   110                       in
   112                         HEADGOAL (Method.insert_tac (assms @ case_prems)) THEN
   111                         HEADGOAL (Method.insert_tac (assms @ case_prems)) THEN
   113                         unfold_thms_tac ctxt eqs
   112                         Ctr_Sugar_General_Tactics.unfold_thms_tac ctxt eqs
   114                       end)) ctxt)))])
   113                       end)) ctxt)))])
   115         end) ctxt) THEN'
   114         end) ctxt) THEN'
   116       K (prune_params_tac ctxt))
   115       K (prune_params_tac ctxt))
   117     #> Seq.maps (fn st =>
   116     #> Seq.maps (fn st =>
   118       CASES (Rule_Cases.make_common (Proof_Context.theory_of ctxt, prop_of st) cases) all_tac st)
   117       CASES (Rule_Cases.make_common (Proof_Context.theory_of ctxt, prop_of st) cases) all_tac st)
   135   named_rule Induct.typeN (Args.type_name {proper = false, strict = false}) get_type ||
   134   named_rule Induct.typeN (Args.type_name {proper = false, strict = false}) get_type ||
   136   named_rule Induct.predN (Args.const {proper = false, strict = false}) get_pred ||
   135   named_rule Induct.predN (Args.const {proper = false, strict = false}) get_pred ||
   137   named_rule Induct.setN (Args.const {proper = false, strict = false}) get_pred ||
   136   named_rule Induct.setN (Args.const {proper = false, strict = false}) get_pred ||
   138   Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms;
   137   Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms;
   139 
   138 
   140 val coinduct_rule = rule Induct.lookup_coinductT Induct.lookup_coinductP >> single_rule;
   139 val coinduct_rule =
       
   140   rule Induct.lookup_coinductT Induct.lookup_coinductP >> single_rule;
   141 
   141 
   142 fun unless_more_args scan = Scan.unless (Scan.lift
   142 fun unless_more_args scan = Scan.unless (Scan.lift
   143   ((Args.$$$ arbitraryN || Args.$$$ Induct.typeN ||
   143   ((Args.$$$ arbitraryN || Args.$$$ Induct.typeN ||
   144     Args.$$$ Induct.predN || Args.$$$ Induct.setN || Args.$$$ ruleN) -- Args.colon)) scan;
   144     Args.$$$ Induct.predN || Args.$$$ Induct.setN || Args.$$$ ruleN) -- Args.colon)) scan;
   145 
   145