2-- Module : Streamly.Internal.Data.Stream.StreamD.Nesting
3-- Copyright : (c) 2018 Composewell Technologies
4-- (c) Roman Leshchinskiy 2008-2010
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
10-- This module contains transformations involving multiple streams, unfolds or
11-- folds. There are two types of transformations generational or eliminational.
12-- Generational transformations are like the "Generate" module but they
13-- generate a stream by combining streams instead of elements. Eliminational
14-- transformations are like the "Eliminate" module but they transform a stream
15-- by eliminating parts of the stream instead of eliminating the whole stream.
17-- These combinators involve transformation, generation, elimination so can be
18-- classified under any of those.
20-- Ultimately these operations should be supported by Unfolds, Pipes and Folds,
21-- and this module may become redundant.
23-- The zipWithM combinator in this module has been adapted from the vector
24-- package (c) Roman Leshchinskiy.
26module Streamly.Internal.Data.Stream.StreamD.Nesting
29 -- | Combining streams to generate streams.
31 -- ** Combine Two Streams
32 -- | Functions ending in the shape:
34 -- @t m a -> t m a -> t m a@.
37 -- | Append a stream after another. A special case of concatMap or
43 -- | Interleave elements from two streams alternately. A special case of
44 -- unfoldManyInterleave.
52 -- | Execute streams alternately irrespective of whether they generate
53 -- elements or not. Note 'interleave' would execute a stream until it
54 -- yields an element. A special case of unfoldManyRoundRobin.
55 , roundRobin -- interleaveFair?/ParallelFair
58 -- | Zip corresponding elements of two streams.
63 -- | Interleave elements from two streams based on a condition.
67 -- ** Combine N Streams
68 -- | Functions generally ending in these shapes:
71 -- concat: f (t m a) -> t m a
72 -- concatMap: (a -> t m b) -> t m a -> t m b
73 -- unfoldMany: Unfold m a b -> t m a -> t m b
77 -- | Generate streams by mapping a stream generator on each element of an
78 -- input stream, append the resulting streams and flatten.
83 -- | Generate streams by using an unfold on each element of an input
84 -- stream, append the resulting streams and flatten. A special case of
87 , ConcatUnfoldInterleaveState (..)
88 , unfoldManyInterleave
89 , unfoldManyRoundRobin
92 -- | Like unfoldMany but intersperses an effect between the streams. A
93 -- special case of gintercalate.
98 -- | Like unfoldMany but intersperses streams from another source between
99 -- the streams from the first source.
104 -- | Folding and Parsing chunks of streams to eliminate nested streams.
105 -- Functions generally ending in these shapes:
108 -- f (Fold m a b) -> t m a -> t m b
109 -- f (Parser m a b) -> t m a -> t m b
113 -- | Apply folds on a stream.
118 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
119 -- unfoldMany. concatMap generates a stream from single values in a
120 -- stream and flattens, parseMany does the opposite of flattening by
121 -- splitting the stream and then folds each such split to single value in
122 -- the output stream.
127 -- | Group segments of a stream and fold. Special case of parsing.
134 -- | A special case of parsing.
139 -- * Transform (Nested Containers)
140 -- | Opposite to compact in ArrayStream
148import Control.Exception (assert)
149import Control.Monad.Catch (MonadThrow, throwM)
150import Control.Monad.IO.Class (MonadIO(..))
151import Data.Bits (shiftR, shiftL, (.|.), (.&.))
152#if __GLASGOW_HASKELL__ >= 801
153import Data.Functor.Identity ( Identity )
155import Data.Word (Word32)
156import Foreign.Storable (Storable(..))
157import Fusion.Plugin.Types (Fuse(..))
158import GHC.Types (SPEC(..))
160import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
161import Streamly.Internal.Data.Fold.Type (Fold(..))
162import Streamly.Internal.Data.Parser (ParseError(..))
163import Streamly.Internal.Data.SVar.Type (adaptState)
164import Streamly.Internal.Data.Unfold.Type (Unfold(..))
166import qualified Streamly.Internal.Data.Array.Foreign.Type as A
167import qualified Streamly.Internal.Data.Fold.Type as FL
168import qualified Streamly.Internal.Data.Parser as PR
169import qualified Streamly.Internal.Data.Parser.ParserD as PRD
170import qualified Streamly.Internal.Ring.Foreign as RB
172import Streamly.Internal.Data.Stream.StreamD.Type
174import Prelude hiding (concatMap, mapM, zipWith)
176------------------------------------------------------------------------------
178------------------------------------------------------------------------------
180data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
182-- Note that this could be much faster compared to the CPS stream. However, as
183-- the number of streams being composed increases this may become expensive.
184-- Need to see where the breaking point is between the two.
186{-# INLINE_NORMAL append #-}
187append :: Monad m => Stream m a -> Stream m a -> Stream m a
188append (Stream step1 state1) (Stream step2 state2) =
189 Stream step (AppendFirst state1)
193 {-# INLINE_LATE step #-}
194 step gst (AppendFirst st) = do
197 Yield a s -> Yield a (AppendFirst s)
198 Skip s -> Skip (AppendFirst s)
199 Stop -> Skip (AppendSecond state2)
201 step gst (AppendSecond st) = do
204 Yield a s -> Yield a (AppendSecond s)
205 Skip s -> Skip (AppendSecond s)
208------------------------------------------------------------------------------
210------------------------------------------------------------------------------
212data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
213 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
215{-# INLINE_NORMAL interleave #-}
216interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
217interleave (Stream step1 state1) (Stream step2 state2) =
218 Stream step (InterleaveFirst state1 state2)
222 {-# INLINE_LATE step #-}
223 step gst (InterleaveFirst st1 st2) = do
226 Yield a s -> Yield a (InterleaveSecond s st2)
227 Skip s -> Skip (InterleaveFirst s st2)
228 Stop -> Skip (InterleaveSecondOnly st2)
230 step gst (InterleaveSecond st1 st2) = do
233 Yield a s -> Yield a (InterleaveFirst st1 s)
234 Skip s -> Skip (InterleaveSecond st1 s)
235 Stop -> Skip (InterleaveFirstOnly st1)
237 step gst (InterleaveFirstOnly st1) = do
240 Yield a s -> Yield a (InterleaveFirstOnly s)
241 Skip s -> Skip (InterleaveFirstOnly s)
244 step gst (InterleaveSecondOnly st2) = do
247 Yield a s -> Yield a (InterleaveSecondOnly s)
248 Skip s -> Skip (InterleaveSecondOnly s)
251{-# INLINE_NORMAL interleaveMin #-}
252interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
253interleaveMin (Stream step1 state1) (Stream step2 state2) =
254 Stream step (InterleaveFirst state1 state2)
258 {-# INLINE_LATE step #-}
259 step gst (InterleaveFirst st1 st2) = do
262 Yield a s -> Yield a (InterleaveSecond s st2)
263 Skip s -> Skip (InterleaveFirst s st2)
266 step gst (InterleaveSecond st1 st2) = do
269 Yield a s -> Yield a (InterleaveFirst st1 s)
270 Skip s -> Skip (InterleaveSecond st1 s)
273 step _ (InterleaveFirstOnly _) = undefined
274 step _ (InterleaveSecondOnly _) = undefined
276{-# INLINE_NORMAL interleaveSuffix #-}
277interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
278interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
279 Stream step (InterleaveFirst state1 state2)
283 {-# INLINE_LATE step #-}
284 step gst (InterleaveFirst st1 st2) = do
287 Yield a s -> Yield a (InterleaveSecond s st2)
288 Skip s -> Skip (InterleaveFirst s st2)
291 step gst (InterleaveSecond st1 st2) = do
294 Yield a s -> Yield a (InterleaveFirst st1 s)
295 Skip s -> Skip (InterleaveSecond st1 s)
296 Stop -> Skip (InterleaveFirstOnly st1)
298 step gst (InterleaveFirstOnly st1) = do
301 Yield a s -> Yield a (InterleaveFirstOnly s)
302 Skip s -> Skip (InterleaveFirstOnly s)
305 step _ (InterleaveSecondOnly _) = undefined
307data InterleaveInfixState s1 s2 a
308 = InterleaveInfixFirst s1 s2
309 | InterleaveInfixSecondBuf s1 s2
310 | InterleaveInfixSecondYield s1 s2 a
311 | InterleaveInfixFirstYield s1 s2 a
312 | InterleaveInfixFirstOnly s1
314{-# INLINE_NORMAL interleaveInfix #-}
315interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
316interleaveInfix (Stream step1 state1) (Stream step2 state2) =
317 Stream step (InterleaveInfixFirst state1 state2)
321 {-# INLINE_LATE step #-}
322 step gst (InterleaveInfixFirst st1 st2) = do
325 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
326 Skip s -> Skip (InterleaveInfixFirst s st2)
329 step gst (InterleaveInfixSecondBuf st1 st2) = do
332 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
333 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
334 Stop -> Skip (InterleaveInfixFirstOnly st1)
336 step gst (InterleaveInfixSecondYield st1 st2 x) = do
339 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
340 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
343 step _ (InterleaveInfixFirstYield st1 st2 x) = do
344 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
346 step gst (InterleaveInfixFirstOnly st1) = do
349 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
350 Skip s -> Skip (InterleaveInfixFirstOnly s)
353------------------------------------------------------------------------------
355------------------------------------------------------------------------------
357{-# INLINE_NORMAL roundRobin #-}
358roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
359roundRobin (Stream step1 state1) (Stream step2 state2) =
360 Stream step (InterleaveFirst state1 state2)
364 {-# INLINE_LATE step #-}
365 step gst (InterleaveFirst st1 st2) = do
368 Yield a s -> Yield a (InterleaveSecond s st2)
369 Skip s -> Skip (InterleaveSecond s st2)
370 Stop -> Skip (InterleaveSecondOnly st2)
372 step gst (InterleaveSecond st1 st2) = do
375 Yield a s -> Yield a (InterleaveFirst st1 s)
376 Skip s -> Skip (InterleaveFirst st1 s)
377 Stop -> Skip (InterleaveFirstOnly st1)
379 step gst (InterleaveSecondOnly st2) = do
382 Yield a s -> Yield a (InterleaveSecondOnly s)
383 Skip s -> Skip (InterleaveSecondOnly s)
386 step gst (InterleaveFirstOnly st1) = do
389 Yield a s -> Yield a (InterleaveFirstOnly s)
390 Skip s -> Skip (InterleaveFirstOnly s)
393------------------------------------------------------------------------------
395------------------------------------------------------------------------------
397{-# INLINE_NORMAL zipWithM #-}
399 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
400zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
402 {-# INLINE_LATE step #-}
403 step gst (sa, sb, Nothing) = do
404 r <- stepa (adaptState gst) sa
407 Yield x sa' -> Skip (sa', sb, Just x)
408 Skip sa' -> Skip (sa', sb, Nothing)
411 step gst (sa, sb, Just x) = do
412 r <- stepb (adaptState gst) sb
416 return $ Yield z (sa, sb', Nothing)
417 Skip sb' -> return $ Skip (sa, sb', Just x)
420#if __GLASGOW_HASKELL__ >= 801
421{-# RULES "zipWithM xs xs"
422 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
425{-# INLINE zipWith #-}
426zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
427zipWith f = zipWithM (\a b -> return (f a b))
429------------------------------------------------------------------------------
431------------------------------------------------------------------------------
433{-# INLINE_NORMAL mergeByM #-}
436 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
437mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
438 Stream step (Just ta, Just tb, Nothing, Nothing)
440 {-# INLINE_LATE step #-}
442 -- one of the values is missing, and the corresponding stream is running
443 step gst (Just sa, sb, Nothing, b) = do
446 Yield a sa' -> Skip (Just sa', sb, Just a, b)
447 Skip sa' -> Skip (Just sa', sb, Nothing, b)
448 Stop -> Skip (Nothing, sb, Nothing, b)
450 step gst (sa, Just sb, a, Nothing) = do
453 Yield b sb' -> Skip (sa, Just sb', a, Just b)
454 Skip sb' -> Skip (sa, Just sb', a, Nothing)
455 Stop -> Skip (sa, Nothing, a, Nothing)
457 -- both the values are available
458 step _ (sa, sb, Just a, Just b) = do
461 GT -> Yield b (sa, sb, Just a, Nothing)
462 _ -> Yield a (sa, sb, Nothing, Just b)
464 -- one of the values is missing, corresponding stream is done
465 step _ (Nothing, sb, Nothing, Just b) =
466 return $ Yield b (Nothing, sb, Nothing, Nothing)
468 step _ (sa, Nothing, Just a, Nothing) =
469 return $ Yield a (sa, Nothing, Nothing, Nothing)
471 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
473{-# INLINE mergeBy #-}
476 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
477mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
479------------------------------------------------------------------------------
480-- Combine N Streams - unfoldMany
481------------------------------------------------------------------------------
483data ConcatUnfoldInterleaveState o i =
484 ConcatUnfoldInterleaveOuter o [i]
485 | ConcatUnfoldInterleaveInner o [i]
486 | ConcatUnfoldInterleaveInnerL [i] [i]
487 | ConcatUnfoldInterleaveInnerR [i] [i]
489-- XXX use arrays to store state instead of lists.
490-- XXX In general we can use different scheduling strategies e.g. how to
491-- schedule the outer vs inner loop or assigning weights to different streams
492-- or outer and inner loops.
494-- After a yield, switch to the next stream. Do not switch streams on Skip.
495-- Yield from outer stream switches to the inner stream.
497-- There are two choices here, (1) exhaust the outer stream first and then
498-- start yielding from the inner streams, this is much simpler to implement,
499-- (2) yield at least one element from an inner stream before going back to
500-- outer stream and opening the next stream from it.
502-- Ideally, we need some scheduling bias to inner streams vs outer stream.
503-- Maybe we can configure the behavior.
505{-# INLINE_NORMAL unfoldManyInterleave #-}
506unfoldManyInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
507unfoldManyInterleave (Unfold istep inject) (Stream ostep ost) =
508 Stream step (ConcatUnfoldInterleaveOuter ost [])
510 {-# INLINE_LATE step #-}
511 step gst (ConcatUnfoldInterleaveOuter o ls) = do
512 r <- ostep (adaptState gst) o
516 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
517 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
518 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
520 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
521 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
524 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
525 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
526 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
528 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
529 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
530 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
532 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
535 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
536 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
537 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
539 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
540 step _ (ConcatUnfoldInterleaveInnerR ls []) =
541 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
543 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
546 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
547 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
548 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
550-- XXX In general we can use different scheduling strategies e.g. how to
551-- schedule the outer vs inner loop or assigning weights to different streams
552-- or outer and inner loops.
554-- This could be inefficient if the tasks are too small.
556-- Compared to unfoldManyInterleave this one switches streams on Skips.
558{-# INLINE_NORMAL unfoldManyRoundRobin #-}
559unfoldManyRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
560unfoldManyRoundRobin (Unfold istep inject) (Stream ostep ost) =
561 Stream step (ConcatUnfoldInterleaveOuter ost [])
563 {-# INLINE_LATE step #-}
564 step gst (ConcatUnfoldInterleaveOuter o ls) = do
565 r <- ostep (adaptState gst) o
569 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
570 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
571 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
573 step _ (ConcatUnfoldInterleaveInner o []) =
574 return $ Skip (ConcatUnfoldInterleaveOuter o [])
576 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
579 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
580 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
581 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
583 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
584 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
585 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
587 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
590 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
591 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
592 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
594 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
595 step _ (ConcatUnfoldInterleaveInnerR ls []) =
596 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
598 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
601 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
602 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
603 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
605------------------------------------------------------------------------------
606-- Combine N Streams - interpose
607------------------------------------------------------------------------------
609{-# ANN type InterposeSuffixState Fuse #-}
610data InterposeSuffixState s1 i1 =
611 InterposeSuffixFirst s1
612 -- | InterposeSuffixFirstYield s1 i1
613 | InterposeSuffixFirstInner s1 i1
614 | InterposeSuffixSecond s1
616-- Note that if an unfolded layer turns out to be nil we still emit the
617-- separator effect. An alternate behavior could be to emit the separator
618-- effect only if at least one element has been yielded by the unfolding.
619-- However, that becomes a bit complicated, so we have chosen the former
621{-# INLINE_NORMAL interposeSuffix #-}
624 => m c -> Unfold m b c -> Stream m b -> Stream m c
627 (Unfold istep1 inject1) (Stream step1 state1) =
628 Stream step (InterposeSuffixFirst state1)
632 {-# INLINE_LATE step #-}
633 step gst (InterposeSuffixFirst s1) = do
634 r <- step1 (adaptState gst) s1
638 i `seq` return (Skip (InterposeSuffixFirstInner s i))
639 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
640 Skip s -> return $ Skip (InterposeSuffixFirst s)
644 step _ (InterposeSuffixFirstYield s1 i1) = do
647 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
648 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
649 Stop -> Skip (InterposeSuffixFirst s1)
652 step _ (InterposeSuffixFirstInner s1 i1) = do
655 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
656 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
657 Stop -> Skip (InterposeSuffixSecond s1)
659 step _ (InterposeSuffixSecond s1) = do
661 return $ Yield r (InterposeSuffixFirst s1)
663{-# ANN type InterposeState Fuse #-}
664data InterposeState s1 i1 a =
666 -- | InterposeFirstYield s1 i1
667 | InterposeFirstInner s1 i1
668 | InterposeFirstInject s1
669 -- | InterposeFirstBuf s1 i1
670 | InterposeSecondYield s1 i1
671 -- -- | InterposeSecondYield s1 i1 a
672 -- -- | InterposeFirstResume s1 i1 a
674-- Note that this only interposes the pure values, we may run many effects to
675-- generate those values as some effects may not generate anything (Skip).
676{-# INLINE_NORMAL interpose #-}
677interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
680 (Unfold istep1 inject1) (Stream step1 state1) =
681 Stream step (InterposeFirst state1)
685 {-# INLINE_LATE step #-}
686 step gst (InterposeFirst s1) = do
687 r <- step1 (adaptState gst) s1
691 i `seq` return (Skip (InterposeFirstInner s i))
692 -- i `seq` return (Skip (InterposeFirstYield s i))
693 Skip s -> return $ Skip (InterposeFirst s)
697 step _ (InterposeFirstYield s1 i1) = do
700 Yield x i' -> Yield x (InterposeFirstInner s1 i')
701 Skip i' -> Skip (InterposeFirstYield s1 i')
702 Stop -> Skip (InterposeFirst s1)
705 step _ (InterposeFirstInner s1 i1) = do
708 Yield x i' -> Yield x (InterposeFirstInner s1 i')
709 Skip i' -> Skip (InterposeFirstInner s1 i')
710 Stop -> Skip (InterposeFirstInject s1)
712 step gst (InterposeFirstInject s1) = do
713 r <- step1 (adaptState gst) s1
717 -- i `seq` return (Skip (InterposeFirstBuf s i))
718 i `seq` return (Skip (InterposeSecondYield s i))
719 Skip s -> return $ Skip (InterposeFirstInject s)
723 step _ (InterposeFirstBuf s1 i1) = do
726 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
727 Skip i' -> Skip (InterposeFirstBuf s1 i')
732 step _ (InterposeSecondYield s1 i1 v) = do
734 return $ Yield r (InterposeFirstResume s1 i1 v)
736 step _ (InterposeSecondYield s1 i1) = do
738 return $ Yield r (InterposeFirstInner s1 i1)
741 step _ (InterposeFirstResume s1 i1 v) = do
742 return $ Yield v (InterposeFirstInner s1 i1)
745------------------------------------------------------------------------------
746-- Combine N Streams - intercalate
747------------------------------------------------------------------------------
749data ICUState s1 s2 i1 i2 =
754 | ICUFirstInner s1 s2 i1
755 | ICUSecondInner s1 s2 i2
756 | ICUFirstOnlyInner s1 i1
757 | ICUSecondOnlyInner s2 i2
759-- | Interleave streams (full streams, not the elements) unfolded from two
760-- input streams and concat. Stop when the first stream stops. If the second
761-- stream ends before the first one then first stream still keeps running alone
762-- without any interleaving with the second stream.
764-- [a1, a2, ... an] [b1, b2 ...]
765-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
766-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
767-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
769{-# INLINE_NORMAL gintercalateSuffix #-}
772 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
774 (Unfold istep1 inject1) (Stream step1 state1)
775 (Unfold istep2 inject2) (Stream step2 state2) =
776 Stream step (ICUFirst state1 state2)
780 {-# INLINE_LATE step #-}
781 step gst (ICUFirst s1 s2) = do
782 r <- step1 (adaptState gst) s1
786 i `seq` return (Skip (ICUFirstInner s s2 i))
787 Skip s -> return $ Skip (ICUFirst s s2)
790 step gst (ICUFirstOnly s1) = do
791 r <- step1 (adaptState gst) s1
795 i `seq` return (Skip (ICUFirstOnlyInner s i))
796 Skip s -> return $ Skip (ICUFirstOnly s)
799 step _ (ICUFirstInner s1 s2 i1) = do
802 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
803 Skip i' -> Skip (ICUFirstInner s1 s2 i')
804 Stop -> Skip (ICUSecond s1 s2)
806 step _ (ICUFirstOnlyInner s1 i1) = do
809 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
810 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
811 Stop -> Skip (ICUFirstOnly s1)
813 step gst (ICUSecond s1 s2) = do
814 r <- step2 (adaptState gst) s2
818 i `seq` return (Skip (ICUSecondInner s1 s i))
819 Skip s -> return $ Skip (ICUSecond s1 s)
820 Stop -> return $ Skip (ICUFirstOnly s1)
822 step _ (ICUSecondInner s1 s2 i2) = do
825 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
826 Skip i' -> Skip (ICUSecondInner s1 s2 i')
827 Stop -> Skip (ICUFirst s1 s2)
829 step _ (ICUSecondOnly _s2) = undefined
830 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
832data ICALState s1 s2 i1 i2 a =
834 -- | ICALFirstYield s1 s2 i1
835 | ICALFirstInner s1 s2 i1
837 | ICALFirstOnlyInner s1 i1
838 | ICALSecondInject s1 s2
839 | ICALFirstInject s1 s2 i2
840 -- | ICALFirstBuf s1 s2 i1 i2
841 | ICALSecondInner s1 s2 i1 i2
842 -- -- | ICALSecondInner s1 s2 i1 i2 a
843 -- -- | ICALFirstResume s1 s2 i1 i2 a
845-- | Interleave streams (full streams, not the elements) unfolded from two
846-- input streams and concat. Stop when the first stream stops. If the second
847-- stream ends before the first one then first stream still keeps running alone
848-- without any interleaving with the second stream.
850-- [a1, a2, ... an] [b1, b2 ...]
851-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
852-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
853-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
855{-# INLINE_NORMAL gintercalate #-}
858 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
860 (Unfold istep1 inject1) (Stream step1 state1)
861 (Unfold istep2 inject2) (Stream step2 state2) =
862 Stream step (ICALFirst state1 state2)
866 {-# INLINE_LATE step #-}
867 step gst (ICALFirst s1 s2) = do
868 r <- step1 (adaptState gst) s1
872 i `seq` return (Skip (ICALFirstInner s s2 i))
873 -- i `seq` return (Skip (ICALFirstYield s s2 i))
874 Skip s -> return $ Skip (ICALFirst s s2)
878 step _ (ICALFirstYield s1 s2 i1) = do
881 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
882 Skip i' -> Skip (ICALFirstYield s1 s2 i')
883 Stop -> Skip (ICALFirst s1 s2)
886 step _ (ICALFirstInner s1 s2 i1) = do
889 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
890 Skip i' -> Skip (ICALFirstInner s1 s2 i')
891 Stop -> Skip (ICALSecondInject s1 s2)
893 step gst (ICALFirstOnly s1) = do
894 r <- step1 (adaptState gst) s1
898 i `seq` return (Skip (ICALFirstOnlyInner s i))
899 Skip s -> return $ Skip (ICALFirstOnly s)
902 step _ (ICALFirstOnlyInner s1 i1) = do
905 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
906 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
907 Stop -> Skip (ICALFirstOnly s1)
909 -- We inject the second stream even before checking if the first stream
910 -- would yield any more elements. There is no clear choice whether we
911 -- should do this before or after that. Doing it after may make the state
912 -- machine a bit simpler though.
913 step gst (ICALSecondInject s1 s2) = do
914 r <- step2 (adaptState gst) s2
918 i `seq` return (Skip (ICALFirstInject s1 s i))
919 Skip s -> return $ Skip (ICALSecondInject s1 s)
920 Stop -> return $ Skip (ICALFirstOnly s1)
922 step gst (ICALFirstInject s1 s2 i2) = do
923 r <- step1 (adaptState gst) s1
927 i `seq` return (Skip (ICALSecondInner s s2 i i2))
928 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
929 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
933 step _ (ICALFirstBuf s1 s2 i1 i2) = do
936 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
937 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
940 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
943 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
944 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
945 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
948 step _ (ICALSecondInner s1 s2 i1 i2) = do
951 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
952 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
953 Stop -> Skip (ICALFirstInner s1 s2 i1)
954 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
957 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
958 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
961------------------------------------------------------------------------------
963------------------------------------------------------------------------------
965{-# ANN type FIterState Fuse #-}
966data FIterState s f m a b
968 | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
969 | FIterYield b (FIterState s f m a b)
972{-# INLINE_NORMAL foldIterateM #-}
974 Monad m => (b -> m (FL.Fold m a b)) -> b -> Stream m a -> Stream m b
975foldIterateM func seed0 (Stream step state) =
976 Stream stepOuter (FIterInit state seed0)
980 {-# INLINE iterStep #-}
981 iterStep from st fstep extract = do
986 FL.Partial fs -> FIterStream st fstep fs extract
987 FL.Done fb -> FIterYield fb $ FIterInit st fb
989 {-# INLINE_LATE stepOuter #-}
990 stepOuter _ (FIterInit st seed) = do
991 (FL.Fold fstep initial extract) <- func seed
992 iterStep initial st fstep extract
993 stepOuter gst (FIterStream st fstep fs extract) = do
994 r <- step (adaptState gst) st
997 iterStep (fstep fs x) s fstep extract
998 Skip s -> return $ Skip $ FIterStream s fstep fs extract
1001 return $ Skip $ FIterYield b FIterStop
1002 stepOuter _ (FIterYield a next) = return $ Yield a next
1003 stepOuter _ FIterStop = return Stop
1005------------------------------------------------------------------------------
1007------------------------------------------------------------------------------
1009{-# ANN type ParseChunksState Fuse #-}
1010data ParseChunksState x inpBuf st pst =
1011 ParseChunksInit inpBuf st
1012 | ParseChunksInitLeftOver inpBuf
1013 | ParseChunksStream st inpBuf !pst
1014 | ParseChunksBuf inpBuf st inpBuf !pst
1015 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1017{-# INLINE_NORMAL parseMany #-}
1023parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1024 Stream stepOuter (ParseChunksInit [] state)
1028 {-# INLINE_LATE stepOuter #-}
1029 -- Buffer is empty, get the first element from the stream, initialize the
1030 -- fold and then go to stream processing loop.
1031 stepOuter gst (ParseChunksInit [] st) = do
1032 r <- step (adaptState gst) st
1038 return $ Skip $ ParseChunksBuf [x] s [] ps
1040 let next = ParseChunksInit [x] s
1041 in return $ Skip $ ParseChunksYield pb next
1042 PRD.IError err -> throwM $ ParseError err
1043 Skip s -> return $ Skip $ ParseChunksInit [] s
1046 -- Buffer is not empty, go to buffered processing loop
1047 stepOuter _ (ParseChunksInit src st) = do
1051 return $ Skip $ ParseChunksBuf src st [] ps
1053 let next = ParseChunksInit src st
1054 in return $ Skip $ ParseChunksYield pb next
1055 PRD.IError err -> throwM $ ParseError err
1057 -- XXX we just discard any leftover input at the end
1058 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1060 -- Buffer is empty, process elements from the stream
1061 stepOuter gst (ParseChunksStream st buf pst) = do
1062 r <- step (adaptState gst) st
1067 PR.Partial 0 pst1 ->
1068 return $ Skip $ ParseChunksStream s [] pst1
1069 PR.Partial n pst1 -> do
1070 assert (n <= length (x:buf)) (return ())
1071 let src0 = Prelude.take n (x:buf)
1072 src = Prelude.reverse src0
1073 return $ Skip $ ParseChunksBuf src s [] pst1
1074 PR.Continue 0 pst1 ->
1075 return $ Skip $ ParseChunksStream s (x:buf) pst1
1076 PR.Continue n pst1 -> do
1077 assert (n <= length (x:buf)) (return ())
1078 let (src0, buf1) = splitAt n (x:buf)
1079 src = Prelude.reverse src0
1080 return $ Skip $ ParseChunksBuf src s buf1 pst1
1083 ParseChunksYield b (ParseChunksInit [] s)
1085 assert (n <= length (x:buf)) (return ())
1086 let src = Prelude.reverse (Prelude.take n (x:buf))
1088 ParseChunksYield b (ParseChunksInit src s)
1089 PR.Error err -> throwM $ ParseError err
1090 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1093 let src = Prelude.reverse buf
1095 ParseChunksYield b (ParseChunksInitLeftOver src)
1097 -- go back to stream processing mode
1098 stepOuter _ (ParseChunksBuf [] s buf pst) =
1099 return $ Skip $ ParseChunksStream s buf pst
1101 -- buffered processing loop
1102 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1105 PR.Partial 0 pst1 ->
1106 return $ Skip $ ParseChunksBuf xs s [] pst1
1107 PR.Partial n pst1 -> do
1108 assert (n <= length (x:buf)) (return ())
1109 let src0 = Prelude.take n (x:buf)
1110 src = Prelude.reverse src0 ++ xs
1111 return $ Skip $ ParseChunksBuf src s [] pst1
1112 PR.Continue 0 pst1 ->
1113 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1114 PR.Continue n pst1 -> do
1115 assert (n <= length (x:buf)) (return ())
1116 let (src0, buf1) = splitAt n (x:buf)
1117 src = Prelude.reverse src0 ++ xs
1118 return $ Skip $ ParseChunksBuf src s buf1 pst1
1120 return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1122 assert (n <= length (x:buf)) (return ())
1123 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1124 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1125 PR.Error err -> throwM $ ParseError err
1127 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1129{-# ANN type ConcatParseState Fuse #-}
1130data ConcatParseState b inpBuf st p m a =
1131 ConcatParseInit inpBuf st p
1132 | ConcatParseInitLeftOver inpBuf
1133 | forall s. ConcatParseStream st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1134 | forall s. ConcatParseBuf inpBuf st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1135 | ConcatParseYield b (ConcatParseState b inpBuf st p m a)
1137{-# INLINE_NORMAL parseIterate #-}
1140 => (b -> PRD.Parser m a b)
1144parseIterate func seed (Stream step state) =
1145 Stream stepOuter (ConcatParseInit [] state (func seed))
1149 {-# INLINE_LATE stepOuter #-}
1150 -- Buffer is empty, go to stream processing loop
1151 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1155 return $ Skip $ ConcatParseStream st [] pstep ps extract
1157 let next = ConcatParseInit [] st (func pb)
1158 in return $ Skip $ ConcatParseYield pb next
1159 PRD.IError err -> throwM $ ParseError err
1161 -- Buffer is not empty, go to buffered processing loop
1162 stepOuter _ (ConcatParseInit src st
1163 (PRD.Parser pstep initial extract)) = do
1167 return $ Skip $ ConcatParseBuf src st [] pstep ps extract
1169 let next = ConcatParseInit src st (func pb)
1170 in return $ Skip $ ConcatParseYield pb next
1171 PRD.IError err -> throwM $ ParseError err
1173 -- XXX we just discard any leftover input at the end
1174 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1176 -- Buffer is empty process elements from the stream
1177 stepOuter gst (ConcatParseStream st buf pstep pst extract) = do
1178 r <- step (adaptState gst) st
1183 PR.Partial 0 pst1 ->
1184 return $ Skip $ ConcatParseStream s [] pstep pst1 extract
1185 PR.Partial n pst1 -> do
1186 assert (n <= length (x:buf)) (return ())
1187 let src0 = Prelude.take n (x:buf)
1188 src = Prelude.reverse src0
1189 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1190 -- PR.Continue 0 pst1 ->
1191 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1192 PR.Continue n pst1 -> do
1193 assert (n <= length (x:buf)) (return ())
1194 let (src0, buf1) = splitAt n (x:buf)
1195 src = Prelude.reverse src0
1196 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1197 -- XXX Specialize for Stop 0 common case?
1199 assert (n <= length (x:buf)) (return ())
1200 let src = Prelude.reverse (Prelude.take n (x:buf))
1202 ConcatParseYield b (ConcatParseInit src s (func b))
1203 PR.Error err -> throwM $ ParseError err
1204 Skip s -> return $ Skip $ ConcatParseStream s buf pstep pst extract
1207 let src = Prelude.reverse buf
1208 return $ Skip $ ConcatParseYield b (ConcatParseInitLeftOver src)
1210 -- go back to stream processing mode
1211 stepOuter _ (ConcatParseBuf [] s buf pstep ps extract) =
1212 return $ Skip $ ConcatParseStream s buf pstep ps extract
1214 -- buffered processing loop
1215 stepOuter _ (ConcatParseBuf (x:xs) s buf pstep pst extract) = do
1218 PR.Partial 0 pst1 ->
1219 return $ Skip $ ConcatParseBuf xs s [] pstep pst1 extract
1220 PR.Partial n pst1 -> do
1221 assert (n <= length (x:buf)) (return ())
1222 let src0 = Prelude.take n (x:buf)
1223 src = Prelude.reverse src0 ++ xs
1224 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1225 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1226 PR.Continue n pst1 -> do
1227 assert (n <= length (x:buf)) (return ())
1228 let (src0, buf1) = splitAt n (x:buf)
1229 src = Prelude.reverse src0 ++ xs
1230 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1231 -- XXX Specialize for Stop 0 common case?
1233 assert (n <= length (x:buf)) (return ())
1234 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1235 return $ Skip $ ConcatParseYield b
1236 (ConcatParseInit src s (func b))
1237 PR.Error err -> throwM $ ParseError err
1239 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1241------------------------------------------------------------------------------
1243------------------------------------------------------------------------------
1245data GroupByState st fs a b
1248 | GroupingInitWith st !a
1249 | GroupingDoWith st !fs !a
1250 | GroupingYield !b (GroupByState st fs a b)
1253{-# INLINE_NORMAL groupsBy #-}
1260groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1262groupsBy cmp (Fold fstep initial done) (Stream step state) =
1263 Stream stepOuter (GroupingInit state)
1267 {-# INLINE_LATE stepOuter #-}
1268 stepOuter _ (GroupingInit st) = do
1269 -- XXX Note that if the stream stops without yielding a single element
1270 -- in the group we discard the "initial" effect.
1274 FL.Partial s -> Skip $ GroupingDo st s
1275 FL.Done b -> Yield b $ GroupingInit st
1276 stepOuter gst (GroupingDo st fs) = do
1277 res <- step (adaptState gst) st
1282 FL.Partial fs1 -> go SPEC x s fs1
1283 FL.Done b -> return $ Yield b (GroupingInit s)
1284 Skip s -> return $ Skip $ GroupingDo s fs
1289 go !_ prev stt !acc = do
1290 res <- step (adaptState gst) stt
1297 FL.Partial fs1 -> go SPEC prev s fs1
1298 FL.Done b -> return $ Yield b (GroupingInit s)
1301 return $ Yield r (GroupingInitWith s x)
1302 Skip s -> go SPEC prev s acc
1303 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1304 stepOuter _ (GroupingInitWith st x) = do
1308 FL.Partial s -> Skip $ GroupingDoWith st s x
1309 FL.Done b -> Yield b $ GroupingInitWith st x
1310 stepOuter gst (GroupingDoWith st fs prev) = do
1311 res <- fstep fs prev
1313 FL.Partial fs1 -> go SPEC st fs1
1314 FL.Done b -> return $ Yield b (GroupingInit st)
1318 -- XXX code duplicated from the previous equation
1320 res <- step (adaptState gst) stt
1327 FL.Partial fs1 -> go SPEC s fs1
1328 FL.Done b -> return $ Yield b (GroupingInit s)
1331 return $ Yield r (GroupingInitWith s x)
1332 Skip s -> go SPEC s acc
1333 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1334 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1335 stepOuter _ GroupingDone = return Stop
1337{-# INLINE_NORMAL groupsRollingBy #-}
1338groupsRollingBy :: Monad m
1344groupsRollingBy eq fld = parseMany (PRD.groupByRolling eq fld)
1346groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
1347 Stream stepOuter (GroupingInit state)
1351 {-# INLINE_LATE stepOuter #-}
1352 stepOuter _ (GroupingInit st) = do
1353 -- XXX Note that if the stream stops without yielding a single element
1354 -- in the group we discard the "initial" effect.
1358 FL.Partial fs -> Skip $ GroupingDo st fs
1359 FL.Done fb -> Yield fb $ GroupingInit st
1360 stepOuter gst (GroupingDo st fs) = do
1361 res <- step (adaptState gst) st
1366 FL.Partial fs1 -> go SPEC x s fs1
1367 FL.Done fb -> return $ Yield fb (GroupingInit s)
1368 Skip s -> return $ Skip $ GroupingDo s fs
1373 go !_ prev stt !acc = do
1374 res <- step (adaptState gst) stt
1381 FL.Partial fs1 -> go SPEC x s fs1
1382 FL.Done b -> return $ Yield b (GroupingInit s)
1385 return $ Yield r (GroupingInitWith s x)
1386 Skip s -> go SPEC prev s acc
1387 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1388 stepOuter _ (GroupingInitWith st x) = do
1392 FL.Partial s -> Skip $ GroupingDoWith st s x
1393 FL.Done b -> Yield b $ GroupingInitWith st x
1394 stepOuter gst (GroupingDoWith st fs previous) = do
1395 res <- fstep fs previous
1397 FL.Partial s -> go SPEC previous st s
1398 FL.Done b -> return $ Yield b (GroupingInit st)
1402 -- XXX GHC: groupsBy has one less parameter in this go loop and it
1403 -- fuses. However, groupsRollingBy does not fuse, removing the prev
1404 -- parameter makes it fuse. Something needs to be fixed in GHC. The
1405 -- workaround for this is noted in the comments below.
1406 go !_ prev !stt !acc = do
1407 res <- step (adaptState gst) stt
1414 FL.Partial fs1 -> go SPEC x s fs1
1415 FL.Done b -> return $ Yield b (GroupingInit st)
1419 return $ Yield r (GroupingInitWith s x)
1421 -- The code above does not let groupBy fuse. We use the
1422 -- alternative code below instead. Instead of jumping
1423 -- to GroupingInitWith state, we unroll the code of
1424 -- GroupingInitWith state here to help GHC with stream
1431 FL.Partial fsi -> GroupingDoWith s fsi x
1432 FL.Done b -> GroupingYield b (GroupingInit s)
1433 Skip s -> go SPEC prev s acc
1434 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1435 stepOuter _ (GroupingYield r next) = return $ Yield r next
1436 stepOuter _ GroupingDone = return Stop
1438------------------------------------------------------------------------------
1439-- Splitting - by a predicate
1440------------------------------------------------------------------------------
1442data WordsByState st fs b
1446 | WordsByYield !b (WordsByState st fs b)
1448{-# INLINE_NORMAL wordsBy #-}
1449wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1450wordsBy predicate (Fold fstep initial done) (Stream step state) =
1451 Stream stepOuter (WordsByInit state)
1455 {-# INLINE_LATE stepOuter #-}
1456 stepOuter _ (WordsByInit st) = do
1460 FL.Partial s -> Skip $ WordsByDo st s
1461 FL.Done b -> Yield b (WordsByInit st)
1463 stepOuter gst (WordsByDo st fs) = do
1464 res <- step (adaptState gst) st
1472 FL.Partial fs1 -> Skip $ WordsByDo s fs1
1473 FL.Done b -> Yield b (WordsByInit s)
1477 FL.Partial fs1 -> go SPEC s fs1
1478 FL.Done b -> return $ Yield b (WordsByInit s)
1479 Skip s -> return $ Skip $ WordsByDo s fs
1485 res <- step (adaptState gst) stt
1492 return $ Yield r (WordsByInit s)
1494 -- The above code does not fuse well. Need to check why
1495 -- GHC is not able to simplify it well. Using the code
1496 -- below, instead of jumping through the WordsByInit
1497 -- state always, we directly go to WordsByDo state in
1498 -- the common case of Partial.
1504 FL.Partial fs1 -> WordsByDo s fs1
1505 FL.Done b -> WordsByYield b (WordsByInit s)
1509 FL.Partial fs1 -> go SPEC s fs1
1510 FL.Done b -> return $ Yield b (WordsByInit s)
1511 Skip s -> go SPEC s acc
1512 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
1514 stepOuter _ WordsByDone = return Stop
1516 stepOuter _ (WordsByYield b next) = return $ Yield b next
1518------------------------------------------------------------------------------
1519-- Splitting on a sequence
1520------------------------------------------------------------------------------
1522-- String search algorithms:
1523-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1526-- TODO can we unify the splitting operations using a splitting configuration
1527-- like in the split package.
1529data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1530data SplitOptions = SplitOptions
1531 { style :: SplitStyle
1532 , withSep :: Bool -- ^ keep the separators in output
1533 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1534 -- , trimHead :: Bool -- ^ drop blank at head
1535 -- , trimTail :: Bool -- ^ drop blank at tail
1539-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
1540-- because we can use the constructor directly without having to create "jump"
1542{-# ANN type SplitOnSeqState Fuse #-}
1543data SplitOnSeqState rb rh ck w fs s b x =
1545 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1548 | SplitOnSeqEmpty !fs s
1550 | SplitOnSeqSingle !fs s x
1552 | SplitOnSeqWordInit !fs s
1553 | SplitOnSeqWordLoop !w s !fs
1554 | SplitOnSeqWordDone Int !fs !w
1556 | SplitOnSeqKRInit Int !fs s rb !rh
1557 | SplitOnSeqKRLoop fs s rb !rh !ck
1558 | SplitOnSeqKRCheck fs s rb !rh
1559 | SplitOnSeqKRDone Int !fs rb !rh
1561 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
1563{-# INLINE_NORMAL splitOnSeq #-}
1565 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1570splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1571 Stream stepOuter SplitOnSeqInit
1575 patLen = A.length patArr
1576 maxIndex = patLen - 1
1577 elemBits = sizeOf (undefined :: a) * 8
1579 -- For word pattern case
1581 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1584 elemMask = (1 `shiftL` elemBits) - 1
1587 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1589 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1591 -- For Rabin-Karp search
1592 k = 2891336453 :: Word32
1595 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1597 deltaCksum cksum old new =
1598 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1600 -- XXX shall we use a random starting hash or 1 instead of 0?
1601 patHash = A.foldl' addCksum 0 patArr
1603 skip = return . Skip
1605 nextAfterInit nextGen stepRes =
1607 FL.Partial s -> nextGen s
1608 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
1610 {-# INLINE yieldProceed #-}
1611 yieldProceed nextGen fs =
1612 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
1614 {-# INLINE_LATE stepOuter #-}
1615 stepOuter _ SplitOnSeqInit = do
1620 then return $ Skip $ SplitOnSeqEmpty acc state
1623 pat <- liftIO $ A.unsafeIndexIO patArr 0
1624 return $ Skip $ SplitOnSeqSingle acc state pat
1625 else if sizeOf (undefined :: a) * patLen
1626 <= sizeOf (undefined :: Word)
1627 then return $ Skip $ SplitOnSeqWordInit acc state
1629 (rb, rhead) <- liftIO $ RB.new patLen
1630 skip $ SplitOnSeqKRInit 0 acc state rb rhead
1631 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
1633 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1635 ---------------------------
1637 ---------------------------
1639 stepOuter _ (SplitOnSeqReinit nextGen) =
1640 initial >>= skip . nextAfterInit nextGen
1642 ---------------------------
1644 ---------------------------
1646 stepOuter gst (SplitOnSeqEmpty acc st) = do
1647 res <- step (adaptState gst) st
1653 FL.Partial acc1 -> done acc1
1654 FL.Done b -> return b
1655 let jump c = SplitOnSeqEmpty c s
1656 in yieldProceed jump b1
1657 Skip s -> skip (SplitOnSeqEmpty acc s)
1664 stepOuter _ SplitOnSeqDone = return Stop
1670 stepOuter gst (SplitOnSeqSingle fs st pat) = do
1671 res <- step (adaptState gst) st
1674 let jump c = SplitOnSeqSingle c s pat
1676 then done fs >>= yieldProceed jump
1680 FL.Partial fs1 -> skip $ jump fs1
1681 FL.Done b -> yieldProceed jump b
1682 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1685 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1687 ---------------------------
1688 -- Short Pattern - Shift Or
1689 ---------------------------
1691 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1693 skip $ SplitOnSeqYield r SplitOnSeqDone
1694 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1695 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1696 r <- fstep fs (toEnum $ fromIntegral old)
1698 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1700 let jump c = SplitOnSeqWordDone (n - 1) c wrd
1703 stepOuter gst (SplitOnSeqWordInit fs st0) =
1709 go !_ !idx !wrd !st = do
1710 res <- step (adaptState gst) st
1713 let wrd1 = addToWord wrd x
1716 if wrd1 .&. wordMask == wordPat
1718 let jump c = SplitOnSeqWordInit c s
1719 done fs >>= yieldProceed jump
1720 else skip $ SplitOnSeqWordLoop wrd1 s fs
1721 else go SPEC (idx + 1) wrd1 s
1722 Skip s -> go SPEC idx wrd s
1725 then skip $ SplitOnSeqWordDone idx fs wrd
1728 skip $ SplitOnSeqYield r SplitOnSeqDone
1730 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1731 go SPEC wrd0 st0 fs0
1736 go !_ !wrd !st !fs = do
1737 res <- step (adaptState gst) st
1740 let jump c = SplitOnSeqWordInit c s
1741 wrd1 = addToWord wrd x
1742 old = (wordMask .&. wrd)
1743 `shiftR` (elemBits * (patLen - 1))
1744 r <- fstep fs (toEnum $ fromIntegral old)
1746 FL.Partial fs1 -> do
1747 if wrd1 .&. wordMask == wordPat
1748 then done fs1 >>= yieldProceed jump
1749 else go SPEC wrd1 s fs1
1750 FL.Done b -> yieldProceed jump b
1751 Skip s -> go SPEC wrd s fs
1752 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1754 -------------------------------
1755 -- General Pattern - Karp Rabin
1756 -------------------------------
1758 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
1759 res <- step (adaptState gst) st
1762 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1765 let fld = RB.unsafeFoldRing (RB.ringBound rb)
1766 let !ringHash = fld addCksum 0 rb
1767 if ringHash == patHash
1768 then skip $ SplitOnSeqKRCheck fs s rb rh1
1769 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1770 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
1771 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
1773 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1775 -- XXX The recursive "go" is more efficient than the state based recursion
1776 -- code commented out below. Perhaps its more efficient because of
1777 -- factoring out "rb" outside the loop.
1779 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1780 go SPEC fs0 st0 rh0 cksum0
1784 go !_ !fs !st !rh !cksum = do
1785 res <- step (adaptState gst) st
1788 old <- liftIO $ peek rh
1789 let cksum1 = deltaCksum cksum old x
1792 FL.Partial fs1 -> do
1793 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1794 if cksum1 == patHash
1795 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1796 else go SPEC fs1 s rh1 cksum1
1798 let rst = RB.startOf rb
1799 jump c = SplitOnSeqKRInit 0 c s rb rst
1801 Skip s -> go SPEC fs s rh cksum
1802 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1804 -- XXX The following code is 5 times slower compared to the recursive loop
1805 -- based code above. Need to investigate why. One possibility is that the
1806 -- go loop above does not thread around the ring buffer (rb). This code may
1807 -- be causing the state to bloat and getting allocated on each iteration.
1808 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1809 -- such problem is needed. One way to avoid this could be to use unboxed
1812 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1813 res <- step (adaptState gst) st
1816 old <- liftIO $ peek rh
1817 let cksum1 = deltaCksum cksum old x
1819 if (cksum1 == patHash)
1822 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1824 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1825 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1826 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1827 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1830 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1831 if RB.unsafeEqArray rb rh patArr
1834 let rst = RB.startOf rb
1835 jump c = SplitOnSeqKRInit 0 c st rb rst
1837 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1839 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1841 skip $ SplitOnSeqYield r SplitOnSeqDone
1842 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1843 old <- liftIO $ peek rh
1844 let rh1 = RB.advance rb rh
1847 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
1849 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
1852{-# ANN type SplitOnSuffixSeqState Fuse #-}
1853data SplitOnSuffixSeqState rb rh ck w fs s b x =
1854 SplitOnSuffixSeqInit
1855 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
1856 | SplitOnSuffixSeqDone
1858 | SplitOnSuffixSeqEmpty !fs s
1860 | SplitOnSuffixSeqSingleInit !fs s x
1861 | SplitOnSuffixSeqSingle !fs s x
1863 | SplitOnSuffixSeqWordInit !fs s
1864 | SplitOnSuffixSeqWordLoop !w s !fs
1865 | SplitOnSuffixSeqWordDone Int !fs !w
1867 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
1868 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
1869 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
1870 | SplitOnSuffixSeqKRCheck fs s rb !rh
1871 | SplitOnSuffixSeqKRDone Int !fs rb !rh
1873 | SplitOnSuffixSeqReinit
1874 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
1876{-# INLINE_NORMAL splitOnSuffixSeq #-}
1878 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1884splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
1885 Stream stepOuter SplitOnSuffixSeqInit
1889 patLen = A.length patArr
1890 maxIndex = patLen - 1
1891 elemBits = sizeOf (undefined :: a) * 8
1893 -- For word pattern case
1895 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1898 elemMask = (1 `shiftL` elemBits) - 1
1901 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1903 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1905 nextAfterInit nextGen stepRes =
1907 FL.Partial s -> nextGen s
1909 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
1911 {-# INLINE yieldProceed #-}
1912 yieldProceed nextGen fs =
1913 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
1915 -- For single element pattern case
1916 {-# INLINE processYieldSingle #-}
1917 processYieldSingle pat x s fs = do
1918 let jump c = SplitOnSuffixSeqSingleInit c s pat
1921 r <- if withSep then fstep fs x else return $ FL.Partial fs
1924 FL.Partial fs1 -> done fs1
1925 FL.Done b -> return b
1926 yieldProceed jump b1
1930 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
1931 FL.Done b -> yieldProceed jump b
1933 -- For Rabin-Karp search
1934 k = 2891336453 :: Word32
1937 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1939 deltaCksum cksum old new =
1940 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1942 -- XXX shall we use a random starting hash or 1 instead of 0?
1943 patHash = A.foldl' addCksum 0 patArr
1945 skip = return . Skip
1947 {-# INLINE_LATE stepOuter #-}
1948 stepOuter _ SplitOnSuffixSeqInit = do
1953 then skip $ SplitOnSuffixSeqEmpty fs state
1956 pat <- liftIO $ A.unsafeIndexIO patArr 0
1957 skip $ SplitOnSuffixSeqSingleInit fs state pat
1958 else if sizeOf (undefined :: a) * patLen
1959 <= sizeOf (undefined :: Word)
1960 then skip $ SplitOnSuffixSeqWordInit fs state
1962 (rb, rhead) <- liftIO $ RB.new patLen
1963 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
1964 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
1966 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
1968 ---------------------------
1970 ---------------------------
1972 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
1973 initial >>= skip . nextAfterInit nextGen
1975 ---------------------------
1977 ---------------------------
1979 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
1980 res <- step (adaptState gst) st
1983 let jump c = SplitOnSuffixSeqEmpty c s
1987 FL.Partial fs -> done fs
1988 FL.Done b -> return b
1989 yieldProceed jump b1
1990 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
1997 stepOuter _ SplitOnSuffixSeqDone = return Stop
2003 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
2004 res <- step (adaptState gst) st
2006 Yield x s -> processYieldSingle pat x s fs
2007 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
2010 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2011 res <- step (adaptState gst) st
2013 Yield x s -> processYieldSingle pat x s fs
2014 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2017 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2019 ---------------------------
2020 -- Short Pattern - Shift Or
2021 ---------------------------
2023 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2025 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2026 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2027 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2028 r <- fstep fs (toEnum $ fromIntegral old)
2030 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2032 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
2035 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
2036 res <- step (adaptState gst) st0
2039 let wrd = addToWord 0 x
2040 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
2042 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2044 let jump c = SplitOnSuffixSeqWordInit c s
2046 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
2052 go !_ !idx !wrd !st !fs = do
2053 res <- step (adaptState gst) st
2056 let jump c = SplitOnSuffixSeqWordInit c s
2057 let wrd1 = addToWord wrd x
2058 r <- if withSep then fstep fs x else return $ FL.Partial fs
2062 then go SPEC (idx + 1) wrd1 s fs1
2063 else if wrd1 .&. wordMask /= wordPat
2064 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2065 else do done fs >>= yieldProceed jump
2066 FL.Done b -> yieldProceed jump b
2067 Skip s -> go SPEC idx wrd s fs
2068 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2070 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2071 go SPEC wrd0 st0 fs0
2076 go !_ !wrd !st !fs = do
2077 res <- step (adaptState gst) st
2080 let jump c = SplitOnSuffixSeqWordInit c s
2081 wrd1 = addToWord wrd x
2082 old = (wordMask .&. wrd)
2083 `shiftR` (elemBits * (patLen - 1))
2087 else fstep fs (toEnum $ fromIntegral old)
2090 if wrd1 .&. wordMask == wordPat
2091 then done fs1 >>= yieldProceed jump
2092 else go SPEC wrd1 s fs1
2093 FL.Done b -> yieldProceed jump b
2094 Skip s -> go SPEC wrd s fs
2096 if wrd .&. wordMask == wordPat
2101 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2102 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2104 -------------------------------
2105 -- General Pattern - Karp Rabin
2106 -------------------------------
2108 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2109 res <- step (adaptState gst) st0
2112 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2113 r <- if withSep then fstep fs x else return $ FL.Partial fs
2116 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2118 let rst = RB.startOf rb
2119 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2121 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2124 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2125 go SPEC 1 rh0 st0 fs0
2129 go !_ !idx !rh st !fs = do
2130 res <- step (adaptState gst) st
2133 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2134 r <- if withSep then fstep fs x else return $ FL.Partial fs
2138 then go SPEC (idx + 1) rh1 s fs1
2140 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2141 !ringHash = fld addCksum 0 rb
2142 in if ringHash == patHash
2143 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2144 else SplitOnSuffixSeqKRLoop
2145 fs1 s rb rh1 ringHash
2147 let rst = RB.startOf rb
2148 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2150 Skip s -> go SPEC idx rh s fs
2152 -- do not issue a blank segment when we end at pattern
2153 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2158 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2159 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2161 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2162 go SPEC fs0 st0 rh0 cksum0
2166 go !_ !fs !st !rh !cksum = do
2167 res <- step (adaptState gst) st
2170 old <- liftIO $ peek rh
2171 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2172 let cksum1 = deltaCksum cksum old x
2173 r <- if withSep then fstep fs x else fstep fs old
2176 if (cksum1 /= patHash)
2177 then go SPEC fs1 s rh1 cksum1
2178 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2180 let rst = RB.startOf rb
2181 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2183 Skip s -> go SPEC fs s rh cksum
2185 if RB.unsafeEqArray rb rh patArr
2190 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2191 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2193 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2194 if RB.unsafeEqArray rb rh patArr
2197 let rst = RB.startOf rb
2198 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2200 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2202 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2204 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2205 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2206 old <- liftIO $ peek rh
2207 let rh1 = RB.advance rb rh
2210 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2212 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2215------------------------------------------------------------------------------
2216-- Nested Container Transformation
2217------------------------------------------------------------------------------
2219{-# ANN type SplitState Fuse #-}
2220data SplitState s arr
2222 | SplitBuffering s arr
2223 | SplitSplitting s arr
2224 | SplitYielding arr (SplitState s arr)
2227-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2228-- split using a splitBy like combinator. The Fold would consume upto the
2229-- separator and return any leftover which can then be fed to the next fold.
2231-- We can revisit this once we have partial folds/parsers.
2233-- | Performs infix separator style splitting.
2234{-# INLINE_NORMAL splitInnerBy #-}
2237 => (f a -> m (f a, Maybe (f a))) -- splitter
2238 -> (f a -> f a -> m (f a)) -- joiner
2241splitInnerBy splitter joiner (Stream step1 state1) =
2242 (Stream step (SplitInitial state1))
2246 {-# INLINE_LATE step #-}
2247 step gst (SplitInitial st) = do
2251 (x1, mx2) <- splitter x
2252 return $ case mx2 of
2253 Nothing -> Skip (SplitBuffering s x1)
2254 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2255 Skip s -> return $ Skip (SplitInitial s)
2256 Stop -> return $ Stop
2258 step gst (SplitBuffering st buf) = do
2262 (x1, mx2) <- splitter x
2263 buf' <- joiner buf x1
2264 return $ case mx2 of
2265 Nothing -> Skip (SplitBuffering s buf')
2266 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2267 Skip s -> return $ Skip (SplitBuffering s buf)
2268 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2270 step _ (SplitSplitting st buf) = do
2271 (x1, mx2) <- splitter buf
2272 return $ case mx2 of
2273 Nothing -> Skip $ SplitBuffering st x1
2274 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2276 step _ (SplitYielding x next) = return $ Yield x next
2277 step _ SplitFinishing = return $ Stop
2279-- | Performs infix separator style splitting.
2280{-# INLINE_NORMAL splitInnerBySuffix #-}
2282 :: (Monad m, Eq (f a), Monoid (f a))
2283 => (f a -> m (f a, Maybe (f a))) -- splitter
2284 -> (f a -> f a -> m (f a)) -- joiner
2287splitInnerBySuffix splitter joiner (Stream step1 state1) =
2288 (Stream step (SplitInitial state1))
2292 {-# INLINE_LATE step #-}
2293 step gst (SplitInitial st) = do
2297 (x1, mx2) <- splitter x
2298 return $ case mx2 of
2299 Nothing -> Skip (SplitBuffering s x1)
2300 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2301 Skip s -> return $ Skip (SplitInitial s)
2302 Stop -> return $ Stop
2304 step gst (SplitBuffering st buf) = do
2308 (x1, mx2) <- splitter x
2309 buf' <- joiner buf x1
2310 return $ case mx2 of
2311 Nothing -> Skip (SplitBuffering s buf')
2312 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2313 Skip s -> return $ Skip (SplitBuffering s buf)
2317 else Skip (SplitYielding buf SplitFinishing)
2319 step _ (SplitSplitting st buf) = do
2320 (x1, mx2) <- splitter buf
2321 return $ case mx2 of
2322 Nothing -> Skip $ SplitBuffering st x1
2323 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2325 step _ (SplitYielding x next) = return $ Yield x next
2326 step _ SplitFinishing = return Stop
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list