--- 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;
+