advanced retrofit, which allows new subgoals and variables;
authorwenzelm
Sun, 26 Jul 2009 13:12:54 +0200
changeset 32200 2bd8ab91a426
parent 32199 82c4c570310a
child 32201 3689b647356d
advanced retrofit, which allows new subgoals and variables; added FOCUS -- does not require closed proof;
src/Pure/subgoal.ML
--- a/src/Pure/subgoal.ML	Sun Jul 26 13:12:54 2009 +0200
+++ b/src/Pure/subgoal.ML	Sun Jul 26 13:12:54 2009 +0200
@@ -1,30 +1,28 @@
 (*  Title:      Pure/subgoal.ML
     Author:     Makarius
 
-Tactical operations depending on local subgoal structure.
+Tactical operations with explicit subgoal focus, based on
+canonical proof decomposition (similar to fix/assume/show).
 *)
 
-signature BASIC_SUBGOAL =
-sig
-  val SUBPROOF:
-    ({context: Proof.context, schematics: ctyp list * cterm list,
-      params: cterm list, asms: cterm list, concl: cterm,
-      prems: thm list} -> tactic) -> Proof.context -> int -> tactic
-end
-
 signature SUBGOAL =
 sig
-  include BASIC_SUBGOAL
-  val focus: Proof.context -> int -> thm ->
-   {context: Proof.context, schematics: ctyp list * cterm list,
-    params: cterm list, asms: cterm list, concl: cterm, prems: thm list} * thm
-
+  type focus = {context: Proof.context, params: (string * cterm) list, prems: thm list,
+    asms: cterm list, concl: cterm, schematics: ctyp list * cterm list}
+  val focus: Proof.context -> int -> thm -> focus * thm
+  val retrofit: Proof.context -> (string * cterm) list -> cterm list ->
+    int -> thm -> thm -> thm Seq.seq
+  val FOCUS: (focus -> tactic) -> Proof.context -> int -> tactic
+  val SUBPROOF: (focus -> tactic) -> Proof.context -> int -> tactic
 end;
 
 structure Subgoal: SUBGOAL =
 struct
 
-(* canonical proof decomposition -- similar to fix/assume/show *)
+(* focus *)
+
+type focus = {context: Proof.context, params: (string * cterm) list, prems: thm list,
+  asms: cterm list, concl: cterm, schematics: ctyp list * cterm list};
 
 fun focus ctxt i st =
   let
@@ -35,24 +33,78 @@
     val concl = Drule.strip_imp_concl goal;
     val (prems, context) = Assumption.add_assumes asms ctxt'';
   in
-    ({context = context, schematics = schematics, params = params,
-      asms = asms, concl = concl, prems = prems}, Goal.init concl)
+    ({context = context, params = params, prems = prems,
+      asms = asms, concl = concl, schematics = schematics}, Goal.init concl)
   end;
 
-fun SUBPROOF tac ctxt i st =
+
+(* lift and retrofit *)
+
+(*
+     B [?'b, ?y]
+  ----------------
+  B ['b, y params]
+*)
+fun lift_import params th ctxt =
+  let
+    val cert = Thm.cterm_of (Thm.theory_of_thm th);
+    val ((_, [th']), ctxt') = Variable.importT [th] ctxt;
+
+    val Ts = map (#T o Thm.rep_cterm) params;
+    val ts = map Thm.term_of params;
+
+    val vars = rev (Term.add_vars (Thm.full_prop_of th') []);
+    val (ys, ctxt'') = Variable.variant_fixes (map (Name.clean o #1 o #1) vars) ctxt';
+    fun var_inst (v as (_, T)) y =
+      (cert (Var v), cert (list_comb (Free (y, Ts ---> T), ts)));
+    val th'' = Thm.instantiate ([], map2 var_inst vars ys) th';
+  in (th'', ctxt'') end;
+
+(*
+        [A x]
+          :
+      B x ==> C
+  ------------------
+  [!!x. A x ==> B x]
+         :
+         C
+*)
+fun lift_subgoals params asms th =
+  let
+    val lift = fold_rev Thm.all_name params o curry Drule.list_implies asms;
+    val unlift =
+      fold (Thm.elim_implies o Thm.assume) asms o
+      Drule.forall_elim_list (map #2 params) o Thm.assume;
+    val subgoals = map lift (Drule.strip_imp_prems (Thm.cprop_of th));
+    val th' = fold (Thm.elim_implies o unlift) subgoals th;
+  in (subgoals, th') end;
+
+fun retrofit ctxt params asms i th =
+  let
+    val ps = map #2 params;
+    val res0 = Goal.conclude th;
+    val (res1, ctxt1) = lift_import ps res0 ctxt;
+    val (subgoals, res2) = lift_subgoals params asms res1;
+    val result = res2
+      |> Drule.implies_intr_list asms
+      |> Drule.forall_intr_list ps
+      |> Drule.implies_intr_list subgoals
+      |> singleton (Variable.export ctxt1 ctxt);
+  in Thm.compose_no_flatten false (result, Thm.nprems_of res0) i end;
+
+
+(* tacticals *)
+
+fun FOCUS tac ctxt i st =
   if Thm.nprems_of st < i then Seq.empty
   else
-    let
-      val (args as {context, params, ...}, st') = focus ctxt i st;
-      fun export_closed th =
-        let
-          val (th' :: params') = ProofContext.export context ctxt (th :: map Drule.mk_term params);
-          val vs = map (Thm.dest_arg o Drule.strip_imp_concl o Thm.cprop_of) params';
-        in Drule.forall_intr_list vs th' end;
-      fun retrofit th = Thm.compose_no_flatten false (th, 0) i;
-    in Seq.lifts retrofit (Seq.map (Goal.finish #> export_closed) (tac args st')) st end
+    let val (args as {context, params, asms, ...}, st') = focus ctxt i st;
+    in Seq.lifts (retrofit context params asms i) (tac args st') st end;
+
+fun SUBPROOF tac = FOCUS (FILTER Thm.no_prems o tac);
 
 end;
 
-structure BasicSubgoal: BASIC_SUBGOAL = Subgoal;
-open BasicSubgoal;
+val FOCUS = Subgoal.FOCUS;
+val SUBPROOF = Subgoal.SUBPROOF;
+