23 val FOCUS_PARAMS: (focus -> tactic) -> Proof.context -> int -> tactic |
23 val FOCUS_PARAMS: (focus -> tactic) -> Proof.context -> int -> tactic |
24 val FOCUS_PARAMS_FIXED: (focus -> tactic) -> Proof.context -> int -> tactic |
24 val FOCUS_PARAMS_FIXED: (focus -> tactic) -> Proof.context -> int -> tactic |
25 val FOCUS_PREMS: (focus -> tactic) -> Proof.context -> int -> tactic |
25 val FOCUS_PREMS: (focus -> tactic) -> Proof.context -> int -> tactic |
26 val FOCUS: (focus -> tactic) -> Proof.context -> int -> tactic |
26 val FOCUS: (focus -> tactic) -> Proof.context -> int -> tactic |
27 val SUBPROOF: (focus -> tactic) -> Proof.context -> int -> tactic |
27 val SUBPROOF: (focus -> tactic) -> Proof.context -> int -> tactic |
28 val subgoal: Attrib.binding -> Attrib.binding option -> (binding * mixfix) list -> |
28 val subgoal: Attrib.binding -> Attrib.binding option -> string option list -> |
29 Proof.state -> focus * Proof.state |
29 Proof.state -> focus * Proof.state |
30 val subgoal_cmd: Attrib.binding -> Attrib.binding option -> (binding * mixfix) list -> |
30 val subgoal_cmd: Attrib.binding -> Attrib.binding option -> string option list -> |
31 Proof.state -> focus * Proof.state |
31 Proof.state -> focus * Proof.state |
32 end; |
32 end; |
33 |
33 |
34 structure Subgoal: SUBGOAL = |
34 structure Subgoal: SUBGOAL = |
35 struct |
35 struct |
161 |
161 |
162 (* Isar subgoal command *) |
162 (* Isar subgoal command *) |
163 |
163 |
164 local |
164 local |
165 |
165 |
166 fun gen_subgoal prep_atts raw_result_binding raw_prems_binding params state = |
166 fun rename_params ctxt param_specs st = |
|
167 let |
|
168 val _ = if Thm.no_prems st then error "No subgoals!" else (); |
|
169 val (A, C) = Logic.dest_implies (Thm.prop_of st); |
|
170 |
|
171 val params = |
|
172 map (apfst (Name.internal o Name.clean)) (Term.strip_all_vars A) |
|
173 |> Term.variant_frees A |> map #1; |
|
174 val _ = |
|
175 (case drop (length params) param_specs of |
|
176 [] => () |
|
177 | bad => error ("Excessive subgoal parameters: " ^ commas_quote (map (the_default "_") bad))); |
|
178 |
|
179 fun rename_list (SOME x :: xs) (y :: ys) = |
|
180 (Proof_Context.cert_var (Binding.name x, NONE, NoSyn) ctxt; x :: rename_list xs ys) |
|
181 | rename_list (NONE :: xs) (y :: ys) = y :: rename_list xs ys |
|
182 | rename_list _ ys = ys; |
|
183 |
|
184 fun rename_prop (x :: xs) ((c as Const ("Pure.all", _)) $ Abs (_, T, t)) = |
|
185 (c $ Abs (x, T, rename_prop xs t)) |
|
186 | rename_prop [] t = t; |
|
187 in |
|
188 Thm.renamed_prop (Logic.mk_implies (rename_prop (rename_list param_specs params) A, C)) st |
|
189 end; |
|
190 |
|
191 fun gen_subgoal prep_atts raw_result_binding raw_prems_binding param_specs state = |
167 let |
192 let |
168 val _ = Proof.assert_backward state; |
193 val _ = Proof.assert_backward state; |
169 |
194 |
170 val state1 = state |> Proof.refine_insert []; |
195 val state1 = state |> Proof.refine_insert []; |
171 val {context = ctxt, facts = facts, goal = st} = Proof.raw_goal state1; |
196 val {context = ctxt, facts = facts, goal = st} = Proof.raw_goal state1; |
174 val (prems_binding, do_prems) = |
199 val (prems_binding, do_prems) = |
175 (case raw_prems_binding of |
200 (case raw_prems_binding of |
176 SOME (b, raw_atts) => ((b, map (prep_atts ctxt) raw_atts), true) |
201 SOME (b, raw_atts) => ((b, map (prep_atts ctxt) raw_atts), true) |
177 | NONE => ((Binding.empty, []), false)); |
202 | NONE => ((Binding.empty, []), false)); |
178 |
203 |
179 fun check_param (b, mx) = ignore (Proof_Context.cert_var (b, NONE, mx) ctxt); |
204 val (subgoal_focus, _) = |
180 val _ = List.app check_param params; |
205 rename_params ctxt param_specs st |
181 |
206 |> (if do_prems then focus else focus_params_fixed) ctxt 1; |
182 val _ = if Thm.no_prems st then error "No subgoals!" else (); |
|
183 val subgoal_focus = |
|
184 #1 ((if do_prems then focus else focus_params_fixed) ctxt 1 st); |
|
185 |
207 |
186 fun after_qed (ctxt'', [[result]]) = |
208 fun after_qed (ctxt'', [[result]]) = |
187 Proof.end_block #> (fn state' => |
209 Proof.end_block #> (fn state' => |
188 let |
210 let |
189 val ctxt' = Proof.context_of state'; |
211 val ctxt' = Proof.context_of state'; |