Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 2013,2017-2018 Matthew Fluet. |
2 | * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh | |
3 | * Jagannathan, and Stephen Weeks. | |
4 | * Copyright (C) 1997-2000 NEC Research Institute. | |
5 | * | |
6 | * MLton is released under a BSD-style license. | |
7 | * See the file MLton-LICENSE for details. | |
8 | *) | |
9 | ||
10 | structure SeqIndex = | |
11 | struct | |
12 | open SeqIndex | |
13 | ||
14 | local | |
15 | structure S = | |
16 | Int_ChooseInt | |
17 | (type 'a t = 'a -> int | |
18 | val fInt8 = SeqIndex.sextdFromInt8 | |
19 | val fInt16 = SeqIndex.sextdFromInt16 | |
20 | val fInt32 = SeqIndex.sextdFromInt32 | |
21 | val fInt64 = SeqIndex.sextdFromInt64 | |
22 | val fIntInf = SeqIndex.sextdFromIntInf) | |
23 | in | |
24 | val fromIntUnsafe = S.f | |
25 | end | |
26 | local | |
27 | structure S = | |
28 | Int_ChooseInt | |
29 | (type 'a t = 'a -> int | |
30 | val fInt8 = SeqIndex.schckFromInt8 | |
31 | val fInt16 = SeqIndex.schckFromInt16 | |
32 | val fInt32 = SeqIndex.schckFromInt32 | |
33 | val fInt64 = SeqIndex.schckFromInt64 | |
34 | val fIntInf = SeqIndex.schckFromIntInf) | |
35 | in | |
36 | val fromInt = S.f | |
37 | end | |
38 | local | |
39 | structure S = | |
40 | Int_ChooseInt | |
41 | (type 'a t = int -> 'a | |
42 | val fInt8 = SeqIndex.sextdToInt8 | |
43 | val fInt16 = SeqIndex.sextdToInt16 | |
44 | val fInt32 = SeqIndex.sextdToInt32 | |
45 | val fInt64 = SeqIndex.sextdToInt64 | |
46 | val fIntInf = SeqIndex.sextdToIntInf) | |
47 | in | |
48 | val toIntUnsafe = S.f | |
49 | end | |
50 | local | |
51 | structure S = | |
52 | Int_ChooseInt | |
53 | (type 'a t = int -> 'a | |
54 | val fInt8 = SeqIndex.schckToInt8 | |
55 | val fInt16 = SeqIndex.schckToInt16 | |
56 | val fInt32 = SeqIndex.schckToInt32 | |
57 | val fInt64 = SeqIndex.schckToInt64 | |
58 | val fIntInf = SeqIndex.schckToIntInf) | |
59 | in | |
60 | val toInt = S.f | |
61 | end | |
62 | ||
63 | fun fromIntForLength n = | |
64 | if Primitive.Controls.safe | |
65 | then (fromInt n) handle Overflow => raise Size | |
66 | else fromIntUnsafe n | |
67 | end | |
68 | ||
69 | functor Sequence (S: PRIM_SEQUENCE): SEQUENCE = | |
70 | struct | |
71 | val op +? = SeqIndex.+? | |
72 | val op +! = SeqIndex.+! | |
73 | val op -? = SeqIndex.-? | |
74 | val op <= = SeqIndex.<= | |
75 | val op > = SeqIndex.> | |
76 | val op >= = SeqIndex.>= | |
77 | ||
78 | (* fun wrap1 f = fn (i) => f (SeqIndex.toIntUnsafe i) *) | |
79 | fun wrap2 f = fn (i, x) => f (SeqIndex.toIntUnsafe i, x) | |
80 | fun wrap3 f = fn (i, x, y) => f (SeqIndex.toIntUnsafe i, x, y) | |
81 | fun unwrap1 f = fn (i) => f (SeqIndex.fromIntUnsafe i) | |
82 | fun unwrap2 f = fn (i, x) => f (SeqIndex.fromIntUnsafe i, x) | |
83 | ||
84 | type 'a sequence = 'a S.sequence | |
85 | type 'a elt = 'a S.elt | |
86 | ||
87 | (* S.maxLen must be representable as an Int.int already *) | |
88 | val maxLen = SeqIndex.toInt S.maxLen | |
89 | ||
90 | fun length s = | |
91 | if Primitive.Controls.safe | |
92 | then (SeqIndex.toInt (S.length s)) | |
93 | handle Overflow => raise Fail "Sequence.length" | |
94 | else SeqIndex.toIntUnsafe (S.length s) | |
95 | ||
96 | fun alloc n = S.alloc (SeqIndex.fromIntForLength n) | |
97 | fun unsafeAlloc n = S.unsafeAlloc (SeqIndex.fromIntUnsafe n) | |
98 | ||
99 | fun create n = | |
100 | let | |
101 | val {done, sub, update} = S.create (SeqIndex.fromIntForLength n) | |
102 | in | |
103 | {done = done, | |
104 | sub = unwrap1 sub, | |
105 | update = unwrap2 update} | |
106 | end | |
107 | ||
108 | fun unfoldi (n, b, f) = S.unfoldi (SeqIndex.fromIntForLength n, b, wrap2 f) | |
109 | fun unfold (n, b, f) = S.unfold (SeqIndex.fromIntForLength n, b, f) | |
110 | fun unsafeUnfold (n, b, f) = S.unfold (SeqIndex.fromIntUnsafe n, b, f) | |
111 | ||
112 | fun seq0 () = #1 (unfold (0, (), fn _ => raise Fail "Sequence.seq0")) | |
113 | ||
114 | fun tabulate (n, f) = | |
115 | #1 (unfoldi (n, (), fn (i, ()) => (f i, ()))) | |
116 | ||
117 | fun new (n, x) = | |
118 | #1 (unfold (n, (), fn () => (x, ()))) | |
119 | fun unsafeNew (n, x) = | |
120 | #1 (unsafeUnfold (n, (), fn () => (x, ()))) | |
121 | ||
122 | fun fromList l = | |
123 | #1 (unfold (List.length l, l, fn l => | |
124 | case l of | |
125 | nil => raise Fail "Sequence.fromList" | |
126 | | h::t => (h, t))) | |
127 | ||
128 | structure Slice = | |
129 | struct | |
130 | type 'a sequence = 'a S.Slice.sequence | |
131 | type 'a elt = 'a S.Slice.elt | |
132 | type 'a slice = 'a S.Slice.slice | |
133 | ||
134 | fun length sl = | |
135 | if Primitive.Controls.safe | |
136 | then (SeqIndex.toInt (S.Slice.length sl)) | |
137 | handle Overflow => raise Fail "Sequence.Slice.length" | |
138 | else SeqIndex.toIntUnsafe (S.Slice.length sl) | |
139 | ||
140 | fun unsafeSub (sl, i) = | |
141 | S.Slice.unsafeSub (sl, SeqIndex.fromIntUnsafe i) | |
142 | fun sub (sl, i) = | |
143 | if Primitive.Controls.safe | |
144 | then let | |
145 | val i = | |
146 | (SeqIndex.fromInt i) | |
147 | handle Overflow => raise Subscript | |
148 | in | |
149 | S.Slice.sub (sl, i) | |
150 | end | |
151 | else unsafeSub (sl, i) | |
152 | ||
153 | fun unsafeUpdate (sl, i, x) = | |
154 | S.Slice.unsafeUpdate (sl, SeqIndex.fromIntUnsafe i, x) | |
155 | fun update (sl, i, x) = | |
156 | if Primitive.Controls.safe | |
157 | then let | |
158 | val i = | |
159 | (SeqIndex.fromInt i) | |
160 | handle Overflow => raise Subscript | |
161 | in | |
162 | S.Slice.update (sl, i, x) | |
163 | end | |
164 | else unsafeUpdate (sl, i, x) | |
165 | ||
166 | val uninitIsNop = S.Slice.uninitIsNop | |
167 | fun unsafeUninit (sl, i) = | |
168 | S.Slice.unsafeUninit (sl, SeqIndex.fromIntUnsafe i) | |
169 | fun uninit (sl, i) = | |
170 | if Primitive.Controls.safe | |
171 | then let | |
172 | val i = | |
173 | (SeqIndex.fromInt i) | |
174 | handle Overflow => raise Subscript | |
175 | in | |
176 | S.Slice.uninit (sl, i) | |
177 | end | |
178 | else unsafeUninit (sl, i) | |
179 | ||
180 | fun unsafeCopy {dst, di, src} = | |
181 | S.Slice.unsafeCopy | |
182 | {dst = dst, | |
183 | di = SeqIndex.fromIntUnsafe di, | |
184 | src = src} | |
185 | fun copy {dst, di, src} = | |
186 | (S.Slice.copy | |
187 | {dst = dst, | |
188 | di = SeqIndex.fromInt di, | |
189 | src = src}) | |
190 | handle Overflow => raise Subscript | |
191 | ||
192 | val full = S.Slice.full | |
193 | fun unsafeSubslice (sl, start, len) = | |
194 | S.Slice.unsafeSubslice | |
195 | (sl, SeqIndex.fromIntUnsafe start, | |
196 | Option.map SeqIndex.fromIntUnsafe len) | |
197 | fun unsafeSlice (seq, start, len) = | |
198 | unsafeSubslice (full seq, start, len) | |
199 | fun subslice (sl, start, len) = | |
200 | if Primitive.Controls.safe | |
201 | then (S.Slice.subslice (sl, | |
202 | SeqIndex.fromInt start, | |
203 | Option.map SeqIndex.fromInt len)) | |
204 | handle Overflow => raise Subscript | |
205 | else unsafeSubslice (sl, start, len) | |
206 | fun slice (seq: 'a sequence, start, len) = | |
207 | subslice (full seq, start, len) | |
208 | fun base sl = | |
209 | let | |
210 | val (seq, start, len) = S.Slice.base sl | |
211 | in | |
212 | if Primitive.Controls.safe | |
213 | then (seq, SeqIndex.toInt start, SeqIndex.toInt len) | |
214 | handle Overflow => raise Fail "Sequence.Slice.base" | |
215 | else (seq, | |
216 | SeqIndex.toIntUnsafe start, | |
217 | SeqIndex.toIntUnsafe len) | |
218 | end | |
219 | val isEmpty = S.Slice.isEmpty | |
220 | val getItem = S.Slice.getItem | |
221 | fun foldli f b sl = S.Slice.foldli (wrap3 f) b sl | |
222 | fun foldri f b sl = S.Slice.foldri (wrap3 f) b sl | |
223 | val foldl = S.Slice.foldl | |
224 | val foldr = S.Slice.foldr | |
225 | fun appi f sl = S.Slice.appi (wrap2 f) sl | |
226 | val app = S.Slice.app | |
227 | fun mapi f sl = S.Slice.mapi (wrap2 f) sl | |
228 | val map = S.Slice.map | |
229 | fun findi p sl = | |
230 | Option.map (wrap2 (fn z => z)) (S.Slice.findi (wrap2 p) sl) | |
231 | val find = S.Slice.find | |
232 | fun existsi p sl = S.Slice.existsi (wrap2 p) sl | |
233 | val exists = S.Slice.exists | |
234 | fun alli p sl = S.Slice.alli (wrap2 p) sl | |
235 | val all = S.Slice.all | |
236 | val collate = S.Slice.collate | |
237 | val sequence = S.Slice.sequence | |
238 | val append = S.Slice.append | |
239 | ||
240 | fun concatGen (xs: 'b list, toSlice: 'b -> 'a slice): 'a sequence = | |
241 | case xs of | |
242 | [] => seq0 () | |
243 | | [x] => sequence (toSlice x) | |
244 | | xs => | |
245 | let | |
246 | val add = | |
247 | if Primitive.Controls.safe | |
248 | then (fn (x, s) => | |
249 | (s +! S.Slice.length (toSlice x)) | |
250 | handle Overflow => raise Size) | |
251 | else (fn (x, s) => s +? S.Slice.length (toSlice x)) | |
252 | val n = List.foldl add 0 xs | |
253 | val a = Primitive.Array.alloc n | |
254 | fun loop (di, xs) = | |
255 | case xs of | |
256 | [] => S.unsafeFromArray a | |
257 | | x::xs => | |
258 | let val sl = toSlice x | |
259 | in | |
260 | S.Slice.unsafeCopy {dst = a, di = di, src = sl} | |
261 | ; loop (di +? S.Slice.length sl, xs) | |
262 | end | |
263 | in | |
264 | loop (0, xs) | |
265 | end | |
266 | fun concat (sls: 'a slice list): 'a sequence = | |
267 | concatGen (sls, fn sl => sl) | |
268 | fun concatWithGen (sep: 'a sequence) (xs: 'b list, toSlice: 'b -> 'a slice): 'a sequence = | |
269 | case xs of | |
270 | [] => seq0 () | |
271 | | [x] => sequence (toSlice x) | |
272 | | x::xs => | |
273 | let | |
274 | val sep = S.Slice.full sep | |
275 | val sepn = S.Slice.length sep | |
276 | val add = | |
277 | if Primitive.Controls.safe | |
278 | then (fn (x, s) => | |
279 | (s +! sepn +! S.Slice.length (toSlice x)) | |
280 | handle Overflow => raise Size) | |
281 | else (fn (x, s) => | |
282 | (s +? sepn +? S.Slice.length (toSlice x))) | |
283 | val n = List.foldl add (S.Slice.length (toSlice x)) xs | |
284 | val a = Primitive.Array.alloc n | |
285 | fun loop (di, xs) = | |
286 | case xs of | |
287 | [] => raise Fail "Sequence.Slice.concatWithGen" | |
288 | | [x] => | |
289 | let | |
290 | val sl = toSlice x | |
291 | val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sl} | |
292 | in | |
293 | S.unsafeFromArray a | |
294 | end | |
295 | | x::xs => | |
296 | let | |
297 | val sl = toSlice x | |
298 | val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sl} | |
299 | val di = di +? S.Slice.length sl | |
300 | val _ = S.Slice.unsafeCopy {dst = a, di = di, src = sep} | |
301 | val di = di +? sepn | |
302 | in | |
303 | loop (di, xs) | |
304 | end | |
305 | in | |
306 | loop (0, x::xs) | |
307 | end | |
308 | fun concatWith sep sls = concatWithGen sep (sls, fn sl => sl) | |
309 | fun triml k sl = | |
310 | if Primitive.Controls.safe andalso Int.< (k, 0) | |
311 | then raise Subscript | |
312 | else let | |
313 | val len = S.Slice.length sl | |
314 | val k = | |
315 | if Primitive.Controls.safe | |
316 | then SeqIndex.fromInt k | |
317 | else SeqIndex.fromIntUnsafe k | |
318 | in | |
319 | if SeqIndex.> (k, len) | |
320 | then S.Slice.unsafeSubslice (sl, len, SOME 0) | |
321 | else S.Slice.unsafeSubslice (sl, k, SOME (len -? k)) | |
322 | end handle Overflow => | |
323 | (* k is positive, so behavior is specified! *) | |
324 | S.Slice.unsafeSubslice (sl, S.Slice.length sl, SOME 0) | |
325 | fun trimr k sl = | |
326 | if Primitive.Controls.safe andalso Int.< (k, 0) | |
327 | then raise Subscript | |
328 | else let | |
329 | val len = S.Slice.length sl | |
330 | val k = | |
331 | if Primitive.Controls.safe | |
332 | then SeqIndex.fromInt k | |
333 | else SeqIndex.fromIntUnsafe k | |
334 | in | |
335 | if SeqIndex.> (k, len) | |
336 | then S.Slice.unsafeSubslice (sl, 0, SOME 0) | |
337 | else S.Slice.unsafeSubslice (sl, 0, SOME (len -? k)) | |
338 | end handle Overflow => | |
339 | (* k is positive, so behavior is specified! *) | |
340 | S.Slice.unsafeSubslice (sl, 0, SOME 0) | |
341 | fun isSubsequence (eq: 'a elt * 'a elt -> bool) | |
342 | (seq: 'a sequence) | |
343 | (sl: 'a slice) = | |
344 | let | |
345 | val n = S.length seq | |
346 | val n' = S.Slice.length sl | |
347 | in | |
348 | if n <= n' | |
349 | then let | |
350 | val n'' = n' -? n | |
351 | fun loop (i, j) = | |
352 | if i > n'' | |
353 | then false | |
354 | else if j >= n | |
355 | then true | |
356 | else if eq (S.unsafeSub (seq, j), | |
357 | S.Slice.unsafeSub (sl, i +? j)) | |
358 | then loop (i, j +? 1) | |
359 | else loop (i +? 1, 0) | |
360 | in | |
361 | loop (0, 0) | |
362 | end | |
363 | else false | |
364 | end | |
365 | fun isPrefix (eq: 'a elt * 'a elt -> bool) | |
366 | (seq: 'a sequence) | |
367 | (sl: 'a slice) = | |
368 | let | |
369 | val n = S.length seq | |
370 | val n' = S.Slice.length sl | |
371 | in | |
372 | if n <= n' | |
373 | then let | |
374 | fun loop (j) = | |
375 | if j >= n | |
376 | then true | |
377 | else if eq (S.unsafeSub (seq, j), | |
378 | S.Slice.unsafeSub (sl, j)) | |
379 | then loop (j +? 1) | |
380 | else false | |
381 | in | |
382 | loop (0) | |
383 | end | |
384 | else false | |
385 | end | |
386 | fun isSuffix (eq: 'a elt * 'a elt -> bool) | |
387 | (seq: 'a sequence) | |
388 | (sl: 'a slice) = | |
389 | let | |
390 | val n = S.length seq | |
391 | val n' = S.Slice.length sl | |
392 | in | |
393 | if n <= n' | |
394 | then let | |
395 | val n'' = n' -? n | |
396 | fun loop (j) = | |
397 | if j >= n | |
398 | then true | |
399 | else if eq (S.unsafeSub (seq, j), | |
400 | S.Slice.unsafeSub (sl, n'' +? j)) | |
401 | then loop (j +? 1) | |
402 | else false | |
403 | in | |
404 | loop (0) | |
405 | end | |
406 | else false | |
407 | end | |
408 | val splitl = S.Slice.splitl | |
409 | val splitr = S.Slice.splitr | |
410 | fun splitAt (sl, i) = | |
411 | if Primitive.Controls.safe | |
412 | then (S.Slice.splitAt (sl, SeqIndex.fromInt i)) | |
413 | handle Overflow => raise Subscript | |
414 | else S.Slice.splitAt (sl, SeqIndex.fromIntUnsafe i) | |
415 | val dropl = S.Slice.dropl | |
416 | val dropr = S.Slice.dropr | |
417 | val takel = S.Slice.takel | |
418 | val taker = S.Slice.taker | |
419 | val position = S.Slice.position | |
420 | fun translate f (sl: 'a slice) = | |
421 | concat (List.rev (foldl (fn (c, l) => (full (f c)) :: l) [] sl)) | |
422 | local | |
423 | fun make finish p sl = | |
424 | let | |
425 | val (seq, start, len) = S.Slice.base sl | |
426 | val max = start +? len | |
427 | fun loop (i, start, sls) = | |
428 | if i >= max | |
429 | then List.rev (finish (seq, start, i, sls)) | |
430 | else | |
431 | if p (S.unsafeSub (seq, i)) | |
432 | then loop (i +? 1, i +? 1, finish (seq, start, i, sls)) | |
433 | else loop (i +? 1, start, sls) | |
434 | in loop (start, start, []) | |
435 | end | |
436 | in | |
437 | fun tokensGen fromSlice p sl = | |
438 | make (fn (seq, start, stop, sls) => | |
439 | if start = stop | |
440 | then sls | |
441 | else | |
442 | (fromSlice | |
443 | (S.Slice.unsafeSlice | |
444 | (seq, start, SOME (stop -? start)))) | |
445 | :: sls) | |
446 | p sl | |
447 | fun fieldsGen fromSlice p sl = | |
448 | make (fn (seq, start, stop, sls) => | |
449 | (fromSlice | |
450 | (S.Slice.unsafeSlice | |
451 | (seq, start, SOME (stop -? start)))) | |
452 | :: sls) | |
453 | p sl | |
454 | end | |
455 | fun tokens p sl = tokensGen (fn sl => sl) p sl | |
456 | fun fields p sl = fieldsGen (fn sl => sl) p sl | |
457 | fun toList (sl: 'a slice) = foldr (fn (a,l) => a::l) [] sl | |
458 | end | |
459 | ||
460 | local | |
461 | fun make f seq = f (Slice.full seq) | |
462 | fun make2 f (seq1, seq2) = f (Slice.full seq1, Slice.full seq2) | |
463 | in | |
464 | fun sub (seq, i) = Slice.sub (Slice.full seq, i) | |
465 | fun unsafeSub (seq, i) = Slice.unsafeSub (Slice.full seq, i) | |
466 | fun update (seq, i, x) = Slice.update (Slice.full seq, i, x) | |
467 | fun unsafeUpdate (seq, i, x) = Slice.unsafeUpdate (Slice.full seq, i, x) | |
468 | fun uninitIsNop seq = Slice.uninitIsNop (Slice.full seq) | |
469 | fun uninit (seq, i) = Slice.uninit (Slice.full seq, i) | |
470 | fun unsafeUninit (seq, i) = Slice.unsafeUninit (Slice.full seq, i) | |
471 | fun copy {dst, di, src} = | |
472 | Slice.copy {dst = dst, di = di, src = Slice.full src} | |
473 | fun unsafeCopy {dst, di, src} = | |
474 | Slice.unsafeCopy {dst = dst, di = di, src = Slice.full src} | |
475 | fun append seqs = make2 Slice.append seqs | |
476 | fun concat seqs = Slice.concatGen (seqs, Slice.full) | |
477 | fun appi f = make (Slice.appi f) | |
478 | fun app f = make (Slice.app f) | |
479 | fun mapi f = make (Slice.mapi f) | |
480 | fun map f = make (Slice.map f) | |
481 | fun foldli f b = make (Slice.foldli f b) | |
482 | fun foldl f b = make (Slice.foldl f b) | |
483 | fun foldri f b = make (Slice.foldri f b) | |
484 | fun foldr f b = make (Slice.foldr f b) | |
485 | fun findi p = make (Slice.findi p) | |
486 | fun find p = make (Slice.find p) | |
487 | fun existsi p = make (Slice.existsi p) | |
488 | fun exists p = make (Slice.exists p) | |
489 | fun alli p = make (Slice.alli p) | |
490 | fun all p = make (Slice.all p) | |
491 | fun collate cmp = make2 (Slice.collate cmp) | |
492 | fun concatWith sep seqs = Slice.concatWithGen sep (seqs, Slice.full) | |
493 | fun isPrefix eq seq = make (Slice.isPrefix eq seq) | |
494 | fun isSubsequence eq seq = make (Slice.isSubsequence eq seq) | |
495 | fun isSuffix eq seq = make (Slice.isSuffix eq seq) | |
496 | fun translate f = make (Slice.translate f) | |
497 | fun tokens f seq = make (Slice.tokensGen Slice.sequence f) seq | |
498 | fun fields f seq = make (Slice.fieldsGen Slice.sequence f) seq | |
499 | fun duplicate seq = make Slice.sequence seq | |
500 | fun toList seq = make Slice.toList seq | |
501 | end | |
502 | end |