-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathBackTrack.sml
More file actions
76 lines (62 loc) · 2.54 KB
/
BackTrack.sml
File metadata and controls
76 lines (62 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
(* Celf
* Copyright (C) 2008 Anders Schack-Nielsen and Carsten Schürmann
*
* This file is part of Celf.
*
* Celf is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Celf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Celf. If not, see <http://www.gnu.org/licenses/>.
*)
structure BackTrack :> BACKTRACK =
struct
datatype trailPoint = Mark | Update of unit -> unit (*| Assign of Syntax.obj option ref*)
val nMarks = ref 0
val trail : trailPoint list ref = ref []
fun push tp = trail := tp :: (!trail)
fun pop () = hd (!trail) before trail := tl (!trail)
fun setMark () = (push Mark; nMarks := 1 + !nMarks)
fun mark () = !nMarks before setMark ()
fun rewind () = case pop () of
Mark => nMarks := !nMarks - 1
| Update undoF => (undoF (); rewind ())
(*| Assign r => (r := NONE; rewind ())*)
fun eraseMarks' 0 tacc t = trail := List.revAppend (tacc, t)
| eraseMarks' n tacc (Mark::t) = eraseMarks' (n-1) tacc t
| eraseMarks' n tacc (tp::t) = eraseMarks' n (tp::tacc) t
| eraseMarks' _ _ [] = raise Fail "Internal error: eraseMarks'"
fun eraseMarks n = (eraseMarks' (!nMarks - n) [] (!trail); nMarks := n)
(* trailAssign : obj option ref -> unit *)
(* trails the assignment of the ref cell for future backtracking *)
(*fun trailAssign r = push (Assign r)*)
(* trailUpdate : (unit -> unit) -> unit *)
(* trails a state update and saves the undo function for future backtracking *)
fun trailUpdate undoF = if !nMarks <> 0 then push (Update undoF) else ()
(* backtrackC : (('a -> exn) -> unit) -> 'a option *)
(* backtrackC f
* run "f commitExn", then backtrack updates done by f unless
* commitExn x has been raised in which case we erase the backtracking
* marks and return SOME x.
*)
fun backtrackC f =
let exception commitExn of 'a
val n = mark ()
in
(f commitExn; rewind (); NONE) handle commitExn x => (eraseMarks n; SOME x)
end
(* backtrack : (unit -> unit) -> unit *)
(* val backtrack f = let val NONE = backtrackC (fn _ => f ()) in () end *)
fun backtrack f =
( mark ()
(* ; if !nMarks mod 1000 = 0 then print ("["^Int.toString (!nMarks)^"]") else ()*)
; f ()
; rewind () )
end