adamc@915
|
1 datatype dlist'' t =
|
adamc@915
|
2 Nil
|
adamc@915
|
3 | Cons of t * source (dlist'' t)
|
adamc@915
|
4
|
adamc@915
|
5 datatype dlist' t =
|
adamc@915
|
6 Empty
|
adamc@915
|
7 | Nonempty of { Head : dlist'' t, Tail : source (source (dlist'' t)) }
|
adamc@915
|
8
|
adamc@951
|
9 con dlist t = source (dlist' t)
|
adamc@915
|
10
|
adamc@915
|
11 type position = transaction unit
|
adamc@915
|
12
|
adamc@915
|
13 fun headPos [t] (dl : dlist t) =
|
adamc@951
|
14 dl' <- get dl;
|
adamc@915
|
15 case dl' of
|
adamc@915
|
16 Nonempty { Head = Cons (_, tl), Tail = tl' } =>
|
adamc@915
|
17 cur <- get tl;
|
adamc@951
|
18 set dl (case cur of
|
adamc@951
|
19 Nil => Empty
|
adamc@951
|
20 | _ => Nonempty {Head = cur, Tail = tl'})
|
adamc@915
|
21 | _ => return ()
|
adamc@915
|
22
|
adamc@915
|
23 fun tailPos [t] (cur : source (dlist'' t)) new tail =
|
adamc@915
|
24 new' <- get new;
|
adamc@915
|
25 set cur new';
|
adamc@915
|
26
|
adamc@915
|
27 case new' of
|
adamc@915
|
28 Nil => set tail cur
|
adamc@915
|
29 | _ => return ()
|
adamc@915
|
30
|
adamc@951
|
31 val create [t] = source Empty
|
adamc@915
|
32
|
adamc@951
|
33 fun clear [t] (s : dlist t) = set s Empty
|
adamc@915
|
34
|
adamc@915
|
35 fun append [t] dl v =
|
adamc@951
|
36 dl' <- get dl;
|
adamc@915
|
37 case dl' of
|
adamc@915
|
38 Empty =>
|
adamc@915
|
39 tl <- source Nil;
|
adamc@915
|
40 tl' <- source tl;
|
adamc@951
|
41 set dl (Nonempty {Head = Cons (v, tl), Tail = tl'});
|
adamc@915
|
42 return (headPos dl)
|
adamc@915
|
43
|
adamc@915
|
44 | Nonempty {Tail = tl, ...} =>
|
adamc@915
|
45 cur <- get tl;
|
adamc@915
|
46 new <- source Nil;
|
adamc@915
|
47 set cur (Cons (v, new));
|
adamc@915
|
48 set tl new;
|
adamc@915
|
49 return (tailPos cur new tl)
|
adamc@915
|
50
|
adamc@952
|
51 fun renderDyn [ctx] [ctx ~ body] [t] (f : t -> position -> xml (ctx ++ body) [] []) filter dl = <xml>
|
adamc@951
|
52 <dyn signal={dl' <- signal dl;
|
adamc@915
|
53 return (case dl' of
|
adamc@915
|
54 Empty => <xml/>
|
adamc@915
|
55 | Nonempty {Head = hd, Tail = tlTop} =>
|
adamc@915
|
56 let
|
adamc@915
|
57 fun render' prev dl'' =
|
adamc@915
|
58 case dl'' of
|
adamc@915
|
59 Nil => <xml/>
|
adamc@915
|
60 | Cons (v, tl) =>
|
adamc@915
|
61 let
|
adamc@915
|
62 val pos = case prev of
|
adamc@915
|
63 None => headPos dl
|
adamc@915
|
64 | Some prev => tailPos prev tl tlTop
|
adamc@915
|
65 in
|
adamc@951
|
66 <xml><dyn signal={b <- filter v;
|
adamc@944
|
67 return (if b then
|
adamc@944
|
68 f v pos
|
adamc@944
|
69 else
|
adamc@944
|
70 <xml/>)}/>
|
adamc@944
|
71 <dyn signal={tl' <- signal tl;
|
adamc@944
|
72 return (render' (Some tl) tl')}/></xml>
|
adamc@915
|
73 end
|
adamc@915
|
74 in
|
adamc@915
|
75 render' None hd
|
adamc@915
|
76 end)}/>
|
adamc@915
|
77 </xml>
|
adamc@915
|
78
|
adamc@952
|
79 fun renderFlat [ctx] [ctx ~ body] [t] (f : t -> position -> xml (ctx ++ body) [] []) filter ls =
|
adamc@952
|
80 List.mapX (fn p => f p.1 p.2) ls
|
adamc@952
|
81
|
adamc@953
|
82 val split [t] =
|
adamc@953
|
83 let
|
adamc@953
|
84 fun split' acc (ls : list t) =
|
adamc@953
|
85 case ls of
|
adamc@953
|
86 [] => acc
|
adamc@953
|
87 | x1 :: [] => (x1 :: acc.1, acc.2)
|
adamc@953
|
88 | x1 :: x2 :: ls => split' (x1 :: acc.1, x2 :: acc.2) ls
|
adamc@953
|
89 in
|
adamc@953
|
90 split' ([], [])
|
adamc@953
|
91 end
|
adamc@953
|
92
|
adamc@953
|
93 fun merge [t] (cmp : t -> t -> signal bool) =
|
adamc@953
|
94 let
|
adamc@953
|
95 fun merge' acc (ls1 : list t) (ls2 : list t) =
|
adamc@953
|
96 case (ls1, ls2) of
|
adamc@953
|
97 ([], _) => return (List.revAppend acc ls2)
|
adamc@953
|
98 | (_, []) => return (List.revAppend acc ls1)
|
adamc@953
|
99 | (x1 :: ls1', x2 :: ls2') =>
|
adamc@953
|
100 b <- cmp x1 x2;
|
adamc@953
|
101 if b then
|
adamc@953
|
102 merge' (x1 :: acc) ls1' ls2
|
adamc@953
|
103 else
|
adamc@953
|
104 merge' (x2 :: acc) ls1 ls2'
|
adamc@953
|
105 in
|
adamc@953
|
106 merge' []
|
adamc@953
|
107 end
|
adamc@953
|
108
|
adamc@953
|
109 fun sort [t] (cmp : t -> t -> signal bool) =
|
adamc@953
|
110 let
|
adamc@953
|
111 fun sort' (ls : list t) =
|
adamc@953
|
112 case ls of
|
adamc@953
|
113 [] => return ls
|
adamc@953
|
114 | _ :: [] => return ls
|
adamc@953
|
115 | _ =>
|
adamc@953
|
116 let
|
adamc@953
|
117 val (ls1, ls2) = split ls
|
adamc@953
|
118 in
|
adamc@953
|
119 ls1' <- sort' ls1;
|
adamc@953
|
120 ls2' <- sort' ls2;
|
adamc@953
|
121 merge cmp ls1' ls2'
|
adamc@953
|
122 end
|
adamc@953
|
123 in
|
adamc@953
|
124 sort'
|
adamc@953
|
125 end
|
adamc@953
|
126
|
adamc@953
|
127 fun render [ctx] [ctx ~ body] [t] f (r : {Filter : t -> signal bool,
|
adamc@953
|
128 Sort : signal (option (t -> t -> signal bool))}) dl = <xml>
|
adamc@953
|
129 <dyn signal={cmp <- r.Sort;
|
adamc@953
|
130 case cmp of
|
adamc@952
|
131 None => return (renderDyn f r.Filter dl)
|
adamc@953
|
132 | Some cmp =>
|
adamc@952
|
133 dl' <- signal dl;
|
adamc@952
|
134 elems <- (case dl' of
|
adamc@952
|
135 Empty => return []
|
adamc@952
|
136 | Nonempty {Head = hd, Tail = tlTop} =>
|
adamc@952
|
137 let
|
adamc@952
|
138 fun listOut prev dl'' acc =
|
adamc@952
|
139 case dl'' of
|
adamc@952
|
140 Nil => return acc
|
adamc@952
|
141 | Cons (v, tl) =>
|
adamc@952
|
142 let
|
adamc@952
|
143 val pos = case prev of
|
adamc@952
|
144 None => headPos dl
|
adamc@952
|
145 | Some prev => tailPos prev tl tlTop
|
adamc@952
|
146 in
|
adamc@952
|
147 tl' <- signal tl;
|
adamc@952
|
148 listOut (Some tl) tl' ((v, pos) :: acc)
|
adamc@952
|
149 end
|
adamc@952
|
150 in
|
adamc@952
|
151 listOut None hd []
|
adamc@952
|
152 end);
|
adamc@953
|
153 elems <- sort (fn v1 v2 => cmp v1.1 v2.1) elems;
|
adamc@952
|
154 return (renderFlat f r.Filter elems)}/>
|
adamc@952
|
155 </xml>
|
adamc@952
|
156
|
adamc@952
|
157
|
adamc@952
|
158
|
adamc@915
|
159 fun delete pos = pos
|
adamc@915
|
160
|
adamc@915
|
161 fun elements' [t] (dl'' : dlist'' t) =
|
adamc@915
|
162 case dl'' of
|
adamc@915
|
163 Nil => return []
|
adamc@915
|
164 | Cons (x, dl'') =>
|
adamc@915
|
165 dl'' <- signal dl'';
|
adamc@915
|
166 tl <- elements' dl'';
|
adamc@915
|
167 return (x :: tl)
|
adamc@915
|
168
|
adamc@915
|
169 fun elements [t] (dl : dlist t) =
|
adamc@951
|
170 dl' <- signal dl;
|
adamc@915
|
171 case dl' of
|
adamc@915
|
172 Empty => return []
|
adamc@915
|
173 | Nonempty {Head = hd, ...} => elements' hd
|
adamc@937
|
174
|
adamc@937
|
175 fun foldl [t] [acc] (f : t -> acc -> signal acc) =
|
adamc@937
|
176 let
|
adamc@937
|
177 fun foldl'' (i : acc) (dl : dlist'' t) : signal acc =
|
adamc@937
|
178 case dl of
|
adamc@937
|
179 Nil => return i
|
adamc@937
|
180 | Cons (v, dl') =>
|
adamc@937
|
181 dl' <- signal dl';
|
adamc@937
|
182 i' <- f v i;
|
adamc@937
|
183 foldl'' i' dl'
|
adamc@937
|
184
|
adamc@937
|
185 fun foldl' (i : acc) (dl : dlist t) : signal acc =
|
adamc@951
|
186 dl <- signal dl;
|
adamc@937
|
187 case dl of
|
adamc@937
|
188 Empty => return i
|
adamc@937
|
189 | Nonempty {Head = dl, ...} => foldl'' i dl
|
adamc@937
|
190 in
|
adamc@937
|
191 foldl'
|
adamc@937
|
192 end
|