29 val FIRST: tactic list -> tactic |
29 val FIRST: tactic list -> tactic |
30 val FIRST': ('a -> tactic) list -> 'a -> tactic |
30 val FIRST': ('a -> tactic) list -> 'a -> tactic |
31 val FIRST1: (int -> tactic) list -> tactic |
31 val FIRST1: (int -> tactic) list -> tactic |
32 val RANGE: (int -> tactic) list -> int -> tactic |
32 val RANGE: (int -> tactic) list -> int -> tactic |
33 val print_tac: Proof.context -> string -> tactic |
33 val print_tac: Proof.context -> string -> tactic |
34 val pause_tac: tactic |
|
35 val trace_REPEAT: bool Unsynchronized.ref |
|
36 val suppress_tracing: bool Unsynchronized.ref |
|
37 val tracify: bool Unsynchronized.ref -> tactic -> tactic |
|
38 val traced_tac: (thm -> (thm * thm Seq.seq) option) -> tactic |
|
39 val REPEAT_DETERM_N: int -> tactic -> tactic |
34 val REPEAT_DETERM_N: int -> tactic -> tactic |
40 val REPEAT_DETERM: tactic -> tactic |
35 val REPEAT_DETERM: tactic -> tactic |
41 val REPEAT: tactic -> tactic |
36 val REPEAT: tactic -> tactic |
42 val REPEAT_DETERM1: tactic -> tactic |
37 val REPEAT_DETERM1: tactic -> tactic |
43 val REPEAT1: tactic -> tactic |
38 val REPEAT1: tactic -> tactic |
177 (*Apply tactics on consecutive subgoals*) |
172 (*Apply tactics on consecutive subgoals*) |
178 fun RANGE [] _ = all_tac |
173 fun RANGE [] _ = all_tac |
179 | RANGE (tac :: tacs) i = RANGE tacs (i + 1) THEN tac i; |
174 | RANGE (tac :: tacs) i = RANGE tacs (i + 1) THEN tac i; |
180 |
175 |
181 |
176 |
182 (*** Tracing tactics ***) |
|
183 |
|
184 (*Print the current proof state and pass it on.*) |
177 (*Print the current proof state and pass it on.*) |
185 fun print_tac ctxt msg st = |
178 fun print_tac ctxt msg st = |
186 (tracing (msg ^ "\n" ^ Pretty.string_of (Pretty.chunks (Goal_Display.pretty_goals ctxt st))); |
179 (tracing (msg ^ "\n" ^ Pretty.string_of (Pretty.chunks (Goal_Display.pretty_goals ctxt st))); |
187 Seq.single st); |
180 Seq.single st); |
188 |
|
189 (*Pause until a line is typed -- if non-empty then fail. *) |
|
190 fun pause_tac st = |
|
191 (tracing "** Press RETURN to continue:"; |
|
192 if TextIO.inputLine TextIO.stdIn = SOME "\n" then Seq.single st |
|
193 else (tracing "Goodbye"; Seq.empty)); |
|
194 |
|
195 exception TRACE_EXIT of thm |
|
196 and TRACE_QUIT; |
|
197 |
|
198 (*Tracing flags*) |
|
199 val trace_REPEAT= Unsynchronized.ref false |
|
200 and suppress_tracing = Unsynchronized.ref false; |
|
201 |
|
202 (*Handle all tracing commands for current state and tactic *) |
|
203 fun exec_trace_command flag (tac, st) = |
|
204 (case TextIO.inputLine TextIO.stdIn of |
|
205 SOME "\n" => tac st |
|
206 | SOME "f\n" => Seq.empty |
|
207 | SOME "o\n" => (flag := false; tac st) |
|
208 | SOME "s\n" => (suppress_tracing := true; tac st) |
|
209 | SOME "x\n" => (tracing "Exiting now"; raise (TRACE_EXIT st)) |
|
210 | SOME "quit\n" => raise TRACE_QUIT |
|
211 | _ => |
|
212 (tracing |
|
213 "Type RETURN to continue or...\n\ |
|
214 \ f - to fail here\n\ |
|
215 \ o - to switch tracing off\n\ |
|
216 \ s - to suppress tracing until next entry to a tactical\n\ |
|
217 \ x - to exit at this point\n\ |
|
218 \ quit - to abort this tracing run\n\ |
|
219 \** Well? "; exec_trace_command flag (tac, st))); |
|
220 |
|
221 |
|
222 (*Extract from a tactic, a thm->thm seq function that handles tracing*) |
|
223 fun tracify flag tac st = |
|
224 if !flag andalso not (!suppress_tracing) then |
|
225 (tracing (Pretty.string_of (Pretty.chunks |
|
226 (Goal_Display.pretty_goals (Syntax.init_pretty_global (Thm.theory_of_thm st)) st @ |
|
227 [Pretty.str "** Press RETURN to continue:"]))); |
|
228 exec_trace_command flag (tac, st)) |
|
229 else tac st; |
|
230 |
|
231 (*Create a tactic whose outcome is given by seqf, handling TRACE_EXIT*) |
|
232 fun traced_tac seqf st = |
|
233 (suppress_tracing := false; |
|
234 Seq.make (fn () => seqf st handle TRACE_EXIT st' => SOME (st', Seq.empty))); |
|
235 |
181 |
236 |
182 |
237 (*Deterministic REPEAT: only retains the first outcome; |
183 (*Deterministic REPEAT: only retains the first outcome; |
238 uses less space than REPEAT; tail recursive. |
184 uses less space than REPEAT; tail recursive. |
239 If non-negative, n bounds the number of repetitions.*) |
185 If non-negative, n bounds the number of repetitions.*) |
240 fun REPEAT_DETERM_N n tac = |
186 fun REPEAT_DETERM_N n tac = |
241 let |
187 let |
242 val tac = tracify trace_REPEAT tac; |
|
243 fun drep 0 st = SOME (st, Seq.empty) |
188 fun drep 0 st = SOME (st, Seq.empty) |
244 | drep n st = |
189 | drep n st = |
245 (case Seq.pull (tac st) of |
190 (case Seq.pull (tac st) of |
246 NONE => SOME(st, Seq.empty) |
191 NONE => SOME(st, Seq.empty) |
247 | SOME (st', _) => drep (n - 1) st'); |
192 | SOME (st', _) => drep (n - 1) st'); |
248 in traced_tac (drep n) end; |
193 in fn st => Seq.make (fn () => drep n st) end; |
249 |
194 |
250 (*Allows any number of repetitions*) |
195 (*Allows any number of repetitions*) |
251 val REPEAT_DETERM = REPEAT_DETERM_N ~1; |
196 val REPEAT_DETERM = REPEAT_DETERM_N ~1; |
252 |
197 |
253 (*General REPEAT: maintains a stack of alternatives; tail recursive*) |
198 (*General REPEAT: maintains a stack of alternatives; tail recursive*) |
254 fun REPEAT tac = |
199 fun REPEAT tac = |
255 let |
200 let |
256 val tac = tracify trace_REPEAT tac; |
|
257 fun rep qs st = |
201 fun rep qs st = |
258 (case Seq.pull (tac st) of |
202 (case Seq.pull (tac st) of |
259 NONE => SOME (st, Seq.make (fn () => repq qs)) |
203 NONE => SOME (st, Seq.make (fn () => repq qs)) |
260 | SOME (st', q) => rep (q :: qs) st') |
204 | SOME (st', q) => rep (q :: qs) st') |
261 and repq [] = NONE |
205 and repq [] = NONE |
262 | repq (q :: qs) = |
206 | repq (q :: qs) = |
263 (case Seq.pull q of |
207 (case Seq.pull q of |
264 NONE => repq qs |
208 NONE => repq qs |
265 | SOME (st, q) => rep (q :: qs) st); |
209 | SOME (st, q) => rep (q :: qs) st); |
266 in traced_tac (rep []) end; |
210 in fn st => Seq.make (fn () => rep [] st) end; |
267 |
211 |
268 (*Repeat 1 or more times*) |
212 (*Repeat 1 or more times*) |
269 fun REPEAT_DETERM1 tac = DETERM tac THEN REPEAT_DETERM tac; |
213 fun REPEAT_DETERM1 tac = DETERM tac THEN REPEAT_DETERM tac; |
270 fun REPEAT1 tac = tac THEN REPEAT tac; |
214 fun REPEAT1 tac = tac THEN REPEAT tac; |
271 |
215 |