Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / basis-library / arrays-and-vectors / sequence.fun
CommitLineData
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
10structure 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
69functor 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