forked from standardml/cmlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ideque.sml
executable file
·166 lines (139 loc) · 3.99 KB
/
ideque.sml
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
structure IDeque :> IDEQUE =
struct
datatype 'a qbody =
Null (* not used in active deques *)
| End of 'a qptr (* front or back bookend *)
| Node of 'a * 'a qptr * 'a qptr
withtype 'a qptr = 'a qbody ref
(* Invariant:
A ideque has the form (f, b) where f is a cell before the first, and b is a cell after the last.
*)
type 'a ideque = 'a qbody * 'a qbody
type idequeNode = (unit -> unit) * (unit -> bool)
exception Orphan
fun next qb =
(case qb of
End ptr => ptr
| Node (_, _, ptr) => ptr
| Null => raise Orphan)
fun prev qb =
(case qb of
End ptr => ptr
| Node (_, ptr, _) => ptr
| Null => raise Orphan)
fun ideque () =
let
val fptr = ref Null
val f = End fptr
val b = End (ref f)
in
fptr := b;
(f, b)
end
fun isEmpty (f, b) =
(case !(next f) of
End _ => true
| _ => false)
fun reset (f, b) =
(
if isEmpty (f, b) then
()
else
(* disconnect from the previous elements so that a delete cannot reconnect them *)
(
prev (! (next f)) := Null;
next (! (prev b)) := Null
);
next f := b;
prev b := f
)
fun insertFront (f, b) x =
let
val curr = ! (next f)
val new = Node (x, ref f, ref curr)
in
next f := new;
prev curr := new
end
fun insertBack (f, b) x =
let
val curr = ! (prev b)
val new = Node (x, ref curr, ref b)
in
prev b := new;
next curr := new
end
exception Empty
fun front (f, b) =
(case !(next f) of
End _ => raise Empty
| Null => raise (Fail "invariant")
| Node (x, _, _) => x)
fun back (f, b) =
(case !(prev b) of
End _ => raise Empty
| Null => raise (Fail "invariant")
| Node (x, _, _) => x)
fun removeFront (f, b) =
(case !(next f) of
End _ => raise Empty
| Null => raise (Fail "invariant")
| Node (x, bwd, fwd) =>
(
next f := !fwd;
prev (!fwd) := f;
bwd := Null;
fwd := Null;
x
))
fun removeBack (f, b) =
(case !(prev b) of
End _ => raise Empty
| Null => raise (Fail "invariant")
| Node (x, bwd, fwd) =>
(
prev b := !bwd;
next (!bwd) := b;
bwd := Null;
fwd := Null;
x
))
fun doDelete bwd fwd () =
(
next (!bwd) := !fwd;
prev (!fwd) := !bwd;
bwd := Null;
fwd := Null
)
fun doOrphan bwd fwd () =
(case !bwd of
Null => true
| _ => (case !fwd of
Null => true
| _ => false))
fun insertFrontNode (f, b) x =
let
val curr = ! (next f)
val bwd = ref f
val fwd = ref curr
val new = Node (x, bwd, fwd)
in
next f := new;
prev curr := new;
(doDelete bwd fwd, doOrphan bwd fwd)
end
fun insertBackNode (f, b) x =
let
val curr = ! (prev b)
val bwd = ref curr
val fwd = ref b
val new = Node (x, bwd, fwd)
in
prev b := new;
next curr := new;
(doDelete bwd fwd, doOrphan bwd fwd)
end
fun delete (f, _) = f ()
fun orphan (_, f) = f ()
val dummy = ((fn () => raise Orphan), (fn () => true))
end