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