src/Pure/subgoal.ML
author wenzelm
Sat Oct 13 16:19:16 2012 +0200 (2012-10-13)
changeset 49845 9b19c0e81166
parent 42495 1af81b70cf09
child 52223 5bb6ae8acb87
permissions -rw-r--r--
tuned signature;
wenzelm@20210
     1
(*  Title:      Pure/subgoal.ML
wenzelm@20210
     2
    Author:     Makarius
wenzelm@20210
     3
wenzelm@32281
     4
Tactical operations with explicit subgoal focus, based on canonical
wenzelm@32281
     5
proof decomposition.  The "visible" part of the text within the
wenzelm@32281
     6
context is fixed, the remaining goal may be schematic.
wenzelm@20210
     7
*)
wenzelm@20210
     8
wenzelm@20210
     9
signature SUBGOAL =
wenzelm@20210
    10
sig
wenzelm@32200
    11
  type focus = {context: Proof.context, params: (string * cterm) list, prems: thm list,
wenzelm@32281
    12
    asms: cterm list, concl: cterm, schematics: (ctyp * ctyp) list * (cterm * cterm) list}
wenzelm@32281
    13
  val focus_params: Proof.context -> int -> thm -> focus * thm
wenzelm@32281
    14
  val focus_prems: Proof.context -> int -> thm -> focus * thm
wenzelm@32200
    15
  val focus: Proof.context -> int -> thm -> focus * thm
wenzelm@32210
    16
  val retrofit: Proof.context -> Proof.context -> (string * cterm) list -> cterm list ->
wenzelm@32200
    17
    int -> thm -> thm -> thm Seq.seq
wenzelm@32281
    18
  val FOCUS_PARAMS: (focus -> tactic) -> Proof.context -> int -> tactic
wenzelm@32281
    19
  val FOCUS_PREMS: (focus -> tactic) -> Proof.context -> int -> tactic
wenzelm@32200
    20
  val FOCUS: (focus -> tactic) -> Proof.context -> int -> tactic
wenzelm@32200
    21
  val SUBPROOF: (focus -> tactic) -> Proof.context -> int -> tactic
wenzelm@20210
    22
end;
wenzelm@20210
    23
wenzelm@20210
    24
structure Subgoal: SUBGOAL =
wenzelm@20210
    25
struct
wenzelm@20210
    26
wenzelm@32200
    27
(* focus *)
wenzelm@32200
    28
wenzelm@32200
    29
type focus = {context: Proof.context, params: (string * cterm) list, prems: thm list,
wenzelm@32281
    30
  asms: cterm list, concl: cterm, schematics: (ctyp * ctyp) list * (cterm * cterm) list};
wenzelm@20210
    31
wenzelm@32281
    32
fun gen_focus (do_prems, do_concl) ctxt i raw_st =
wenzelm@20210
    33
  let
wenzelm@32281
    34
    val st = Simplifier.norm_hhf_protect raw_st;
wenzelm@32281
    35
    val ((schematic_types, [st']), ctxt1) = Variable.importT [st] ctxt;
wenzelm@42495
    36
    val ((params, goal), ctxt2) = Variable.focus_cterm (Thm.cprem_of st' i) ctxt1;
wenzelm@32281
    37
wenzelm@32213
    38
    val (asms, concl) =
wenzelm@32281
    39
      if do_prems then (Drule.strip_imp_prems goal, Drule.strip_imp_concl goal)
wenzelm@32281
    40
      else ([], goal);
wenzelm@32281
    41
    val text = asms @ (if do_concl then [concl] else []);
wenzelm@32281
    42
wenzelm@32281
    43
    val ((_, schematic_terms), ctxt3) =
wenzelm@32281
    44
      Variable.import_inst true (map Thm.term_of text) ctxt2
wenzelm@32281
    45
      |>> Thm.certify_inst (Thm.theory_of_thm raw_st);
wenzelm@32281
    46
wenzelm@32281
    47
    val schematics = (schematic_types, schematic_terms);
wenzelm@32281
    48
    val asms' = map (Thm.instantiate_cterm schematics) asms;
wenzelm@32281
    49
    val concl' = Thm.instantiate_cterm schematics concl;
wenzelm@32281
    50
    val (prems, context) = Assumption.add_assumes asms' ctxt3;
wenzelm@20210
    51
  in
wenzelm@32200
    52
    ({context = context, params = params, prems = prems,
wenzelm@32281
    53
      asms = asms', concl = concl', schematics = schematics}, Goal.init concl')
wenzelm@20210
    54
  end;
wenzelm@20210
    55
wenzelm@32281
    56
val focus_params = gen_focus (false, false);
wenzelm@32281
    57
val focus_prems = gen_focus (true, false);
wenzelm@32281
    58
val focus = gen_focus (true, true);
wenzelm@32213
    59
wenzelm@32200
    60
wenzelm@32200
    61
(* lift and retrofit *)
wenzelm@32200
    62
wenzelm@32200
    63
(*
wenzelm@32200
    64
     B [?'b, ?y]
wenzelm@32200
    65
  ----------------
wenzelm@32200
    66
  B ['b, y params]
wenzelm@32200
    67
*)
wenzelm@32284
    68
fun lift_import idx params th ctxt =
wenzelm@32200
    69
  let
wenzelm@42360
    70
    val cert = Thm.cterm_of (Proof_Context.theory_of ctxt);
wenzelm@32200
    71
    val ((_, [th']), ctxt') = Variable.importT [th] ctxt;
wenzelm@32200
    72
wenzelm@32200
    73
    val Ts = map (#T o Thm.rep_cterm) params;
wenzelm@32200
    74
    val ts = map Thm.term_of params;
wenzelm@32200
    75
wenzelm@32281
    76
    val prop = Thm.full_prop_of th';
wenzelm@32281
    77
    val concl_vars = Term.add_vars (Logic.strip_imp_concl prop) [];
wenzelm@32281
    78
    val vars = rev (Term.add_vars prop []);
wenzelm@32200
    79
    val (ys, ctxt'') = Variable.variant_fixes (map (Name.clean o #1 o #1) vars) ctxt';
wenzelm@32284
    80
wenzelm@32284
    81
    fun var_inst v y =
wenzelm@32284
    82
      let
wenzelm@32284
    83
        val ((x, i), T) = v;
wenzelm@32284
    84
        val (U, args) =
wenzelm@32284
    85
          if member (op =) concl_vars v then (T, [])
wenzelm@32284
    86
          else (Ts ---> T, ts);
wenzelm@32284
    87
        val u = Free (y, U);
wenzelm@32284
    88
        in ((Var v, list_comb (u, args)), (u, Var ((x, i + idx), U))) end;
wenzelm@32284
    89
    val (inst1, inst2) = split_list (map (pairself (pairself cert)) (map2 var_inst vars ys));
wenzelm@32284
    90
wenzelm@32284
    91
    val th'' = Thm.instantiate ([], inst1) th';
wenzelm@32284
    92
  in ((inst2, th''), ctxt'') end;
wenzelm@32200
    93
wenzelm@32200
    94
(*
wenzelm@32281
    95
       [x, A x]
wenzelm@32200
    96
          :
wenzelm@32281
    97
       B x ==> C
wenzelm@32200
    98
  ------------------
wenzelm@32200
    99
  [!!x. A x ==> B x]
wenzelm@32281
   100
          :
wenzelm@32281
   101
          C
wenzelm@32200
   102
*)
wenzelm@32200
   103
fun lift_subgoals params asms th =
wenzelm@32200
   104
  let
wenzelm@32329
   105
    fun lift ct = fold_rev Thm.all_name params (Drule.list_implies (asms, ct));
wenzelm@32200
   106
    val unlift =
wenzelm@32200
   107
      fold (Thm.elim_implies o Thm.assume) asms o
wenzelm@32200
   108
      Drule.forall_elim_list (map #2 params) o Thm.assume;
wenzelm@32200
   109
    val subgoals = map lift (Drule.strip_imp_prems (Thm.cprop_of th));
wenzelm@32200
   110
    val th' = fold (Thm.elim_implies o unlift) subgoals th;
wenzelm@32200
   111
  in (subgoals, th') end;
wenzelm@32200
   112
wenzelm@32213
   113
fun retrofit ctxt1 ctxt0 params asms i st1 st0 =
wenzelm@32200
   114
  let
wenzelm@32284
   115
    val idx = Thm.maxidx_of st0 + 1;
wenzelm@32200
   116
    val ps = map #2 params;
wenzelm@32284
   117
    val ((subgoal_inst, st2), ctxt2) = lift_import idx ps st1 ctxt1;
wenzelm@32213
   118
    val (subgoals, st3) = lift_subgoals params asms st2;
wenzelm@32213
   119
    val result = st3
wenzelm@32213
   120
      |> Goal.conclude
wenzelm@32200
   121
      |> Drule.implies_intr_list asms
wenzelm@32200
   122
      |> Drule.forall_intr_list ps
wenzelm@32200
   123
      |> Drule.implies_intr_list subgoals
wenzelm@32284
   124
      |> fold_rev (Thm.forall_intr o #1) subgoal_inst
wenzelm@32284
   125
      |> fold (Thm.forall_elim o #2) subgoal_inst
wenzelm@32284
   126
      |> Thm.adjust_maxidx_thm idx
wenzelm@32284
   127
      |> singleton (Variable.export ctxt2 ctxt0);
wenzelm@34075
   128
  in Thm.bicompose false (false, result, Thm.nprems_of st1) i st0 end;
wenzelm@32200
   129
wenzelm@32200
   130
wenzelm@32200
   131
(* tacticals *)
wenzelm@32200
   132
wenzelm@32281
   133
fun GEN_FOCUS flags tac ctxt i st =
wenzelm@20210
   134
  if Thm.nprems_of st < i then Seq.empty
wenzelm@20210
   135
  else
wenzelm@32329
   136
    let val (args as {context = ctxt', params, asms, ...}, st') = gen_focus flags ctxt i st;
wenzelm@32329
   137
    in Seq.lifts (retrofit ctxt' ctxt params asms i) (tac args st') st end;
wenzelm@32200
   138
wenzelm@32281
   139
val FOCUS_PARAMS = GEN_FOCUS (false, false);
wenzelm@32281
   140
val FOCUS_PREMS = GEN_FOCUS (true, false);
wenzelm@32281
   141
val FOCUS = GEN_FOCUS (true, true);
wenzelm@32213
   142
wenzelm@49845
   143
fun SUBPROOF tac ctxt = FOCUS (Seq.map (Goal.check_finished ctxt) oo tac) ctxt;
wenzelm@20210
   144
wenzelm@20210
   145
end;
wenzelm@20210
   146
wenzelm@32200
   147
val SUBPROOF = Subgoal.SUBPROOF;
wenzelm@32200
   148