src/Pure/tactical.ML
changeset 62916 621afc4607ec
parent 61841 4d3527b94f2a
child 76051 854e9223767f
equal deleted inserted replaced
62915:0f794993485a 62916:621afc4607ec
    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