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.
120 -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
121 -- unfoldMany. concatMap generates a stream from single values in a
122 -- stream and flattens, parseMany does the opposite of flattening by
123 -- splitting the stream and then folds each such split to single value in
124 -- the output stream.
129 -- | Group segments of a stream and fold. Special case of parsing.
135 -- | A special case of parsing.
141 -- * Transform (Nested Containers)
142 -- | Opposite to compact in ArrayStream
150#include "ArrayMacros.h"
152import Control.Exception (assert)
153import Control.Monad.Catch (MonadThrow, throwM)
154import Control.Monad.IO.Class (MonadIO(..))
155import Data.Bits (shiftR, shiftL, (.|.), (.&.))
156import Data.Functor.Identity ( Identity )
157import Data.Word (Word32)
158import Foreign.Storable (Storable(..))
159import Fusion.Plugin.Types (Fuse(..))
160import GHC.Types (SPEC(..))
162import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
163import Streamly.Internal.Data.Fold.Step (Step(..))
164import Streamly.Internal.Data.Fold.Type (Fold(..))
165import Streamly.Internal.Data.Parser (ParseError(..))
166import Streamly.Internal.Data.Refold.Type (Refold(..))
167import Streamly.Internal.Data.SVar.Type (adaptState)
168import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
169import Streamly.Internal.Data.Unfold.Type (Unfold(..))
171import qualified Streamly.Internal.Data.Array.Foreign.Type as A
172import qualified Streamly.Internal.Data.Fold as FL
173import qualified Streamly.Internal.Data.Parser as PR
174import qualified Streamly.Internal.Data.Parser.ParserD as PRD
175import qualified Streamly.Internal.Data.Ring.Foreign as RB
177import Streamly.Internal.Data.Stream.StreamD.Type
179import Prelude hiding (concatMap, mapM, zipWith)
181------------------------------------------------------------------------------
183------------------------------------------------------------------------------
185data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
187-- Note that this could be much faster compared to the CPS stream. However, as
188-- the number of streams being composed increases this may become expensive.
189-- Need to see where the breaking point is between the two.
191{-# INLINE_NORMAL append #-}
192append :: Monad m => Stream m a -> Stream m a -> Stream m a
193append (Stream step1 state1) (Stream step2 state2) =
194 Stream step (AppendFirst state1)
198 {-# INLINE_LATE step #-}
199 step gst (AppendFirst st) = do
202 Yield a s -> Yield a (AppendFirst s)
203 Skip s -> Skip (AppendFirst s)
204 Stop -> Skip (AppendSecond state2)
206 step gst (AppendSecond st) = do
209 Yield a s -> Yield a (AppendSecond s)
210 Skip s -> Skip (AppendSecond s)
213------------------------------------------------------------------------------
215------------------------------------------------------------------------------
217data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
218 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
220{-# INLINE_NORMAL interleave #-}
221interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
222interleave (Stream step1 state1) (Stream step2 state2) =
223 Stream step (InterleaveFirst state1 state2)
227 {-# INLINE_LATE step #-}
228 step gst (InterleaveFirst st1 st2) = do
231 Yield a s -> Yield a (InterleaveSecond s st2)
232 Skip s -> Skip (InterleaveFirst s st2)
233 Stop -> Skip (InterleaveSecondOnly st2)
235 step gst (InterleaveSecond st1 st2) = do
238 Yield a s -> Yield a (InterleaveFirst st1 s)
239 Skip s -> Skip (InterleaveSecond st1 s)
240 Stop -> Skip (InterleaveFirstOnly st1)
242 step gst (InterleaveFirstOnly st1) = do
245 Yield a s -> Yield a (InterleaveFirstOnly s)
246 Skip s -> Skip (InterleaveFirstOnly s)
249 step gst (InterleaveSecondOnly st2) = do
252 Yield a s -> Yield a (InterleaveSecondOnly s)
253 Skip s -> Skip (InterleaveSecondOnly s)
256{-# INLINE_NORMAL interleaveMin #-}
257interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
258interleaveMin (Stream step1 state1) (Stream step2 state2) =
259 Stream step (InterleaveFirst state1 state2)
263 {-# INLINE_LATE step #-}
264 step gst (InterleaveFirst st1 st2) = do
267 Yield a s -> Yield a (InterleaveSecond s st2)
268 Skip s -> Skip (InterleaveFirst s st2)
271 step gst (InterleaveSecond st1 st2) = do
274 Yield a s -> Yield a (InterleaveFirst st1 s)
275 Skip s -> Skip (InterleaveSecond st1 s)
278 step _ (InterleaveFirstOnly _) = undefined
279 step _ (InterleaveSecondOnly _) = undefined
281{-# INLINE_NORMAL interleaveSuffix #-}
282interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
283interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
284 Stream step (InterleaveFirst state1 state2)
288 {-# INLINE_LATE step #-}
289 step gst (InterleaveFirst st1 st2) = do
292 Yield a s -> Yield a (InterleaveSecond s st2)
293 Skip s -> Skip (InterleaveFirst s st2)
296 step gst (InterleaveSecond st1 st2) = do
299 Yield a s -> Yield a (InterleaveFirst st1 s)
300 Skip s -> Skip (InterleaveSecond st1 s)
301 Stop -> Skip (InterleaveFirstOnly st1)
303 step gst (InterleaveFirstOnly st1) = do
306 Yield a s -> Yield a (InterleaveFirstOnly s)
307 Skip s -> Skip (InterleaveFirstOnly s)
310 step _ (InterleaveSecondOnly _) = undefined
312data InterleaveInfixState s1 s2 a
313 = InterleaveInfixFirst s1 s2
314 | InterleaveInfixSecondBuf s1 s2
315 | InterleaveInfixSecondYield s1 s2 a
316 | InterleaveInfixFirstYield s1 s2 a
317 | InterleaveInfixFirstOnly s1
319{-# INLINE_NORMAL interleaveInfix #-}
320interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
321interleaveInfix (Stream step1 state1) (Stream step2 state2) =
322 Stream step (InterleaveInfixFirst state1 state2)
326 {-# INLINE_LATE step #-}
327 step gst (InterleaveInfixFirst st1 st2) = do
330 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
331 Skip s -> Skip (InterleaveInfixFirst s st2)
334 step gst (InterleaveInfixSecondBuf st1 st2) = do
337 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
338 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
339 Stop -> Skip (InterleaveInfixFirstOnly st1)
341 step gst (InterleaveInfixSecondYield st1 st2 x) = do
344 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
345 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
348 step _ (InterleaveInfixFirstYield st1 st2 x) = do
349 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
351 step gst (InterleaveInfixFirstOnly st1) = do
354 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
355 Skip s -> Skip (InterleaveInfixFirstOnly s)
358------------------------------------------------------------------------------
360------------------------------------------------------------------------------
362{-# INLINE_NORMAL roundRobin #-}
363roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
364roundRobin (Stream step1 state1) (Stream step2 state2) =
365 Stream step (InterleaveFirst state1 state2)
369 {-# INLINE_LATE step #-}
370 step gst (InterleaveFirst st1 st2) = do
373 Yield a s -> Yield a (InterleaveSecond s st2)
374 Skip s -> Skip (InterleaveSecond s st2)
375 Stop -> Skip (InterleaveSecondOnly st2)
377 step gst (InterleaveSecond st1 st2) = do
380 Yield a s -> Yield a (InterleaveFirst st1 s)
381 Skip s -> Skip (InterleaveFirst st1 s)
382 Stop -> Skip (InterleaveFirstOnly st1)
384 step gst (InterleaveSecondOnly st2) = do
387 Yield a s -> Yield a (InterleaveSecondOnly s)
388 Skip s -> Skip (InterleaveSecondOnly s)
391 step gst (InterleaveFirstOnly st1) = do
394 Yield a s -> Yield a (InterleaveFirstOnly s)
395 Skip s -> Skip (InterleaveFirstOnly s)
398------------------------------------------------------------------------------
400------------------------------------------------------------------------------
402{-# INLINE_NORMAL zipWithM #-}
404 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
405zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
407 {-# INLINE_LATE step #-}
408 step gst (sa, sb, Nothing) = do
409 r <- stepa (adaptState gst) sa
412 Yield x sa' -> Skip (sa', sb, Just x)
413 Skip sa' -> Skip (sa', sb, Nothing)
416 step gst (sa, sb, Just x) = do
417 r <- stepb (adaptState gst) sb
421 return $ Yield z (sa, sb', Nothing)
422 Skip sb' -> return $ Skip (sa, sb', Just x)
425{-# RULES "zipWithM xs xs"
426 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
428{-# INLINE zipWith #-}
429zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
430zipWith f = zipWithM (\a b -> return (f a b))
432------------------------------------------------------------------------------
434------------------------------------------------------------------------------
436{-# INLINE_NORMAL mergeByM #-}
439 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
440mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
441 Stream step (Just ta, Just tb, Nothing, Nothing)
443 {-# INLINE_LATE step #-}
445 -- one of the values is missing, and the corresponding stream is running
446 step gst (Just sa, sb, Nothing, b) = do
449 Yield a sa' -> Skip (Just sa', sb, Just a, b)
450 Skip sa' -> Skip (Just sa', sb, Nothing, b)
451 Stop -> Skip (Nothing, sb, Nothing, b)
453 step gst (sa, Just sb, a, Nothing) = do
456 Yield b sb' -> Skip (sa, Just sb', a, Just b)
457 Skip sb' -> Skip (sa, Just sb', a, Nothing)
458 Stop -> Skip (sa, Nothing, a, Nothing)
460 -- both the values are available
461 step _ (sa, sb, Just a, Just b) = do
464 GT -> Yield b (sa, sb, Just a, Nothing)
465 _ -> Yield a (sa, sb, Nothing, Just b)
467 -- one of the values is missing, corresponding stream is done
468 step _ (Nothing, sb, Nothing, Just b) =
469 return $ Yield b (Nothing, sb, Nothing, Nothing)
471 step _ (sa, Nothing, Just a, Nothing) =
472 return $ Yield a (sa, Nothing, Nothing, Nothing)
474 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
476{-# INLINE mergeBy #-}
479 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
480mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
482-------------------------------------------------------------------------------
483-- Intersection of sorted streams
484-------------------------------------------------------------------------------
486-- Assuming the streams are sorted in ascending order
487{-# INLINE_NORMAL intersectBySorted #-}
488intersectBySorted :: Monad m
489 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
490intersectBySorted cmp (Stream stepa ta) (Stream stepb tb) =
492 ( ta -- left stream state
493 , tb -- right stream state
494 , Nothing -- left value
495 , Nothing -- right value
500 {-# INLINE_LATE step #-}
501 -- step 1, fetch the first value
502 step gst (sa, sb, Nothing, b) = do
505 Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
506 Skip sa' -> Skip (sa', sb, Nothing, b)
509 -- step 2, fetch the second value
510 step gst (sa, sb, a@(Just _), Nothing) = do
513 Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
514 Skip sb' -> Skip (sa, sb', a, Nothing)
517 -- step 3, compare the two values
518 step _ (sa, sb, Just a, Just b) = do
521 GT -> Skip (sa, sb, Just a, Nothing) -- step 2
522 LT -> Skip (sa, sb, Nothing, Just b) -- step 1
523 EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
525------------------------------------------------------------------------------
526-- Combine N Streams - unfoldMany
527------------------------------------------------------------------------------
529data ConcatUnfoldInterleaveState o i =
530 ConcatUnfoldInterleaveOuter o [i]
531 | ConcatUnfoldInterleaveInner o [i]
532 | ConcatUnfoldInterleaveInnerL [i] [i]
533 | ConcatUnfoldInterleaveInnerR [i] [i]
535-- XXX use arrays to store state instead of lists?
537-- XXX In general we can use different scheduling strategies e.g. how to
538-- schedule the outer vs inner loop or assigning weights to different streams
539-- or outer and inner loops.
541-- After a yield, switch to the next stream. Do not switch streams on Skip.
542-- Yield from outer stream switches to the inner stream.
544-- There are two choices here, (1) exhaust the outer stream first and then
545-- start yielding from the inner streams, this is much simpler to implement,
546-- (2) yield at least one element from an inner stream before going back to
547-- outer stream and opening the next stream from it.
549-- Ideally, we need some scheduling bias to inner streams vs outer stream.
550-- Maybe we can configure the behavior.
552-- XXX Instead of using "concatPairsWith wSerial" we can implement an N-way
553-- interleaving CPS combinator which behaves like unfoldManyInterleave. Intead
554-- of pairing up the streams We just need to go yielding one element from each
555-- stream and storing the remaining streams and then keep doing rounds through
556-- those in a round robin fashion. This would be much like wAsync.
558-- | This does not pair streams like concatPairsWith, instead, it goes through
559-- each stream one by one and yields one element from each stream. After it
560-- goes to the last stream it reverses the traversal to come back to the first
561-- stream yielding elements from each stream on its way back to the first
564-- >>> input = Stream.fromList [[1,1],[2,2],[3,3],[4,4],[5,5]]
565-- >>> Stream.toList $ Stream.unfoldManyInterleave Unfold.fromList input
566-- [1,2,3,4,5,5,4,3,2,1]
568-- Note that this is order of magnitude more efficient than "concatPairsWith
570{-# INLINE_NORMAL unfoldManyInterleave #-}
571unfoldManyInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
572unfoldManyInterleave (Unfold istep inject) (Stream ostep ost) =
573 Stream step (ConcatUnfoldInterleaveOuter ost [])
577 {-# INLINE_LATE step #-}
578 step gst (ConcatUnfoldInterleaveOuter o ls) = do
579 r <- ostep (adaptState gst) o
583 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
584 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
585 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
587 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
588 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
591 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
592 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
593 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
595 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
596 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
597 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
599 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
602 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
603 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
604 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
606 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
607 step _ (ConcatUnfoldInterleaveInnerR ls []) =
608 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
610 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
613 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
614 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
615 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
617-- XXX In general we can use different scheduling strategies e.g. how to
618-- schedule the outer vs inner loop or assigning weights to different streams
619-- or outer and inner loops.
621-- This could be inefficient if the tasks are too small.
623-- Compared to unfoldManyInterleave this one switches streams on Skips.
625{-# INLINE_NORMAL unfoldManyRoundRobin #-}
626unfoldManyRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
627unfoldManyRoundRobin (Unfold istep inject) (Stream ostep ost) =
628 Stream step (ConcatUnfoldInterleaveOuter ost [])
630 {-# INLINE_LATE step #-}
631 step gst (ConcatUnfoldInterleaveOuter o ls) = do
632 r <- ostep (adaptState gst) o
636 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
637 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
638 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
640 step _ (ConcatUnfoldInterleaveInner o []) =
641 return $ Skip (ConcatUnfoldInterleaveOuter o [])
643 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
646 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
647 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
648 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
650 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
651 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
652 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
654 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
657 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
658 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
659 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
661 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
662 step _ (ConcatUnfoldInterleaveInnerR ls []) =
663 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
665 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
668 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
669 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
670 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
672------------------------------------------------------------------------------
673-- Combine N Streams - interpose
674------------------------------------------------------------------------------
676{-# ANN type InterposeSuffixState Fuse #-}
677data InterposeSuffixState s1 i1 =
678 InterposeSuffixFirst s1
679 -- | InterposeSuffixFirstYield s1 i1
680 | InterposeSuffixFirstInner s1 i1
681 | InterposeSuffixSecond s1
683-- Note that if an unfolded layer turns out to be nil we still emit the
684-- separator effect. An alternate behavior could be to emit the separator
685-- effect only if at least one element has been yielded by the unfolding.
686-- However, that becomes a bit complicated, so we have chosen the former
688{-# INLINE_NORMAL interposeSuffix #-}
691 => m c -> Unfold m b c -> Stream m b -> Stream m c
694 (Unfold istep1 inject1) (Stream step1 state1) =
695 Stream step (InterposeSuffixFirst state1)
699 {-# INLINE_LATE step #-}
700 step gst (InterposeSuffixFirst s1) = do
701 r <- step1 (adaptState gst) s1
705 i `seq` return (Skip (InterposeSuffixFirstInner s i))
706 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
707 Skip s -> return $ Skip (InterposeSuffixFirst s)
711 step _ (InterposeSuffixFirstYield s1 i1) = do
714 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
715 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
716 Stop -> Skip (InterposeSuffixFirst s1)
719 step _ (InterposeSuffixFirstInner s1 i1) = do
722 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
723 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
724 Stop -> Skip (InterposeSuffixSecond s1)
726 step _ (InterposeSuffixSecond s1) = do
728 return $ Yield r (InterposeSuffixFirst s1)
730{-# ANN type InterposeState Fuse #-}
731data InterposeState s1 i1 a =
733 -- | InterposeFirstYield s1 i1
734 | InterposeFirstInner s1 i1
735 | InterposeFirstInject s1
736 -- | InterposeFirstBuf s1 i1
737 | InterposeSecondYield s1 i1
738 -- -- | InterposeSecondYield s1 i1 a
739 -- -- | InterposeFirstResume s1 i1 a
741-- Note that this only interposes the pure values, we may run many effects to
742-- generate those values as some effects may not generate anything (Skip).
743{-# INLINE_NORMAL interpose #-}
744interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
747 (Unfold istep1 inject1) (Stream step1 state1) =
748 Stream step (InterposeFirst state1)
752 {-# INLINE_LATE step #-}
753 step gst (InterposeFirst s1) = do
754 r <- step1 (adaptState gst) s1
758 i `seq` return (Skip (InterposeFirstInner s i))
759 -- i `seq` return (Skip (InterposeFirstYield s i))
760 Skip s -> return $ Skip (InterposeFirst s)
764 step _ (InterposeFirstYield s1 i1) = do
767 Yield x i' -> Yield x (InterposeFirstInner s1 i')
768 Skip i' -> Skip (InterposeFirstYield s1 i')
769 Stop -> Skip (InterposeFirst s1)
772 step _ (InterposeFirstInner s1 i1) = do
775 Yield x i' -> Yield x (InterposeFirstInner s1 i')
776 Skip i' -> Skip (InterposeFirstInner s1 i')
777 Stop -> Skip (InterposeFirstInject s1)
779 step gst (InterposeFirstInject s1) = do
780 r <- step1 (adaptState gst) s1
784 -- i `seq` return (Skip (InterposeFirstBuf s i))
785 i `seq` return (Skip (InterposeSecondYield s i))
786 Skip s -> return $ Skip (InterposeFirstInject s)
790 step _ (InterposeFirstBuf s1 i1) = do
793 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
794 Skip i' -> Skip (InterposeFirstBuf s1 i')
799 step _ (InterposeSecondYield s1 i1 v) = do
801 return $ Yield r (InterposeFirstResume s1 i1 v)
803 step _ (InterposeSecondYield s1 i1) = do
805 return $ Yield r (InterposeFirstInner s1 i1)
808 step _ (InterposeFirstResume s1 i1 v) = do
809 return $ Yield v (InterposeFirstInner s1 i1)
812------------------------------------------------------------------------------
813-- Combine N Streams - intercalate
814------------------------------------------------------------------------------
816data ICUState s1 s2 i1 i2 =
821 | ICUFirstInner s1 s2 i1
822 | ICUSecondInner s1 s2 i2
823 | ICUFirstOnlyInner s1 i1
824 | ICUSecondOnlyInner s2 i2
826-- | Interleave streams (full streams, not the elements) unfolded from two
827-- input streams and concat. Stop when the first stream stops. If the second
828-- stream ends before the first one then first stream still keeps running alone
829-- without any interleaving with the second stream.
831-- [a1, a2, ... an] [b1, b2 ...]
832-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
833-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
834-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
836{-# INLINE_NORMAL gintercalateSuffix #-}
839 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
841 (Unfold istep1 inject1) (Stream step1 state1)
842 (Unfold istep2 inject2) (Stream step2 state2) =
843 Stream step (ICUFirst state1 state2)
847 {-# INLINE_LATE step #-}
848 step gst (ICUFirst s1 s2) = do
849 r <- step1 (adaptState gst) s1
853 i `seq` return (Skip (ICUFirstInner s s2 i))
854 Skip s -> return $ Skip (ICUFirst s s2)
857 step gst (ICUFirstOnly s1) = do
858 r <- step1 (adaptState gst) s1
862 i `seq` return (Skip (ICUFirstOnlyInner s i))
863 Skip s -> return $ Skip (ICUFirstOnly s)
866 step _ (ICUFirstInner s1 s2 i1) = do
869 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
870 Skip i' -> Skip (ICUFirstInner s1 s2 i')
871 Stop -> Skip (ICUSecond s1 s2)
873 step _ (ICUFirstOnlyInner s1 i1) = do
876 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
877 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
878 Stop -> Skip (ICUFirstOnly s1)
880 step gst (ICUSecond s1 s2) = do
881 r <- step2 (adaptState gst) s2
885 i `seq` return (Skip (ICUSecondInner s1 s i))
886 Skip s -> return $ Skip (ICUSecond s1 s)
887 Stop -> return $ Skip (ICUFirstOnly s1)
889 step _ (ICUSecondInner s1 s2 i2) = do
892 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
893 Skip i' -> Skip (ICUSecondInner s1 s2 i')
894 Stop -> Skip (ICUFirst s1 s2)
896 step _ (ICUSecondOnly _s2) = undefined
897 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
899data ICALState s1 s2 i1 i2 a =
901 -- | ICALFirstYield s1 s2 i1
902 | ICALFirstInner s1 s2 i1
904 | ICALFirstOnlyInner s1 i1
905 | ICALSecondInject s1 s2
906 | ICALFirstInject s1 s2 i2
907 -- | ICALFirstBuf s1 s2 i1 i2
908 | ICALSecondInner s1 s2 i1 i2
909 -- -- | ICALSecondInner s1 s2 i1 i2 a
910 -- -- | ICALFirstResume s1 s2 i1 i2 a
912-- | Interleave streams (full streams, not the elements) unfolded from two
913-- input streams and concat. Stop when the first stream stops. If the second
914-- stream ends before the first one then first stream still keeps running alone
915-- without any interleaving with the second stream.
917-- [a1, a2, ... an] [b1, b2 ...]
918-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
919-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
920-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
922{-# INLINE_NORMAL gintercalate #-}
925 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
927 (Unfold istep1 inject1) (Stream step1 state1)
928 (Unfold istep2 inject2) (Stream step2 state2) =
929 Stream step (ICALFirst state1 state2)
933 {-# INLINE_LATE step #-}
934 step gst (ICALFirst s1 s2) = do
935 r <- step1 (adaptState gst) s1
939 i `seq` return (Skip (ICALFirstInner s s2 i))
940 -- i `seq` return (Skip (ICALFirstYield s s2 i))
941 Skip s -> return $ Skip (ICALFirst s s2)
945 step _ (ICALFirstYield s1 s2 i1) = do
948 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
949 Skip i' -> Skip (ICALFirstYield s1 s2 i')
950 Stop -> Skip (ICALFirst s1 s2)
953 step _ (ICALFirstInner s1 s2 i1) = do
956 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
957 Skip i' -> Skip (ICALFirstInner s1 s2 i')
958 Stop -> Skip (ICALSecondInject s1 s2)
960 step gst (ICALFirstOnly s1) = do
961 r <- step1 (adaptState gst) s1
965 i `seq` return (Skip (ICALFirstOnlyInner s i))
966 Skip s -> return $ Skip (ICALFirstOnly s)
969 step _ (ICALFirstOnlyInner s1 i1) = do
972 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
973 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
974 Stop -> Skip (ICALFirstOnly s1)
976 -- We inject the second stream even before checking if the first stream
977 -- would yield any more elements. There is no clear choice whether we
978 -- should do this before or after that. Doing it after may make the state
979 -- machine a bit simpler though.
980 step gst (ICALSecondInject s1 s2) = do
981 r <- step2 (adaptState gst) s2
985 i `seq` return (Skip (ICALFirstInject s1 s i))
986 Skip s -> return $ Skip (ICALSecondInject s1 s)
987 Stop -> return $ Skip (ICALFirstOnly s1)
989 step gst (ICALFirstInject s1 s2 i2) = do
990 r <- step1 (adaptState gst) s1
994 i `seq` return (Skip (ICALSecondInner s s2 i i2))
995 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
996 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
1000 step _ (ICALFirstBuf s1 s2 i1 i2) = do
1003 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
1004 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
1007 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
1010 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
1011 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
1012 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
1015 step _ (ICALSecondInner s1 s2 i1 i2) = do
1018 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
1019 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
1020 Stop -> Skip (ICALFirstInner s1 s2 i1)
1021 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
1024 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
1025 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
1028------------------------------------------------------------------------------
1030------------------------------------------------------------------------------
1032{-# ANN type FIterState Fuse #-}
1033data FIterState s f m a b
1035 | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
1036 | FIterYield b (FIterState s f m a b)
1039{-# INLINE_NORMAL foldIterateM #-}
1041 Monad m => (b -> m (FL.Fold m a b)) -> m b -> Stream m a -> Stream m b
1042foldIterateM func seed0 (Stream step state) =
1043 Stream stepOuter (FIterInit state seed0)
1047 {-# INLINE iterStep #-}
1048 iterStep from st fstep extract = do
1053 FL.Partial fs -> FIterStream st fstep fs extract
1054 FL.Done fb -> FIterYield fb $ FIterInit st (return fb)
1056 {-# INLINE_LATE stepOuter #-}
1057 stepOuter _ (FIterInit st seed) = do
1058 (FL.Fold fstep initial extract) <- seed >>= func
1059 iterStep initial st fstep extract
1060 stepOuter gst (FIterStream st fstep fs extract) = do
1061 r <- step (adaptState gst) st
1064 iterStep (fstep fs x) s fstep extract
1065 Skip s -> return $ Skip $ FIterStream s fstep fs extract
1068 return $ Skip $ FIterYield b FIterStop
1069 stepOuter _ (FIterYield a next) = return $ Yield a next
1070 stepOuter _ FIterStop = return Stop
1072{-# ANN type CIterState Fuse #-}
1073data CIterState s f fs b
1076 | CIterYield b (CIterState s f fs b)
1079-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
1080-- much more efficient due to stream fusion.
1083{-# INLINE_NORMAL refoldIterateM #-}
1085 Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
1086refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
1087 Stream stepOuter (CIterInit state initial)
1091 {-# INLINE iterStep #-}
1092 iterStep st action = do
1097 FL.Partial fs -> CIterConsume st fs
1098 FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
1100 {-# INLINE_LATE stepOuter #-}
1101 stepOuter _ (CIterInit st action) = do
1102 iterStep st (action >>= finject)
1103 stepOuter gst (CIterConsume st fs) = do
1104 r <- step (adaptState gst) st
1106 Yield x s -> iterStep s (fstep fs x)
1107 Skip s -> return $ Skip $ CIterConsume s fs
1110 return $ Skip $ CIterYield b CIterStop
1111 stepOuter _ (CIterYield a next) = return $ Yield a next
1112 stepOuter _ CIterStop = return Stop
1114-- "n" elements at the end are dropped by the fold.
1115{-# INLINE sliceBy #-}
1116sliceBy :: Monad m => Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
1117sliceBy (Fold step1 initial1 extract1) n = Refold step inject extract
1121 inject (i, len) = do
1124 Partial s -> Partial $ Tuple' (i + len + n) s
1125 Done l -> Done (i, l)
1127 step (Tuple' i s) x = do
1130 Partial s1 -> Partial $ Tuple' i s1
1131 Done len -> Done (i, len)
1133 extract (Tuple' i s) = (i,) <$> extract1 s
1135{-# INLINE sliceOnSuffix #-}
1136sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1137sliceOnSuffix predicate =
1138 -- Scan the stream with the given refold
1140 (sliceBy (FL.takeEndBy_ predicate FL.length) 1)
1143------------------------------------------------------------------------------
1145------------------------------------------------------------------------------
1147{-# ANN type ParseChunksState Fuse #-}
1148data ParseChunksState x inpBuf st pst =
1149 ParseChunksInit inpBuf st
1150 | ParseChunksInitLeftOver inpBuf
1151 | ParseChunksStream st inpBuf !pst
1152 | ParseChunksBuf inpBuf st inpBuf !pst
1153 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1155-- XXX This is in fact parseMany1 (a la foldMany1). Do we need a parseMany as
1157{-# INLINE_NORMAL parseMany #-}
1163parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1164 Stream stepOuter (ParseChunksInit [] state)
1168 {-# INLINE_LATE stepOuter #-}
1169 -- Buffer is empty, get the first element from the stream, initialize the
1170 -- fold and then go to stream processing loop.
1171 stepOuter gst (ParseChunksInit [] st) = do
1172 r <- step (adaptState gst) st
1178 return $ Skip $ ParseChunksBuf [x] s [] ps
1180 let next = ParseChunksInit [x] s
1181 in return $ Skip $ ParseChunksYield pb next
1182 PRD.IError err -> throwM $ ParseError err
1183 Skip s -> return $ Skip $ ParseChunksInit [] s
1186 -- Buffer is not empty, go to buffered processing loop
1187 stepOuter _ (ParseChunksInit src st) = do
1191 return $ Skip $ ParseChunksBuf src st [] ps
1193 let next = ParseChunksInit src st
1194 in return $ Skip $ ParseChunksYield pb next
1195 PRD.IError err -> throwM $ ParseError err
1197 -- XXX we just discard any leftover input at the end
1198 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1200 -- Buffer is empty, process elements from the stream
1201 stepOuter gst (ParseChunksStream st buf pst) = do
1202 r <- step (adaptState gst) st
1207 PR.Partial 0 pst1 ->
1208 return $ Skip $ ParseChunksStream s [] pst1
1209 PR.Partial n pst1 -> do
1210 assert (n <= length (x:buf)) (return ())
1211 let src0 = Prelude.take n (x:buf)
1212 src = Prelude.reverse src0
1213 return $ Skip $ ParseChunksBuf src s [] pst1
1214 PR.Continue 0 pst1 ->
1215 return $ Skip $ ParseChunksStream s (x:buf) pst1
1216 PR.Continue n pst1 -> do
1217 assert (n <= length (x:buf)) (return ())
1218 let (src0, buf1) = splitAt n (x:buf)
1219 src = Prelude.reverse src0
1220 return $ Skip $ ParseChunksBuf src s buf1 pst1
1223 ParseChunksYield b (ParseChunksInit [] s)
1225 assert (n <= length (x:buf)) (return ())
1226 let src = Prelude.reverse (Prelude.take n (x:buf))
1228 ParseChunksYield b (ParseChunksInit src s)
1229 PR.Error err -> throwM $ ParseError err
1230 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1233 let src = Prelude.reverse buf
1235 ParseChunksYield b (ParseChunksInitLeftOver src)
1237 -- go back to stream processing mode
1238 stepOuter _ (ParseChunksBuf [] s buf pst) =
1239 return $ Skip $ ParseChunksStream s buf pst
1241 -- buffered processing loop
1242 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1245 PR.Partial 0 pst1 ->
1246 return $ Skip $ ParseChunksBuf xs s [] pst1
1247 PR.Partial n pst1 -> do
1248 assert (n <= length (x:buf)) (return ())
1249 let src0 = Prelude.take n (x:buf)
1250 src = Prelude.reverse src0 ++ xs
1251 return $ Skip $ ParseChunksBuf src s [] pst1
1252 PR.Continue 0 pst1 ->
1253 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1254 PR.Continue n pst1 -> do
1255 assert (n <= length (x:buf)) (return ())
1256 let (src0, buf1) = splitAt n (x:buf)
1257 src = Prelude.reverse src0 ++ xs
1258 return $ Skip $ ParseChunksBuf src s buf1 pst1
1260 return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1262 assert (n <= length (x:buf)) (return ())
1263 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1264 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1265 PR.Error err -> throwM $ ParseError err
1267 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1269{-# ANN type ConcatParseState Fuse #-}
1270data ConcatParseState b inpBuf st p m a =
1271 ConcatParseInit inpBuf st p
1272 | ConcatParseInitLeftOver inpBuf
1273 | forall s. ConcatParseStream st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1274 | forall s. ConcatParseBuf inpBuf st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1275 | ConcatParseYield b (ConcatParseState b inpBuf st p m a)
1277{-# INLINE_NORMAL parseIterate #-}
1280 => (b -> PRD.Parser m a b)
1284parseIterate func seed (Stream step state) =
1285 Stream stepOuter (ConcatParseInit [] state (func seed))
1289 {-# INLINE_LATE stepOuter #-}
1290 -- Buffer is empty, go to stream processing loop
1291 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1295 return $ Skip $ ConcatParseStream st [] pstep ps extract
1297 let next = ConcatParseInit [] st (func pb)
1298 in return $ Skip $ ConcatParseYield pb next
1299 PRD.IError err -> throwM $ ParseError err
1301 -- Buffer is not empty, go to buffered processing loop
1302 stepOuter _ (ConcatParseInit src st
1303 (PRD.Parser pstep initial extract)) = do
1307 return $ Skip $ ConcatParseBuf src st [] pstep ps extract
1309 let next = ConcatParseInit src st (func pb)
1310 in return $ Skip $ ConcatParseYield pb next
1311 PRD.IError err -> throwM $ ParseError err
1313 -- XXX we just discard any leftover input at the end
1314 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1316 -- Buffer is empty process elements from the stream
1317 stepOuter gst (ConcatParseStream st buf pstep pst extract) = do
1318 r <- step (adaptState gst) st
1323 PR.Partial 0 pst1 ->
1324 return $ Skip $ ConcatParseStream s [] pstep pst1 extract
1325 PR.Partial n pst1 -> do
1326 assert (n <= length (x:buf)) (return ())
1327 let src0 = Prelude.take n (x:buf)
1328 src = Prelude.reverse src0
1329 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1330 -- PR.Continue 0 pst1 ->
1331 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1332 PR.Continue n pst1 -> do
1333 assert (n <= length (x:buf)) (return ())
1334 let (src0, buf1) = splitAt n (x:buf)
1335 src = Prelude.reverse src0
1336 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1337 -- XXX Specialize for Stop 0 common case?
1339 assert (n <= length (x:buf)) (return ())
1340 let src = Prelude.reverse (Prelude.take n (x:buf))
1342 ConcatParseYield b (ConcatParseInit src s (func b))
1343 PR.Error err -> throwM $ ParseError err
1344 Skip s -> return $ Skip $ ConcatParseStream s buf pstep pst extract
1347 let src = Prelude.reverse buf
1348 return $ Skip $ ConcatParseYield b (ConcatParseInitLeftOver src)
1350 -- go back to stream processing mode
1351 stepOuter _ (ConcatParseBuf [] s buf pstep ps extract) =
1352 return $ Skip $ ConcatParseStream s buf pstep ps extract
1354 -- buffered processing loop
1355 stepOuter _ (ConcatParseBuf (x:xs) s buf pstep pst extract) = do
1358 PR.Partial 0 pst1 ->
1359 return $ Skip $ ConcatParseBuf xs s [] pstep pst1 extract
1360 PR.Partial n pst1 -> do
1361 assert (n <= length (x:buf)) (return ())
1362 let src0 = Prelude.take n (x:buf)
1363 src = Prelude.reverse src0 ++ xs
1364 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1365 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1366 PR.Continue n pst1 -> do
1367 assert (n <= length (x:buf)) (return ())
1368 let (src0, buf1) = splitAt n (x:buf)
1369 src = Prelude.reverse src0 ++ xs
1370 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1371 -- XXX Specialize for Stop 0 common case?
1373 assert (n <= length (x:buf)) (return ())
1374 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1375 return $ Skip $ ConcatParseYield b
1376 (ConcatParseInit src s (func b))
1377 PR.Error err -> throwM $ ParseError err
1379 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1381------------------------------------------------------------------------------
1383------------------------------------------------------------------------------
1385data GroupByState st fs a b
1388 | GroupingInitWith st !a
1389 | GroupingDoWith st !fs !a
1390 | GroupingYield !b (GroupByState st fs a b)
1393{-# INLINE_NORMAL groupsBy #-}
1400groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1402groupsBy cmp (Fold fstep initial done) (Stream step state) =
1403 Stream stepOuter (GroupingInit state)
1407 {-# INLINE_LATE stepOuter #-}
1408 stepOuter _ (GroupingInit st) = do
1409 -- XXX Note that if the stream stops without yielding a single element
1410 -- in the group we discard the "initial" effect.
1414 FL.Partial s -> Skip $ GroupingDo st s
1415 FL.Done b -> Yield b $ GroupingInit st
1416 stepOuter gst (GroupingDo st fs) = do
1417 res <- step (adaptState gst) st
1422 FL.Partial fs1 -> go SPEC x s fs1
1423 FL.Done b -> return $ Yield b (GroupingInit s)
1424 Skip s -> return $ Skip $ GroupingDo s fs
1429 go !_ prev stt !acc = do
1430 res <- step (adaptState gst) stt
1437 FL.Partial fs1 -> go SPEC prev s fs1
1438 FL.Done b -> return $ Yield b (GroupingInit s)
1441 return $ Yield r (GroupingInitWith s x)
1442 Skip s -> go SPEC prev s acc
1443 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1444 stepOuter _ (GroupingInitWith st x) = do
1448 FL.Partial s -> Skip $ GroupingDoWith st s x
1449 FL.Done b -> Yield b $ GroupingInitWith st x
1450 stepOuter gst (GroupingDoWith st fs prev) = do
1451 res <- fstep fs prev
1453 FL.Partial fs1 -> go SPEC st fs1
1454 FL.Done b -> return $ Yield b (GroupingInit st)
1458 -- XXX code duplicated from the previous equation
1460 res <- step (adaptState gst) stt
1467 FL.Partial fs1 -> go SPEC s fs1
1468 FL.Done b -> return $ Yield b (GroupingInit s)
1471 return $ Yield r (GroupingInitWith s x)
1472 Skip s -> go SPEC s acc
1473 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1474 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1475 stepOuter _ GroupingDone = return Stop
1477{-# INLINE_NORMAL groupsRollingBy #-}
1478groupsRollingBy :: Monad m
1484groupsRollingBy eq fld = parseMany (PRD.groupByRolling eq fld)
1486groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
1487 Stream stepOuter (GroupingInit state)
1491 {-# INLINE_LATE stepOuter #-}
1492 stepOuter _ (GroupingInit st) = do
1493 -- XXX Note that if the stream stops without yielding a single element
1494 -- in the group we discard the "initial" effect.
1498 FL.Partial fs -> Skip $ GroupingDo st fs
1499 FL.Done fb -> Yield fb $ GroupingInit st
1500 stepOuter gst (GroupingDo st fs) = do
1501 res <- step (adaptState gst) st
1506 FL.Partial fs1 -> go SPEC x s fs1
1507 FL.Done fb -> return $ Yield fb (GroupingInit s)
1508 Skip s -> return $ Skip $ GroupingDo s fs
1513 go !_ prev stt !acc = do
1514 res <- step (adaptState gst) stt
1521 FL.Partial fs1 -> go SPEC x s fs1
1522 FL.Done b -> return $ Yield b (GroupingInit s)
1525 return $ Yield r (GroupingInitWith s x)
1526 Skip s -> go SPEC prev s acc
1527 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1528 stepOuter _ (GroupingInitWith st x) = do
1532 FL.Partial s -> Skip $ GroupingDoWith st s x
1533 FL.Done b -> Yield b $ GroupingInitWith st x
1534 stepOuter gst (GroupingDoWith st fs previous) = do
1535 res <- fstep fs previous
1537 FL.Partial s -> go SPEC previous st s
1538 FL.Done b -> return $ Yield b (GroupingInit st)
1542 -- XXX GHC: groupsBy has one less parameter in this go loop and it
1543 -- fuses. However, groupsRollingBy does not fuse, removing the prev
1544 -- parameter makes it fuse. Something needs to be fixed in GHC. The
1545 -- workaround for this is noted in the comments below.
1546 go !_ prev !stt !acc = do
1547 res <- step (adaptState gst) stt
1554 FL.Partial fs1 -> go SPEC x s fs1
1555 FL.Done b -> return $ Yield b (GroupingInit st)
1559 return $ Yield r (GroupingInitWith s x)
1561 -- The code above does not let groupBy fuse. We use the
1562 -- alternative code below instead. Instead of jumping
1563 -- to GroupingInitWith state, we unroll the code of
1564 -- GroupingInitWith state here to help GHC with stream
1571 FL.Partial fsi -> GroupingDoWith s fsi x
1572 FL.Done b -> GroupingYield b (GroupingInit s)
1573 Skip s -> go SPEC prev s acc
1574 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1575 stepOuter _ (GroupingYield r next) = return $ Yield r next
1576 stepOuter _ GroupingDone = return Stop
1578------------------------------------------------------------------------------
1579-- Splitting - by a predicate
1580------------------------------------------------------------------------------
1582data WordsByState st fs b
1586 | WordsByYield !b (WordsByState st fs b)
1588{-# INLINE_NORMAL wordsBy #-}
1589wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1590wordsBy predicate (Fold fstep initial done) (Stream step state) =
1591 Stream stepOuter (WordsByInit state)
1595 {-# INLINE_LATE stepOuter #-}
1596 stepOuter _ (WordsByInit st) = do
1600 FL.Partial s -> Skip $ WordsByDo st s
1601 FL.Done b -> Yield b (WordsByInit st)
1603 stepOuter gst (WordsByDo st fs) = do
1604 res <- step (adaptState gst) st
1612 FL.Partial fs1 -> Skip $ WordsByDo s fs1
1613 FL.Done b -> Yield b (WordsByInit s)
1617 FL.Partial fs1 -> go SPEC s fs1
1618 FL.Done b -> return $ Yield b (WordsByInit s)
1619 Skip s -> return $ Skip $ WordsByDo s fs
1625 res <- step (adaptState gst) stt
1632 return $ Yield r (WordsByInit s)
1634 -- The above code does not fuse well. Need to check why
1635 -- GHC is not able to simplify it well. Using the code
1636 -- below, instead of jumping through the WordsByInit
1637 -- state always, we directly go to WordsByDo state in
1638 -- the common case of Partial.
1644 FL.Partial fs1 -> WordsByDo s fs1
1645 FL.Done b -> WordsByYield b (WordsByInit s)
1649 FL.Partial fs1 -> go SPEC s fs1
1650 FL.Done b -> return $ Yield b (WordsByInit s)
1651 Skip s -> go SPEC s acc
1652 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
1654 stepOuter _ WordsByDone = return Stop
1656 stepOuter _ (WordsByYield b next) = return $ Yield b next
1658------------------------------------------------------------------------------
1659-- Splitting on a sequence
1660------------------------------------------------------------------------------
1662-- String search algorithms:
1663-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1666-- TODO can we unify the splitting operations using a splitting configuration
1667-- like in the split package.
1669data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1670data SplitOptions = SplitOptions
1671 { style :: SplitStyle
1672 , withSep :: Bool -- ^ keep the separators in output
1673 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1674 -- , trimHead :: Bool -- ^ drop blank at head
1675 -- , trimTail :: Bool -- ^ drop blank at tail
1679-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
1680-- because we can use the constructor directly without having to create "jump"
1682{-# ANN type SplitOnSeqState Fuse #-}
1683data SplitOnSeqState rb rh ck w fs s b x =
1685 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1688 | SplitOnSeqEmpty !fs s
1690 | SplitOnSeqSingle !fs s x
1692 | SplitOnSeqWordInit !fs s
1693 | SplitOnSeqWordLoop !w s !fs
1694 | SplitOnSeqWordDone Int !fs !w
1696 | SplitOnSeqKRInit Int !fs s rb !rh
1697 | SplitOnSeqKRLoop fs s rb !rh !ck
1698 | SplitOnSeqKRCheck fs s rb !rh
1699 | SplitOnSeqKRDone Int !fs rb !rh
1701 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
1703{-# INLINE_NORMAL splitOnSeq #-}
1705 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1710splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1711 Stream stepOuter SplitOnSeqInit
1715 patLen = A.length patArr
1716 maxIndex = patLen - 1
1717 elemBits = SIZE_OF(a) * 8
1719 -- For word pattern case
1721 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1724 elemMask = (1 `shiftL` elemBits) - 1
1727 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1729 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1731 -- For Rabin-Karp search
1732 k = 2891336453 :: Word32
1735 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1737 deltaCksum cksum old new =
1738 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1740 -- XXX shall we use a random starting hash or 1 instead of 0?
1741 patHash = A.foldl' addCksum 0 patArr
1743 skip = return . Skip
1745 nextAfterInit nextGen stepRes =
1747 FL.Partial s -> nextGen s
1748 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
1750 {-# INLINE yieldProceed #-}
1751 yieldProceed nextGen fs =
1752 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
1754 {-# INLINE_LATE stepOuter #-}
1755 stepOuter _ SplitOnSeqInit = do
1760 then return $ Skip $ SplitOnSeqEmpty acc state
1763 pat <- liftIO $ A.unsafeIndexIO 0 patArr
1764 return $ Skip $ SplitOnSeqSingle acc state pat
1765 else if SIZE_OF(a) * patLen
1766 <= sizeOf (undefined :: Word)
1767 then return $ Skip $ SplitOnSeqWordInit acc state
1769 (rb, rhead) <- liftIO $ RB.new patLen
1770 skip $ SplitOnSeqKRInit 0 acc state rb rhead
1771 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
1773 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1775 ---------------------------
1777 ---------------------------
1779 stepOuter _ (SplitOnSeqReinit nextGen) =
1780 initial >>= skip . nextAfterInit nextGen
1782 ---------------------------
1784 ---------------------------
1786 stepOuter gst (SplitOnSeqEmpty acc st) = do
1787 res <- step (adaptState gst) st
1793 FL.Partial acc1 -> done acc1
1794 FL.Done b -> return b
1795 let jump c = SplitOnSeqEmpty c s
1796 in yieldProceed jump b1
1797 Skip s -> skip (SplitOnSeqEmpty acc s)
1804 stepOuter _ SplitOnSeqDone = return Stop
1810 stepOuter gst (SplitOnSeqSingle fs st pat) = do
1811 res <- step (adaptState gst) st
1814 let jump c = SplitOnSeqSingle c s pat
1816 then done fs >>= yieldProceed jump
1820 FL.Partial fs1 -> skip $ jump fs1
1821 FL.Done b -> yieldProceed jump b
1822 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1825 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1827 ---------------------------
1828 -- Short Pattern - Shift Or
1829 ---------------------------
1831 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1833 skip $ SplitOnSeqYield r SplitOnSeqDone
1834 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1835 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1836 r <- fstep fs (toEnum $ fromIntegral old)
1838 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1840 let jump c = SplitOnSeqWordDone (n - 1) c wrd
1843 stepOuter gst (SplitOnSeqWordInit fs st0) =
1849 go !_ !idx !wrd !st = do
1850 res <- step (adaptState gst) st
1853 let wrd1 = addToWord wrd x
1856 if wrd1 .&. wordMask == wordPat
1858 let jump c = SplitOnSeqWordInit c s
1859 done fs >>= yieldProceed jump
1860 else skip $ SplitOnSeqWordLoop wrd1 s fs
1861 else go SPEC (idx + 1) wrd1 s
1862 Skip s -> go SPEC idx wrd s
1865 then skip $ SplitOnSeqWordDone idx fs wrd
1868 skip $ SplitOnSeqYield r SplitOnSeqDone
1870 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1871 go SPEC wrd0 st0 fs0
1876 go !_ !wrd !st !fs = do
1877 res <- step (adaptState gst) st
1880 let jump c = SplitOnSeqWordInit c s
1881 wrd1 = addToWord wrd x
1882 old = (wordMask .&. wrd)
1883 `shiftR` (elemBits * (patLen - 1))
1884 r <- fstep fs (toEnum $ fromIntegral old)
1886 FL.Partial fs1 -> do
1887 if wrd1 .&. wordMask == wordPat
1888 then done fs1 >>= yieldProceed jump
1889 else go SPEC wrd1 s fs1
1890 FL.Done b -> yieldProceed jump b
1891 Skip s -> go SPEC wrd s fs
1892 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1894 -------------------------------
1895 -- General Pattern - Karp Rabin
1896 -------------------------------
1898 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
1899 res <- step (adaptState gst) st
1902 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1905 let fld = RB.unsafeFoldRing (RB.ringBound rb)
1906 let !ringHash = fld addCksum 0 rb
1907 if ringHash == patHash
1908 then skip $ SplitOnSeqKRCheck fs s rb rh1
1909 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1910 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
1911 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
1913 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1915 -- XXX The recursive "go" is more efficient than the state based recursion
1916 -- code commented out below. Perhaps its more efficient because of
1917 -- factoring out "rb" outside the loop.
1919 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1920 go SPEC fs0 st0 rh0 cksum0
1924 go !_ !fs !st !rh !cksum = do
1925 res <- step (adaptState gst) st
1928 old <- liftIO $ peek rh
1929 let cksum1 = deltaCksum cksum old x
1932 FL.Partial fs1 -> do
1933 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1934 if cksum1 == patHash
1935 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1936 else go SPEC fs1 s rh1 cksum1
1938 let rst = RB.startOf rb
1939 jump c = SplitOnSeqKRInit 0 c s rb rst
1941 Skip s -> go SPEC fs s rh cksum
1942 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1944 -- XXX The following code is 5 times slower compared to the recursive loop
1945 -- based code above. Need to investigate why. One possibility is that the
1946 -- go loop above does not thread around the ring buffer (rb). This code may
1947 -- be causing the state to bloat and getting allocated on each iteration.
1948 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1949 -- such problem is needed. One way to avoid this could be to use unboxed
1952 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1953 res <- step (adaptState gst) st
1956 old <- liftIO $ peek rh
1957 let cksum1 = deltaCksum cksum old x
1959 if (cksum1 == patHash)
1962 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1964 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1965 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1966 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1967 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1970 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1971 if RB.unsafeEqArray rb rh patArr
1974 let rst = RB.startOf rb
1975 jump c = SplitOnSeqKRInit 0 c st rb rst
1977 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1979 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1981 skip $ SplitOnSeqYield r SplitOnSeqDone
1982 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1983 old <- liftIO $ peek rh
1984 let rh1 = RB.advance rb rh
1987 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
1989 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
1992{-# ANN type SplitOnSuffixSeqState Fuse #-}
1993data SplitOnSuffixSeqState rb rh ck w fs s b x =
1994 SplitOnSuffixSeqInit
1995 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
1996 | SplitOnSuffixSeqDone
1998 | SplitOnSuffixSeqEmpty !fs s
2000 | SplitOnSuffixSeqSingleInit !fs s x
2001 | SplitOnSuffixSeqSingle !fs s x
2003 | SplitOnSuffixSeqWordInit !fs s
2004 | SplitOnSuffixSeqWordLoop !w s !fs
2005 | SplitOnSuffixSeqWordDone Int !fs !w
2007 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
2008 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
2009 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
2010 | SplitOnSuffixSeqKRCheck fs s rb !rh
2011 | SplitOnSuffixSeqKRDone Int !fs rb !rh
2013 | SplitOnSuffixSeqReinit
2014 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
2016{-# INLINE_NORMAL splitOnSuffixSeq #-}
2018 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
2024splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2025 Stream stepOuter SplitOnSuffixSeqInit
2029 patLen = A.length patArr
2030 maxIndex = patLen - 1
2031 elemBits = SIZE_OF(a) * 8
2033 -- For word pattern case
2035 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2038 elemMask = (1 `shiftL` elemBits) - 1
2041 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2043 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2045 nextAfterInit nextGen stepRes =
2047 FL.Partial s -> nextGen s
2049 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
2051 {-# INLINE yieldProceed #-}
2052 yieldProceed nextGen fs =
2053 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
2055 -- For single element pattern case
2056 {-# INLINE processYieldSingle #-}
2057 processYieldSingle pat x s fs = do
2058 let jump c = SplitOnSuffixSeqSingleInit c s pat
2061 r <- if withSep then fstep fs x else return $ FL.Partial fs
2064 FL.Partial fs1 -> done fs1
2065 FL.Done b -> return b
2066 yieldProceed jump b1
2070 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2071 FL.Done b -> yieldProceed jump b
2073 -- For Rabin-Karp search
2074 k = 2891336453 :: Word32
2077 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2079 deltaCksum cksum old new =
2080 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2082 -- XXX shall we use a random starting hash or 1 instead of 0?
2083 patHash = A.foldl' addCksum 0 patArr
2085 skip = return . Skip
2087 {-# INLINE_LATE stepOuter #-}
2088 stepOuter _ SplitOnSuffixSeqInit = do
2093 then skip $ SplitOnSuffixSeqEmpty fs state
2096 pat <- liftIO $ A.unsafeIndexIO 0 patArr
2097 skip $ SplitOnSuffixSeqSingleInit fs state pat
2098 else if SIZE_OF(a) * patLen
2099 <= sizeOf (undefined :: Word)
2100 then skip $ SplitOnSuffixSeqWordInit fs state
2102 (rb, rhead) <- liftIO $ RB.new patLen
2103 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
2104 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
2106 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
2108 ---------------------------
2110 ---------------------------
2112 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
2113 initial >>= skip . nextAfterInit nextGen
2115 ---------------------------
2117 ---------------------------
2119 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
2120 res <- step (adaptState gst) st
2123 let jump c = SplitOnSuffixSeqEmpty c s
2127 FL.Partial fs -> done fs
2128 FL.Done b -> return b
2129 yieldProceed jump b1
2130 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
2137 stepOuter _ SplitOnSuffixSeqDone = return Stop
2143 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
2144 res <- step (adaptState gst) st
2146 Yield x s -> processYieldSingle pat x s fs
2147 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
2150 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2151 res <- step (adaptState gst) st
2153 Yield x s -> processYieldSingle pat x s fs
2154 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2157 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2159 ---------------------------
2160 -- Short Pattern - Shift Or
2161 ---------------------------
2163 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2165 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2166 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2167 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2168 r <- fstep fs (toEnum $ fromIntegral old)
2170 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2172 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
2175 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
2176 res <- step (adaptState gst) st0
2179 let wrd = addToWord 0 x
2180 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
2182 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2184 let jump c = SplitOnSuffixSeqWordInit c s
2186 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
2192 go !_ !idx !wrd !st !fs = do
2193 res <- step (adaptState gst) st
2196 let jump c = SplitOnSuffixSeqWordInit c s
2197 let wrd1 = addToWord wrd x
2198 r <- if withSep then fstep fs x else return $ FL.Partial fs
2202 then go SPEC (idx + 1) wrd1 s fs1
2203 else if wrd1 .&. wordMask /= wordPat
2204 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2205 else do done fs >>= yieldProceed jump
2206 FL.Done b -> yieldProceed jump b
2207 Skip s -> go SPEC idx wrd s fs
2208 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2210 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2211 go SPEC wrd0 st0 fs0
2216 go !_ !wrd !st !fs = do
2217 res <- step (adaptState gst) st
2220 let jump c = SplitOnSuffixSeqWordInit c s
2221 wrd1 = addToWord wrd x
2222 old = (wordMask .&. wrd)
2223 `shiftR` (elemBits * (patLen - 1))
2227 else fstep fs (toEnum $ fromIntegral old)
2230 if wrd1 .&. wordMask == wordPat
2231 then done fs1 >>= yieldProceed jump
2232 else go SPEC wrd1 s fs1
2233 FL.Done b -> yieldProceed jump b
2234 Skip s -> go SPEC wrd s fs
2236 if wrd .&. wordMask == wordPat
2241 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2242 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2244 -------------------------------
2245 -- General Pattern - Karp Rabin
2246 -------------------------------
2248 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2249 res <- step (adaptState gst) st0
2252 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2253 r <- if withSep then fstep fs x else return $ FL.Partial fs
2256 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2258 let rst = RB.startOf rb
2259 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2261 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2264 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2265 go SPEC 1 rh0 st0 fs0
2269 go !_ !idx !rh st !fs = do
2270 res <- step (adaptState gst) st
2273 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2274 r <- if withSep then fstep fs x else return $ FL.Partial fs
2278 then go SPEC (idx + 1) rh1 s fs1
2280 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2281 !ringHash = fld addCksum 0 rb
2282 in if ringHash == patHash
2283 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2284 else SplitOnSuffixSeqKRLoop
2285 fs1 s rb rh1 ringHash
2287 let rst = RB.startOf rb
2288 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2290 Skip s -> go SPEC idx rh s fs
2292 -- do not issue a blank segment when we end at pattern
2293 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2298 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2299 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2301 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2302 go SPEC fs0 st0 rh0 cksum0
2306 go !_ !fs !st !rh !cksum = do
2307 res <- step (adaptState gst) st
2310 old <- liftIO $ peek rh
2311 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2312 let cksum1 = deltaCksum cksum old x
2313 r <- if withSep then fstep fs x else fstep fs old
2316 if cksum1 /= patHash
2317 then go SPEC fs1 s rh1 cksum1
2318 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2320 let rst = RB.startOf rb
2321 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2323 Skip s -> go SPEC fs s rh cksum
2325 if RB.unsafeEqArray rb rh patArr
2330 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2331 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2333 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2334 if RB.unsafeEqArray rb rh patArr
2337 let rst = RB.startOf rb
2338 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2340 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2342 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2344 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2345 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2346 old <- liftIO $ peek rh
2347 let rh1 = RB.advance rb rh
2350 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2352 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2355------------------------------------------------------------------------------
2356-- Nested Container Transformation
2357------------------------------------------------------------------------------
2359{-# ANN type SplitState Fuse #-}
2360data SplitState s arr
2362 | SplitBuffering s arr
2363 | SplitSplitting s arr
2364 | SplitYielding arr (SplitState s arr)
2367-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2368-- split using a splitBy like combinator. The Fold would consume upto the
2369-- separator and return any leftover which can then be fed to the next fold.
2371-- We can revisit this once we have partial folds/parsers.
2373-- | Performs infix separator style splitting.
2374{-# INLINE_NORMAL splitInnerBy #-}
2377 => (f a -> m (f a, Maybe (f a))) -- splitter
2378 -> (f a -> f a -> m (f a)) -- joiner
2381splitInnerBy splitter joiner (Stream step1 state1) =
2382 Stream step (SplitInitial state1)
2386 {-# INLINE_LATE step #-}
2387 step gst (SplitInitial st) = do
2391 (x1, mx2) <- splitter x
2392 return $ case mx2 of
2393 Nothing -> Skip (SplitBuffering s x1)
2394 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2395 Skip s -> return $ Skip (SplitInitial s)
2398 step gst (SplitBuffering st buf) = do
2402 (x1, mx2) <- splitter x
2403 buf' <- joiner buf x1
2404 return $ case mx2 of
2405 Nothing -> Skip (SplitBuffering s buf')
2406 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2407 Skip s -> return $ Skip (SplitBuffering s buf)
2408 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2410 step _ (SplitSplitting st buf) = do
2411 (x1, mx2) <- splitter buf
2412 return $ case mx2 of
2413 Nothing -> Skip $ SplitBuffering st x1
2414 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2416 step _ (SplitYielding x next) = return $ Yield x next
2417 step _ SplitFinishing = return Stop
2419-- | Performs infix separator style splitting.
2420{-# INLINE_NORMAL splitInnerBySuffix #-}
2422 :: (Monad m, Eq (f a), Monoid (f a))
2423 => (f a -> m (f a, Maybe (f a))) -- splitter
2424 -> (f a -> f a -> m (f a)) -- joiner
2427splitInnerBySuffix splitter joiner (Stream step1 state1) =
2428 Stream step (SplitInitial state1)
2432 {-# INLINE_LATE step #-}
2433 step gst (SplitInitial st) = do
2437 (x1, mx2) <- splitter x
2438 return $ case mx2 of
2439 Nothing -> Skip (SplitBuffering s x1)
2440 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2441 Skip s -> return $ Skip (SplitInitial s)
2444 step gst (SplitBuffering st buf) = do
2448 (x1, mx2) <- splitter x
2449 buf' <- joiner buf x1
2450 return $ case mx2 of
2451 Nothing -> Skip (SplitBuffering s buf')
2452 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2453 Skip s -> return $ Skip (SplitBuffering s buf)
2457 else Skip (SplitYielding buf SplitFinishing)
2459 step _ (SplitSplitting st buf) = do
2460 (x1, mx2) <- splitter buf
2461 return $ case mx2 of
2462 Nothing -> Skip $ SplitBuffering st x1
2463 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2465 step _ (SplitYielding x next) = return $ Yield x next
2466 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