src/Pure/tctical.ML
changeset 15531 08c8dad8e399
parent 15017 9ad392226da5
child 15570 8d8c70b41bab
equal deleted inserted replaced
15530:6f43714517ee 15531:08c8dad8e399
    92 (*The tactical ORELSE uses the first tactic that returns a nonempty sequence.
    92 (*The tactical ORELSE uses the first tactic that returns a nonempty sequence.
    93   Like in LCF, ORELSE commits to either tac1 or tac2 immediately.
    93   Like in LCF, ORELSE commits to either tac1 or tac2 immediately.
    94   Does not backtrack to tac2 if tac1 was initially chosen. *)
    94   Does not backtrack to tac2 if tac1 was initially chosen. *)
    95 fun (tac1 ORELSE tac2) st =
    95 fun (tac1 ORELSE tac2) st =
    96     case Seq.pull(tac1 st) of
    96     case Seq.pull(tac1 st) of
    97         None       => tac2 st
    97         NONE       => tac2 st
    98       | sequencecell => Seq.make(fn()=> sequencecell);
    98       | sequencecell => Seq.make(fn()=> sequencecell);
    99 
    99 
   100 
   100 
   101 (*The tactical APPEND combines the results of two tactics.
   101 (*The tactical APPEND combines the results of two tactics.
   102   Like ORELSE, but allows backtracking on both tac1 and tac2.
   102   Like ORELSE, but allows backtracking on both tac1 and tac2.
   114         tac1 ORELSE tac2 = tac1 THEN_ELSE (all_tac, tac2)
   114         tac1 ORELSE tac2 = tac1 THEN_ELSE (all_tac, tac2)
   115         tac1 THEN tac2   = tac1 THEN_ELSE (tac2, no_tac)
   115         tac1 THEN tac2   = tac1 THEN_ELSE (tac2, no_tac)
   116 *)
   116 *)
   117 fun (tac THEN_ELSE (tac1, tac2)) st =
   117 fun (tac THEN_ELSE (tac1, tac2)) st =
   118     case Seq.pull(tac st) of
   118     case Seq.pull(tac st) of
   119         None    => tac2 st              (*failed; try tactic 2*)
   119         NONE    => tac2 st              (*failed; try tactic 2*)
   120       | seqcell => Seq.flat       (*succeeded; use tactic 1*)
   120       | seqcell => Seq.flat       (*succeeded; use tactic 1*)
   121                     (Seq.map tac1 (Seq.make(fn()=> seqcell)));
   121                     (Seq.map tac1 (Seq.make(fn()=> seqcell)));
   122 
   122 
   123 
   123 
   124 (*Versions for combining tactic-valued functions, as in
   124 (*Versions for combining tactic-valued functions, as in
   150 
   150 
   151 local
   151 local
   152   (*This version of EVERY avoids backtracking over repeated states*)
   152   (*This version of EVERY avoids backtracking over repeated states*)
   153 
   153 
   154   fun EVY (trail, []) st =
   154   fun EVY (trail, []) st =
   155         Seq.make (fn()=> Some(st,
   155         Seq.make (fn()=> SOME(st,
   156                         Seq.make (fn()=> Seq.pull (evyBack trail))))
   156                         Seq.make (fn()=> Seq.pull (evyBack trail))))
   157     | EVY (trail, tac::tacs) st =
   157     | EVY (trail, tac::tacs) st =
   158           case Seq.pull(tac st) of
   158           case Seq.pull(tac st) of
   159               None    => evyBack trail              (*failed: backtrack*)
   159               NONE    => evyBack trail              (*failed: backtrack*)
   160             | Some(st',q) => EVY ((st',q,tacs)::trail, tacs) st'
   160             | SOME(st',q) => EVY ((st',q,tacs)::trail, tacs) st'
   161   and evyBack [] = Seq.empty (*no alternatives*)
   161   and evyBack [] = Seq.empty (*no alternatives*)
   162     | evyBack ((st',q,tacs)::trail) =
   162     | evyBack ((st',q,tacs)::trail) =
   163           case Seq.pull q of
   163           case Seq.pull q of
   164               None        => evyBack trail
   164               NONE        => evyBack trail
   165             | Some(st,q') => if eq_thm (st',st)
   165             | SOME(st,q') => if eq_thm (st',st)
   166                              then evyBack ((st',q',tacs)::trail)
   166                              then evyBack ((st',q',tacs)::trail)
   167                              else EVY ((st,q',tacs)::trail, tacs) st
   167                              else EVY ((st,q',tacs)::trail, tacs) st
   168 in
   168 in
   169 
   169 
   170 (* EVERY [tac1,...,tacn]   equals    tac1 THEN ... THEN tacn   *)
   170 (* EVERY [tac1,...,tacn]   equals    tac1 THEN ... THEN tacn   *)
   244 
   244 
   245 (*Create a tactic whose outcome is given by seqf, handling TRACE_EXIT*)
   245 (*Create a tactic whose outcome is given by seqf, handling TRACE_EXIT*)
   246 fun traced_tac seqf st =
   246 fun traced_tac seqf st =
   247     (suppress_tracing := false;
   247     (suppress_tracing := false;
   248      Seq.make (fn()=> seqf st
   248      Seq.make (fn()=> seqf st
   249                          handle TRACE_EXIT st' => Some(st', Seq.empty)));
   249                          handle TRACE_EXIT st' => SOME(st', Seq.empty)));
   250 
   250 
   251 
   251 
   252 (*Deterministic DO..UNTIL: only retains the first outcome; tail recursive.
   252 (*Deterministic DO..UNTIL: only retains the first outcome; tail recursive.
   253   Forces repitition until predicate on state is fulfilled.*)
   253   Forces repitition until predicate on state is fulfilled.*)
   254 fun DETERM_UNTIL p tac =
   254 fun DETERM_UNTIL p tac =
   255 let val tac = tracify trace_REPEAT tac
   255 let val tac = tracify trace_REPEAT tac
   256     fun drep st = if p st then Some (st, Seq.empty)
   256     fun drep st = if p st then SOME (st, Seq.empty)
   257                           else (case Seq.pull(tac st) of
   257                           else (case Seq.pull(tac st) of
   258                                   None        => None
   258                                   NONE        => NONE
   259                                 | Some(st',_) => drep st')
   259                                 | SOME(st',_) => drep st')
   260 in  traced_tac drep  end;
   260 in  traced_tac drep  end;
   261 
   261 
   262 (*Deterministic REPEAT: only retains the first outcome;
   262 (*Deterministic REPEAT: only retains the first outcome;
   263   uses less space than REPEAT; tail recursive.
   263   uses less space than REPEAT; tail recursive.
   264   If non-negative, n bounds the number of repetitions.*)
   264   If non-negative, n bounds the number of repetitions.*)
   265 fun REPEAT_DETERM_N n tac =
   265 fun REPEAT_DETERM_N n tac =
   266   let val tac = tracify trace_REPEAT tac
   266   let val tac = tracify trace_REPEAT tac
   267       fun drep 0 st = Some(st, Seq.empty)
   267       fun drep 0 st = SOME(st, Seq.empty)
   268         | drep n st =
   268         | drep n st =
   269            (case Seq.pull(tac st) of
   269            (case Seq.pull(tac st) of
   270                 None       => Some(st, Seq.empty)
   270                 NONE       => SOME(st, Seq.empty)
   271               | Some(st',_) => drep (n-1) st')
   271               | SOME(st',_) => drep (n-1) st')
   272   in  traced_tac (drep n)  end;
   272   in  traced_tac (drep n)  end;
   273 
   273 
   274 (*Allows any number of repetitions*)
   274 (*Allows any number of repetitions*)
   275 val REPEAT_DETERM = REPEAT_DETERM_N ~1;
   275 val REPEAT_DETERM = REPEAT_DETERM_N ~1;
   276 
   276 
   277 (*General REPEAT: maintains a stack of alternatives; tail recursive*)
   277 (*General REPEAT: maintains a stack of alternatives; tail recursive*)
   278 fun REPEAT tac =
   278 fun REPEAT tac =
   279   let val tac = tracify trace_REPEAT tac
   279   let val tac = tracify trace_REPEAT tac
   280       fun rep qs st =
   280       fun rep qs st =
   281         case Seq.pull(tac st) of
   281         case Seq.pull(tac st) of
   282             None       => Some(st, Seq.make(fn()=> repq qs))
   282             NONE       => SOME(st, Seq.make(fn()=> repq qs))
   283           | Some(st',q) => rep (q::qs) st'
   283           | SOME(st',q) => rep (q::qs) st'
   284       and repq [] = None
   284       and repq [] = NONE
   285         | repq(q::qs) = case Seq.pull q of
   285         | repq(q::qs) = case Seq.pull q of
   286             None       => repq qs
   286             NONE       => repq qs
   287           | Some(st,q) => rep (q::qs) st
   287           | SOME(st,q) => rep (q::qs) st
   288   in  traced_tac (rep [])  end;
   288   in  traced_tac (rep [])  end;
   289 
   289 
   290 (*Repeat 1 or more times*)
   290 (*Repeat 1 or more times*)
   291 fun REPEAT_DETERM1 tac = DETERM tac THEN REPEAT_DETERM tac;
   291 fun REPEAT_DETERM1 tac = DETERM tac THEN REPEAT_DETERM tac;
   292 fun REPEAT1 tac = tac THEN REPEAT tac;
   292 fun REPEAT1 tac = tac THEN REPEAT tac;