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
149#include "ArrayMacros.h"
151import Control.Exception (assert)
152import Control.Monad.Catch (MonadThrow, throwM)
153import Control.Monad.IO.Class (MonadIO(..))
154import Data.Bits (shiftR, shiftL, (.|.), (.&.))
155#if __GLASGOW_HASKELL__ >= 801
156import Data.Functor.Identity ( Identity )
158import Data.Word (Word32)
159import Foreign.Storable (Storable(..))
160import Fusion.Plugin.Types (Fuse(..))
161import GHC.Types (SPEC(..))
163import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
164import Streamly.Internal.Data.Fold.Step (Step(..))
165import Streamly.Internal.Data.Fold.Type (Fold(..))
166import Streamly.Internal.Data.Parser (ParseError(..))
167import Streamly.Internal.Data.Refold.Type (Refold(..))
168import Streamly.Internal.Data.SVar.Type (adaptState)
169import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
170import Streamly.Internal.Data.Unfold.Type (Unfold(..))
172import qualified Streamly.Internal.Data.Array.Foreign.Type as A
173import qualified Streamly.Internal.Data.Fold as FL
174import qualified Streamly.Internal.Data.Parser as PR
175import qualified Streamly.Internal.Data.Parser.ParserD as PRD
176import qualified Streamly.Internal.Data.Ring.Foreign as RB
178import Streamly.Internal.Data.Stream.StreamD.Type
180import Prelude hiding (concatMap, mapM, zipWith)
182------------------------------------------------------------------------------
184------------------------------------------------------------------------------
186data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
188-- Note that this could be much faster compared to the CPS stream. However, as
189-- the number of streams being composed increases this may become expensive.
190-- Need to see where the breaking point is between the two.
192{-# INLINE_NORMAL append #-}
193append :: Monad m => Stream m a -> Stream m a -> Stream m a
194append (Stream step1 state1) (Stream step2 state2) =
195 Stream step (AppendFirst state1)
199 {-# INLINE_LATE step #-}
200 step gst (AppendFirst st) = do
203 Yield a s -> Yield a (AppendFirst s)
204 Skip s -> Skip (AppendFirst s)
205 Stop -> Skip (AppendSecond state2)
207 step gst (AppendSecond st) = do
210 Yield a s -> Yield a (AppendSecond s)
211 Skip s -> Skip (AppendSecond s)
214------------------------------------------------------------------------------
216------------------------------------------------------------------------------
218data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
219 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
221{-# INLINE_NORMAL interleave #-}
222interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
223interleave (Stream step1 state1) (Stream step2 state2) =
224 Stream step (InterleaveFirst state1 state2)
228 {-# INLINE_LATE step #-}
229 step gst (InterleaveFirst st1 st2) = do
232 Yield a s -> Yield a (InterleaveSecond s st2)
233 Skip s -> Skip (InterleaveFirst s st2)
234 Stop -> Skip (InterleaveSecondOnly st2)
236 step gst (InterleaveSecond st1 st2) = do
239 Yield a s -> Yield a (InterleaveFirst st1 s)
240 Skip s -> Skip (InterleaveSecond st1 s)
241 Stop -> Skip (InterleaveFirstOnly st1)
243 step gst (InterleaveFirstOnly st1) = do
246 Yield a s -> Yield a (InterleaveFirstOnly s)
247 Skip s -> Skip (InterleaveFirstOnly s)
250 step gst (InterleaveSecondOnly st2) = do
253 Yield a s -> Yield a (InterleaveSecondOnly s)
254 Skip s -> Skip (InterleaveSecondOnly s)
257{-# INLINE_NORMAL interleaveMin #-}
258interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
259interleaveMin (Stream step1 state1) (Stream step2 state2) =
260 Stream step (InterleaveFirst state1 state2)
264 {-# INLINE_LATE step #-}
265 step gst (InterleaveFirst st1 st2) = do
268 Yield a s -> Yield a (InterleaveSecond s st2)
269 Skip s -> Skip (InterleaveFirst s st2)
272 step gst (InterleaveSecond st1 st2) = do
275 Yield a s -> Yield a (InterleaveFirst st1 s)
276 Skip s -> Skip (InterleaveSecond st1 s)
279 step _ (InterleaveFirstOnly _) = undefined
280 step _ (InterleaveSecondOnly _) = undefined
282{-# INLINE_NORMAL interleaveSuffix #-}
283interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
284interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
285 Stream step (InterleaveFirst state1 state2)
289 {-# INLINE_LATE step #-}
290 step gst (InterleaveFirst st1 st2) = do
293 Yield a s -> Yield a (InterleaveSecond s st2)
294 Skip s -> Skip (InterleaveFirst s st2)
297 step gst (InterleaveSecond st1 st2) = do
300 Yield a s -> Yield a (InterleaveFirst st1 s)
301 Skip s -> Skip (InterleaveSecond st1 s)
302 Stop -> Skip (InterleaveFirstOnly st1)
304 step gst (InterleaveFirstOnly st1) = do
307 Yield a s -> Yield a (InterleaveFirstOnly s)
308 Skip s -> Skip (InterleaveFirstOnly s)
311 step _ (InterleaveSecondOnly _) = undefined
313data InterleaveInfixState s1 s2 a
314 = InterleaveInfixFirst s1 s2
315 | InterleaveInfixSecondBuf s1 s2
316 | InterleaveInfixSecondYield s1 s2 a
317 | InterleaveInfixFirstYield s1 s2 a
318 | InterleaveInfixFirstOnly s1
320{-# INLINE_NORMAL interleaveInfix #-}
321interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
322interleaveInfix (Stream step1 state1) (Stream step2 state2) =
323 Stream step (InterleaveInfixFirst state1 state2)
327 {-# INLINE_LATE step #-}
328 step gst (InterleaveInfixFirst st1 st2) = do
331 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
332 Skip s -> Skip (InterleaveInfixFirst s st2)
335 step gst (InterleaveInfixSecondBuf st1 st2) = do
338 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
339 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
340 Stop -> Skip (InterleaveInfixFirstOnly st1)
342 step gst (InterleaveInfixSecondYield st1 st2 x) = do
345 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
346 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
349 step _ (InterleaveInfixFirstYield st1 st2 x) = do
350 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
352 step gst (InterleaveInfixFirstOnly st1) = do
355 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
356 Skip s -> Skip (InterleaveInfixFirstOnly s)
359------------------------------------------------------------------------------
361------------------------------------------------------------------------------
363{-# INLINE_NORMAL roundRobin #-}
364roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
365roundRobin (Stream step1 state1) (Stream step2 state2) =
366 Stream step (InterleaveFirst state1 state2)
370 {-# INLINE_LATE step #-}
371 step gst (InterleaveFirst st1 st2) = do
374 Yield a s -> Yield a (InterleaveSecond s st2)
375 Skip s -> Skip (InterleaveSecond s st2)
376 Stop -> Skip (InterleaveSecondOnly st2)
378 step gst (InterleaveSecond st1 st2) = do
381 Yield a s -> Yield a (InterleaveFirst st1 s)
382 Skip s -> Skip (InterleaveFirst st1 s)
383 Stop -> Skip (InterleaveFirstOnly st1)
385 step gst (InterleaveSecondOnly st2) = do
388 Yield a s -> Yield a (InterleaveSecondOnly s)
389 Skip s -> Skip (InterleaveSecondOnly s)
392 step gst (InterleaveFirstOnly st1) = do
395 Yield a s -> Yield a (InterleaveFirstOnly s)
396 Skip s -> Skip (InterleaveFirstOnly s)
399------------------------------------------------------------------------------
401------------------------------------------------------------------------------
403{-# INLINE_NORMAL zipWithM #-}
405 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
406zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
408 {-# INLINE_LATE step #-}
409 step gst (sa, sb, Nothing) = do
410 r <- stepa (adaptState gst) sa
413 Yield x sa' -> Skip (sa', sb, Just x)
414 Skip sa' -> Skip (sa', sb, Nothing)
417 step gst (sa, sb, Just x) = do
418 r <- stepb (adaptState gst) sb
422 return $ Yield z (sa, sb', Nothing)
423 Skip sb' -> return $ Skip (sa, sb', Just x)
426#if __GLASGOW_HASKELL__ >= 801
427{-# RULES "zipWithM xs xs"
428 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
431{-# INLINE zipWith #-}
432zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
433zipWith f = zipWithM (\a b -> return (f a b))
435------------------------------------------------------------------------------
437------------------------------------------------------------------------------
439{-# INLINE_NORMAL mergeByM #-}
442 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
443mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
444 Stream step (Just ta, Just tb, Nothing, Nothing)
446 {-# INLINE_LATE step #-}
448 -- one of the values is missing, and the corresponding stream is running
449 step gst (Just sa, sb, Nothing, b) = do
452 Yield a sa' -> Skip (Just sa', sb, Just a, b)
453 Skip sa' -> Skip (Just sa', sb, Nothing, b)
454 Stop -> Skip (Nothing, sb, Nothing, b)
456 step gst (sa, Just sb, a, Nothing) = do
459 Yield b sb' -> Skip (sa, Just sb', a, Just b)
460 Skip sb' -> Skip (sa, Just sb', a, Nothing)
461 Stop -> Skip (sa, Nothing, a, Nothing)
463 -- both the values are available
464 step _ (sa, sb, Just a, Just b) = do
467 GT -> Yield b (sa, sb, Just a, Nothing)
468 _ -> Yield a (sa, sb, Nothing, Just b)
470 -- one of the values is missing, corresponding stream is done
471 step _ (Nothing, sb, Nothing, Just b) =
472 return $ Yield b (Nothing, sb, Nothing, Nothing)
474 step _ (sa, Nothing, Just a, Nothing) =
475 return $ Yield a (sa, Nothing, Nothing, Nothing)
477 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
479{-# INLINE mergeBy #-}
482 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
483mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
485------------------------------------------------------------------------------
486-- Combine N Streams - unfoldMany
487------------------------------------------------------------------------------
489data ConcatUnfoldInterleaveState o i =
490 ConcatUnfoldInterleaveOuter o [i]
491 | ConcatUnfoldInterleaveInner o [i]
492 | ConcatUnfoldInterleaveInnerL [i] [i]
493 | ConcatUnfoldInterleaveInnerR [i] [i]
495-- XXX use arrays to store state instead of lists?
497-- XXX In general we can use different scheduling strategies e.g. how to
498-- schedule the outer vs inner loop or assigning weights to different streams
499-- or outer and inner loops.
501-- After a yield, switch to the next stream. Do not switch streams on Skip.
502-- Yield from outer stream switches to the inner stream.
504-- There are two choices here, (1) exhaust the outer stream first and then
505-- start yielding from the inner streams, this is much simpler to implement,
506-- (2) yield at least one element from an inner stream before going back to
507-- outer stream and opening the next stream from it.
509-- Ideally, we need some scheduling bias to inner streams vs outer stream.
510-- Maybe we can configure the behavior.
512-- XXX Instead of using "concatPairsWith wSerial" we can implement an N-way
513-- interleaving CPS combinator which behaves like unfoldManyInterleave. Intead
514-- of pairing up the streams We just need to go yielding one element from each
515-- stream and storing the remaining streams and then keep doing rounds through
516-- those in a round robin fashion. This would be much like wAsync.
518-- | This does not pair streams like concatPairsWith, instead, it goes through
519-- each stream one by one and yields one element from each stream. After it
520-- goes to the last stream it reverses the traversal to come back to the first
521-- stream yielding elements from each stream on its way back to the first
524-- >>> input = Stream.fromList [[1,1],[2,2],[3,3],[4,4],[5,5]]
525-- >>> Stream.toList $ Stream.unfoldManyInterleave Unfold.fromList input
526-- [1,2,3,4,5,5,4,3,2,1]
528-- Note that this is order of magnitude more efficient than "concatPairsWith
530{-# INLINE_NORMAL unfoldManyInterleave #-}
531unfoldManyInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
532unfoldManyInterleave (Unfold istep inject) (Stream ostep ost) =
533 Stream step (ConcatUnfoldInterleaveOuter ost [])
537 {-# INLINE_LATE step #-}
538 step gst (ConcatUnfoldInterleaveOuter o ls) = do
539 r <- ostep (adaptState gst) o
543 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
544 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
545 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
547 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
548 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
551 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
552 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
553 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
555 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
556 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
557 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
559 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
562 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
563 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
564 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
566 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
567 step _ (ConcatUnfoldInterleaveInnerR ls []) =
568 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
570 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
573 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
574 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
575 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
577-- XXX In general we can use different scheduling strategies e.g. how to
578-- schedule the outer vs inner loop or assigning weights to different streams
579-- or outer and inner loops.
581-- This could be inefficient if the tasks are too small.
583-- Compared to unfoldManyInterleave this one switches streams on Skips.
585{-# INLINE_NORMAL unfoldManyRoundRobin #-}
586unfoldManyRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
587unfoldManyRoundRobin (Unfold istep inject) (Stream ostep ost) =
588 Stream step (ConcatUnfoldInterleaveOuter ost [])
590 {-# INLINE_LATE step #-}
591 step gst (ConcatUnfoldInterleaveOuter o ls) = do
592 r <- ostep (adaptState gst) o
596 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
597 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
598 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
600 step _ (ConcatUnfoldInterleaveInner o []) =
601 return $ Skip (ConcatUnfoldInterleaveOuter o [])
603 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
606 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
607 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
608 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
610 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
611 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
612 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
614 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
617 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
618 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
619 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
621 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
622 step _ (ConcatUnfoldInterleaveInnerR ls []) =
623 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
625 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
628 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
629 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
630 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
632------------------------------------------------------------------------------
633-- Combine N Streams - interpose
634------------------------------------------------------------------------------
636{-# ANN type InterposeSuffixState Fuse #-}
637data InterposeSuffixState s1 i1 =
638 InterposeSuffixFirst s1
639 -- | InterposeSuffixFirstYield s1 i1
640 | InterposeSuffixFirstInner s1 i1
641 | InterposeSuffixSecond s1
643-- Note that if an unfolded layer turns out to be nil we still emit the
644-- separator effect. An alternate behavior could be to emit the separator
645-- effect only if at least one element has been yielded by the unfolding.
646-- However, that becomes a bit complicated, so we have chosen the former
648{-# INLINE_NORMAL interposeSuffix #-}
651 => m c -> Unfold m b c -> Stream m b -> Stream m c
654 (Unfold istep1 inject1) (Stream step1 state1) =
655 Stream step (InterposeSuffixFirst state1)
659 {-# INLINE_LATE step #-}
660 step gst (InterposeSuffixFirst s1) = do
661 r <- step1 (adaptState gst) s1
665 i `seq` return (Skip (InterposeSuffixFirstInner s i))
666 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
667 Skip s -> return $ Skip (InterposeSuffixFirst s)
671 step _ (InterposeSuffixFirstYield s1 i1) = do
674 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
675 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
676 Stop -> Skip (InterposeSuffixFirst s1)
679 step _ (InterposeSuffixFirstInner s1 i1) = do
682 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
683 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
684 Stop -> Skip (InterposeSuffixSecond s1)
686 step _ (InterposeSuffixSecond s1) = do
688 return $ Yield r (InterposeSuffixFirst s1)
690{-# ANN type InterposeState Fuse #-}
691data InterposeState s1 i1 a =
693 -- | InterposeFirstYield s1 i1
694 | InterposeFirstInner s1 i1
695 | InterposeFirstInject s1
696 -- | InterposeFirstBuf s1 i1
697 | InterposeSecondYield s1 i1
698 -- -- | InterposeSecondYield s1 i1 a
699 -- -- | InterposeFirstResume s1 i1 a
701-- Note that this only interposes the pure values, we may run many effects to
702-- generate those values as some effects may not generate anything (Skip).
703{-# INLINE_NORMAL interpose #-}
704interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
707 (Unfold istep1 inject1) (Stream step1 state1) =
708 Stream step (InterposeFirst state1)
712 {-# INLINE_LATE step #-}
713 step gst (InterposeFirst s1) = do
714 r <- step1 (adaptState gst) s1
718 i `seq` return (Skip (InterposeFirstInner s i))
719 -- i `seq` return (Skip (InterposeFirstYield s i))
720 Skip s -> return $ Skip (InterposeFirst s)
724 step _ (InterposeFirstYield s1 i1) = do
727 Yield x i' -> Yield x (InterposeFirstInner s1 i')
728 Skip i' -> Skip (InterposeFirstYield s1 i')
729 Stop -> Skip (InterposeFirst s1)
732 step _ (InterposeFirstInner s1 i1) = do
735 Yield x i' -> Yield x (InterposeFirstInner s1 i')
736 Skip i' -> Skip (InterposeFirstInner s1 i')
737 Stop -> Skip (InterposeFirstInject s1)
739 step gst (InterposeFirstInject s1) = do
740 r <- step1 (adaptState gst) s1
744 -- i `seq` return (Skip (InterposeFirstBuf s i))
745 i `seq` return (Skip (InterposeSecondYield s i))
746 Skip s -> return $ Skip (InterposeFirstInject s)
750 step _ (InterposeFirstBuf s1 i1) = do
753 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
754 Skip i' -> Skip (InterposeFirstBuf s1 i')
759 step _ (InterposeSecondYield s1 i1 v) = do
761 return $ Yield r (InterposeFirstResume s1 i1 v)
763 step _ (InterposeSecondYield s1 i1) = do
765 return $ Yield r (InterposeFirstInner s1 i1)
768 step _ (InterposeFirstResume s1 i1 v) = do
769 return $ Yield v (InterposeFirstInner s1 i1)
772------------------------------------------------------------------------------
773-- Combine N Streams - intercalate
774------------------------------------------------------------------------------
776data ICUState s1 s2 i1 i2 =
781 | ICUFirstInner s1 s2 i1
782 | ICUSecondInner s1 s2 i2
783 | ICUFirstOnlyInner s1 i1
784 | ICUSecondOnlyInner s2 i2
786-- | Interleave streams (full streams, not the elements) unfolded from two
787-- input streams and concat. Stop when the first stream stops. If the second
788-- stream ends before the first one then first stream still keeps running alone
789-- without any interleaving with the second stream.
791-- [a1, a2, ... an] [b1, b2 ...]
792-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
793-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
794-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
796{-# INLINE_NORMAL gintercalateSuffix #-}
799 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
801 (Unfold istep1 inject1) (Stream step1 state1)
802 (Unfold istep2 inject2) (Stream step2 state2) =
803 Stream step (ICUFirst state1 state2)
807 {-# INLINE_LATE step #-}
808 step gst (ICUFirst s1 s2) = do
809 r <- step1 (adaptState gst) s1
813 i `seq` return (Skip (ICUFirstInner s s2 i))
814 Skip s -> return $ Skip (ICUFirst s s2)
817 step gst (ICUFirstOnly s1) = do
818 r <- step1 (adaptState gst) s1
822 i `seq` return (Skip (ICUFirstOnlyInner s i))
823 Skip s -> return $ Skip (ICUFirstOnly s)
826 step _ (ICUFirstInner s1 s2 i1) = do
829 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
830 Skip i' -> Skip (ICUFirstInner s1 s2 i')
831 Stop -> Skip (ICUSecond s1 s2)
833 step _ (ICUFirstOnlyInner s1 i1) = do
836 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
837 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
838 Stop -> Skip (ICUFirstOnly s1)
840 step gst (ICUSecond s1 s2) = do
841 r <- step2 (adaptState gst) s2
845 i `seq` return (Skip (ICUSecondInner s1 s i))
846 Skip s -> return $ Skip (ICUSecond s1 s)
847 Stop -> return $ Skip (ICUFirstOnly s1)
849 step _ (ICUSecondInner s1 s2 i2) = do
852 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
853 Skip i' -> Skip (ICUSecondInner s1 s2 i')
854 Stop -> Skip (ICUFirst s1 s2)
856 step _ (ICUSecondOnly _s2) = undefined
857 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
859data ICALState s1 s2 i1 i2 a =
861 -- | ICALFirstYield s1 s2 i1
862 | ICALFirstInner s1 s2 i1
864 | ICALFirstOnlyInner s1 i1
865 | ICALSecondInject s1 s2
866 | ICALFirstInject s1 s2 i2
867 -- | ICALFirstBuf s1 s2 i1 i2
868 | ICALSecondInner s1 s2 i1 i2
869 -- -- | ICALSecondInner s1 s2 i1 i2 a
870 -- -- | ICALFirstResume s1 s2 i1 i2 a
872-- | Interleave streams (full streams, not the elements) unfolded from two
873-- input streams and concat. Stop when the first stream stops. If the second
874-- stream ends before the first one then first stream still keeps running alone
875-- without any interleaving with the second stream.
877-- [a1, a2, ... an] [b1, b2 ...]
878-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
879-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
880-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
882{-# INLINE_NORMAL gintercalate #-}
885 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
887 (Unfold istep1 inject1) (Stream step1 state1)
888 (Unfold istep2 inject2) (Stream step2 state2) =
889 Stream step (ICALFirst state1 state2)
893 {-# INLINE_LATE step #-}
894 step gst (ICALFirst s1 s2) = do
895 r <- step1 (adaptState gst) s1
899 i `seq` return (Skip (ICALFirstInner s s2 i))
900 -- i `seq` return (Skip (ICALFirstYield s s2 i))
901 Skip s -> return $ Skip (ICALFirst s s2)
905 step _ (ICALFirstYield s1 s2 i1) = do
908 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
909 Skip i' -> Skip (ICALFirstYield s1 s2 i')
910 Stop -> Skip (ICALFirst s1 s2)
913 step _ (ICALFirstInner s1 s2 i1) = do
916 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
917 Skip i' -> Skip (ICALFirstInner s1 s2 i')
918 Stop -> Skip (ICALSecondInject s1 s2)
920 step gst (ICALFirstOnly s1) = do
921 r <- step1 (adaptState gst) s1
925 i `seq` return (Skip (ICALFirstOnlyInner s i))
926 Skip s -> return $ Skip (ICALFirstOnly s)
929 step _ (ICALFirstOnlyInner s1 i1) = do
932 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
933 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
934 Stop -> Skip (ICALFirstOnly s1)
936 -- We inject the second stream even before checking if the first stream
937 -- would yield any more elements. There is no clear choice whether we
938 -- should do this before or after that. Doing it after may make the state
939 -- machine a bit simpler though.
940 step gst (ICALSecondInject s1 s2) = do
941 r <- step2 (adaptState gst) s2
945 i `seq` return (Skip (ICALFirstInject s1 s i))
946 Skip s -> return $ Skip (ICALSecondInject s1 s)
947 Stop -> return $ Skip (ICALFirstOnly s1)
949 step gst (ICALFirstInject s1 s2 i2) = do
950 r <- step1 (adaptState gst) s1
954 i `seq` return (Skip (ICALSecondInner s s2 i i2))
955 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
956 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
960 step _ (ICALFirstBuf s1 s2 i1 i2) = do
963 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
964 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
967 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
970 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
971 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
972 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
975 step _ (ICALSecondInner s1 s2 i1 i2) = do
978 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
979 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
980 Stop -> Skip (ICALFirstInner s1 s2 i1)
981 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
984 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
985 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
988------------------------------------------------------------------------------
990------------------------------------------------------------------------------
992{-# ANN type FIterState Fuse #-}
993data FIterState s f m a b
995 | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
996 | FIterYield b (FIterState s f m a b)
999{-# INLINE_NORMAL foldIterateM #-}
1001 Monad m => (b -> m (FL.Fold m a b)) -> m b -> Stream m a -> Stream m b
1002foldIterateM func seed0 (Stream step state) =
1003 Stream stepOuter (FIterInit state seed0)
1007 {-# INLINE iterStep #-}
1008 iterStep from st fstep extract = do
1013 FL.Partial fs -> FIterStream st fstep fs extract
1014 FL.Done fb -> FIterYield fb $ FIterInit st (return fb)
1016 {-# INLINE_LATE stepOuter #-}
1017 stepOuter _ (FIterInit st seed) = do
1018 (FL.Fold fstep initial extract) <- seed >>= func
1019 iterStep initial st fstep extract
1020 stepOuter gst (FIterStream st fstep fs extract) = do
1021 r <- step (adaptState gst) st
1024 iterStep (fstep fs x) s fstep extract
1025 Skip s -> return $ Skip $ FIterStream s fstep fs extract
1028 return $ Skip $ FIterYield b FIterStop
1029 stepOuter _ (FIterYield a next) = return $ Yield a next
1030 stepOuter _ FIterStop = return Stop
1032{-# ANN type CIterState Fuse #-}
1033data CIterState s f fs b
1036 | CIterYield b (CIterState s f fs b)
1039-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
1040-- much more efficient due to stream fusion.
1043{-# INLINE_NORMAL refoldIterateM #-}
1045 Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
1046refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
1047 Stream stepOuter (CIterInit state initial)
1051 {-# INLINE iterStep #-}
1052 iterStep st action = do
1057 FL.Partial fs -> CIterConsume st fs
1058 FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
1060 {-# INLINE_LATE stepOuter #-}
1061 stepOuter _ (CIterInit st action) = do
1062 iterStep st (action >>= finject)
1063 stepOuter gst (CIterConsume st fs) = do
1064 r <- step (adaptState gst) st
1066 Yield x s -> iterStep s (fstep fs x)
1067 Skip s -> return $ Skip $ CIterConsume s fs
1070 return $ Skip $ CIterYield b CIterStop
1071 stepOuter _ (CIterYield a next) = return $ Yield a next
1072 stepOuter _ CIterStop = return Stop
1074-- "n" elements at the end are dropped by the fold.
1075{-# INLINE sliceBy #-}
1076sliceBy :: Monad m => Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
1077sliceBy (Fold step1 initial1 extract1) n = Refold step inject extract
1081 inject (i, len) = do
1084 Partial s -> Partial $ Tuple' (i + len + n) s
1085 Done l -> Done (i, l)
1087 step (Tuple' i s) x = do
1090 Partial s1 -> Partial $ Tuple' i s1
1091 Done len -> Done (i, len)
1093 extract (Tuple' i s) = (i,) <$> extract1 s
1095{-# INLINE sliceOnSuffix #-}
1096sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1097sliceOnSuffix predicate =
1098 -- Scan the stream with the given refold
1100 (sliceBy (FL.takeEndBy_ predicate FL.length) 1)
1103------------------------------------------------------------------------------
1105------------------------------------------------------------------------------
1107{-# ANN type ParseChunksState Fuse #-}
1108data ParseChunksState x inpBuf st pst =
1109 ParseChunksInit inpBuf st
1110 | ParseChunksInitLeftOver inpBuf
1111 | ParseChunksStream st inpBuf !pst
1112 | ParseChunksBuf inpBuf st inpBuf !pst
1113 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1115{-# INLINE_NORMAL parseMany #-}
1121parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1122 Stream stepOuter (ParseChunksInit [] state)
1126 {-# INLINE_LATE stepOuter #-}
1127 -- Buffer is empty, get the first element from the stream, initialize the
1128 -- fold and then go to stream processing loop.
1129 stepOuter gst (ParseChunksInit [] st) = do
1130 r <- step (adaptState gst) st
1136 return $ Skip $ ParseChunksBuf [x] s [] ps
1138 let next = ParseChunksInit [x] s
1139 in return $ Skip $ ParseChunksYield pb next
1140 PRD.IError err -> throwM $ ParseError err
1141 Skip s -> return $ Skip $ ParseChunksInit [] s
1144 -- Buffer is not empty, go to buffered processing loop
1145 stepOuter _ (ParseChunksInit src st) = do
1149 return $ Skip $ ParseChunksBuf src st [] ps
1151 let next = ParseChunksInit src st
1152 in return $ Skip $ ParseChunksYield pb next
1153 PRD.IError err -> throwM $ ParseError err
1155 -- XXX we just discard any leftover input at the end
1156 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1158 -- Buffer is empty, process elements from the stream
1159 stepOuter gst (ParseChunksStream st buf pst) = do
1160 r <- step (adaptState gst) st
1165 PR.Partial 0 pst1 ->
1166 return $ Skip $ ParseChunksStream s [] pst1
1167 PR.Partial n pst1 -> do
1168 assert (n <= length (x:buf)) (return ())
1169 let src0 = Prelude.take n (x:buf)
1170 src = Prelude.reverse src0
1171 return $ Skip $ ParseChunksBuf src s [] pst1
1172 PR.Continue 0 pst1 ->
1173 return $ Skip $ ParseChunksStream s (x:buf) pst1
1174 PR.Continue n pst1 -> do
1175 assert (n <= length (x:buf)) (return ())
1176 let (src0, buf1) = splitAt n (x:buf)
1177 src = Prelude.reverse src0
1178 return $ Skip $ ParseChunksBuf src s buf1 pst1
1181 ParseChunksYield b (ParseChunksInit [] s)
1183 assert (n <= length (x:buf)) (return ())
1184 let src = Prelude.reverse (Prelude.take n (x:buf))
1186 ParseChunksYield b (ParseChunksInit src s)
1187 PR.Error err -> throwM $ ParseError err
1188 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1191 let src = Prelude.reverse buf
1193 ParseChunksYield b (ParseChunksInitLeftOver src)
1195 -- go back to stream processing mode
1196 stepOuter _ (ParseChunksBuf [] s buf pst) =
1197 return $ Skip $ ParseChunksStream s buf pst
1199 -- buffered processing loop
1200 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1203 PR.Partial 0 pst1 ->
1204 return $ Skip $ ParseChunksBuf xs s [] pst1
1205 PR.Partial n pst1 -> do
1206 assert (n <= length (x:buf)) (return ())
1207 let src0 = Prelude.take n (x:buf)
1208 src = Prelude.reverse src0 ++ xs
1209 return $ Skip $ ParseChunksBuf src s [] pst1
1210 PR.Continue 0 pst1 ->
1211 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1212 PR.Continue n pst1 -> do
1213 assert (n <= length (x:buf)) (return ())
1214 let (src0, buf1) = splitAt n (x:buf)
1215 src = Prelude.reverse src0 ++ xs
1216 return $ Skip $ ParseChunksBuf src s buf1 pst1
1218 return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1220 assert (n <= length (x:buf)) (return ())
1221 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1222 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1223 PR.Error err -> throwM $ ParseError err
1225 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1227{-# ANN type ConcatParseState Fuse #-}
1228data ConcatParseState b inpBuf st p m a =
1229 ConcatParseInit inpBuf st p
1230 | ConcatParseInitLeftOver inpBuf
1231 | forall s. ConcatParseStream st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1232 | forall s. ConcatParseBuf inpBuf st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m b)
1233 | ConcatParseYield b (ConcatParseState b inpBuf st p m a)
1235{-# INLINE_NORMAL parseIterate #-}
1238 => (b -> PRD.Parser m a b)
1242parseIterate func seed (Stream step state) =
1243 Stream stepOuter (ConcatParseInit [] state (func seed))
1247 {-# INLINE_LATE stepOuter #-}
1248 -- Buffer is empty, go to stream processing loop
1249 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1253 return $ Skip $ ConcatParseStream st [] pstep ps extract
1255 let next = ConcatParseInit [] st (func pb)
1256 in return $ Skip $ ConcatParseYield pb next
1257 PRD.IError err -> throwM $ ParseError err
1259 -- Buffer is not empty, go to buffered processing loop
1260 stepOuter _ (ConcatParseInit src st
1261 (PRD.Parser pstep initial extract)) = do
1265 return $ Skip $ ConcatParseBuf src st [] pstep ps extract
1267 let next = ConcatParseInit src st (func pb)
1268 in return $ Skip $ ConcatParseYield pb next
1269 PRD.IError err -> throwM $ ParseError err
1271 -- XXX we just discard any leftover input at the end
1272 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1274 -- Buffer is empty process elements from the stream
1275 stepOuter gst (ConcatParseStream st buf pstep pst extract) = do
1276 r <- step (adaptState gst) st
1281 PR.Partial 0 pst1 ->
1282 return $ Skip $ ConcatParseStream s [] pstep pst1 extract
1283 PR.Partial n pst1 -> do
1284 assert (n <= length (x:buf)) (return ())
1285 let src0 = Prelude.take n (x:buf)
1286 src = Prelude.reverse src0
1287 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1288 -- PR.Continue 0 pst1 ->
1289 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1290 PR.Continue n pst1 -> do
1291 assert (n <= length (x:buf)) (return ())
1292 let (src0, buf1) = splitAt n (x:buf)
1293 src = Prelude.reverse src0
1294 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1295 -- XXX Specialize for Stop 0 common case?
1297 assert (n <= length (x:buf)) (return ())
1298 let src = Prelude.reverse (Prelude.take n (x:buf))
1300 ConcatParseYield b (ConcatParseInit src s (func b))
1301 PR.Error err -> throwM $ ParseError err
1302 Skip s -> return $ Skip $ ConcatParseStream s buf pstep pst extract
1305 let src = Prelude.reverse buf
1306 return $ Skip $ ConcatParseYield b (ConcatParseInitLeftOver src)
1308 -- go back to stream processing mode
1309 stepOuter _ (ConcatParseBuf [] s buf pstep ps extract) =
1310 return $ Skip $ ConcatParseStream s buf pstep ps extract
1312 -- buffered processing loop
1313 stepOuter _ (ConcatParseBuf (x:xs) s buf pstep pst extract) = do
1316 PR.Partial 0 pst1 ->
1317 return $ Skip $ ConcatParseBuf xs s [] pstep pst1 extract
1318 PR.Partial n pst1 -> do
1319 assert (n <= length (x:buf)) (return ())
1320 let src0 = Prelude.take n (x:buf)
1321 src = Prelude.reverse src0 ++ xs
1322 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1323 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1324 PR.Continue n pst1 -> do
1325 assert (n <= length (x:buf)) (return ())
1326 let (src0, buf1) = splitAt n (x:buf)
1327 src = Prelude.reverse src0 ++ xs
1328 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1329 -- XXX Specialize for Stop 0 common case?
1331 assert (n <= length (x:buf)) (return ())
1332 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1333 return $ Skip $ ConcatParseYield b
1334 (ConcatParseInit src s (func b))
1335 PR.Error err -> throwM $ ParseError err
1337 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1339------------------------------------------------------------------------------
1341------------------------------------------------------------------------------
1343data GroupByState st fs a b
1346 | GroupingInitWith st !a
1347 | GroupingDoWith st !fs !a
1348 | GroupingYield !b (GroupByState st fs a b)
1351{-# INLINE_NORMAL groupsBy #-}
1358groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1360groupsBy cmp (Fold fstep initial done) (Stream step state) =
1361 Stream stepOuter (GroupingInit state)
1365 {-# INLINE_LATE stepOuter #-}
1366 stepOuter _ (GroupingInit st) = do
1367 -- XXX Note that if the stream stops without yielding a single element
1368 -- in the group we discard the "initial" effect.
1372 FL.Partial s -> Skip $ GroupingDo st s
1373 FL.Done b -> Yield b $ GroupingInit st
1374 stepOuter gst (GroupingDo st fs) = do
1375 res <- step (adaptState gst) st
1380 FL.Partial fs1 -> go SPEC x s fs1
1381 FL.Done b -> return $ Yield b (GroupingInit s)
1382 Skip s -> return $ Skip $ GroupingDo s fs
1387 go !_ prev stt !acc = do
1388 res <- step (adaptState gst) stt
1395 FL.Partial fs1 -> go SPEC prev s fs1
1396 FL.Done b -> return $ Yield b (GroupingInit s)
1399 return $ Yield r (GroupingInitWith s x)
1400 Skip s -> go SPEC prev s acc
1401 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1402 stepOuter _ (GroupingInitWith st x) = do
1406 FL.Partial s -> Skip $ GroupingDoWith st s x
1407 FL.Done b -> Yield b $ GroupingInitWith st x
1408 stepOuter gst (GroupingDoWith st fs prev) = do
1409 res <- fstep fs prev
1411 FL.Partial fs1 -> go SPEC st fs1
1412 FL.Done b -> return $ Yield b (GroupingInit st)
1416 -- XXX code duplicated from the previous equation
1418 res <- step (adaptState gst) stt
1425 FL.Partial fs1 -> go SPEC s fs1
1426 FL.Done b -> return $ Yield b (GroupingInit s)
1429 return $ Yield r (GroupingInitWith s x)
1430 Skip s -> go SPEC s acc
1431 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1432 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1433 stepOuter _ GroupingDone = return Stop
1435{-# INLINE_NORMAL groupsRollingBy #-}
1436groupsRollingBy :: Monad m
1442groupsRollingBy eq fld = parseMany (PRD.groupByRolling eq fld)
1444groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
1445 Stream stepOuter (GroupingInit state)
1449 {-# INLINE_LATE stepOuter #-}
1450 stepOuter _ (GroupingInit st) = do
1451 -- XXX Note that if the stream stops without yielding a single element
1452 -- in the group we discard the "initial" effect.
1456 FL.Partial fs -> Skip $ GroupingDo st fs
1457 FL.Done fb -> Yield fb $ GroupingInit st
1458 stepOuter gst (GroupingDo st fs) = do
1459 res <- step (adaptState gst) st
1464 FL.Partial fs1 -> go SPEC x s fs1
1465 FL.Done fb -> return $ Yield fb (GroupingInit s)
1466 Skip s -> return $ Skip $ GroupingDo s fs
1471 go !_ prev stt !acc = do
1472 res <- step (adaptState gst) stt
1479 FL.Partial fs1 -> go SPEC x s fs1
1480 FL.Done b -> return $ Yield b (GroupingInit s)
1483 return $ Yield r (GroupingInitWith s x)
1484 Skip s -> go SPEC prev s acc
1485 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1486 stepOuter _ (GroupingInitWith st x) = do
1490 FL.Partial s -> Skip $ GroupingDoWith st s x
1491 FL.Done b -> Yield b $ GroupingInitWith st x
1492 stepOuter gst (GroupingDoWith st fs previous) = do
1493 res <- fstep fs previous
1495 FL.Partial s -> go SPEC previous st s
1496 FL.Done b -> return $ Yield b (GroupingInit st)
1500 -- XXX GHC: groupsBy has one less parameter in this go loop and it
1501 -- fuses. However, groupsRollingBy does not fuse, removing the prev
1502 -- parameter makes it fuse. Something needs to be fixed in GHC. The
1503 -- workaround for this is noted in the comments below.
1504 go !_ prev !stt !acc = do
1505 res <- step (adaptState gst) stt
1512 FL.Partial fs1 -> go SPEC x s fs1
1513 FL.Done b -> return $ Yield b (GroupingInit st)
1517 return $ Yield r (GroupingInitWith s x)
1519 -- The code above does not let groupBy fuse. We use the
1520 -- alternative code below instead. Instead of jumping
1521 -- to GroupingInitWith state, we unroll the code of
1522 -- GroupingInitWith state here to help GHC with stream
1529 FL.Partial fsi -> GroupingDoWith s fsi x
1530 FL.Done b -> GroupingYield b (GroupingInit s)
1531 Skip s -> go SPEC prev s acc
1532 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1533 stepOuter _ (GroupingYield r next) = return $ Yield r next
1534 stepOuter _ GroupingDone = return Stop
1536------------------------------------------------------------------------------
1537-- Splitting - by a predicate
1538------------------------------------------------------------------------------
1540data WordsByState st fs b
1544 | WordsByYield !b (WordsByState st fs b)
1546{-# INLINE_NORMAL wordsBy #-}
1547wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1548wordsBy predicate (Fold fstep initial done) (Stream step state) =
1549 Stream stepOuter (WordsByInit state)
1553 {-# INLINE_LATE stepOuter #-}
1554 stepOuter _ (WordsByInit st) = do
1558 FL.Partial s -> Skip $ WordsByDo st s
1559 FL.Done b -> Yield b (WordsByInit st)
1561 stepOuter gst (WordsByDo st fs) = do
1562 res <- step (adaptState gst) st
1570 FL.Partial fs1 -> Skip $ WordsByDo s fs1
1571 FL.Done b -> Yield b (WordsByInit s)
1575 FL.Partial fs1 -> go SPEC s fs1
1576 FL.Done b -> return $ Yield b (WordsByInit s)
1577 Skip s -> return $ Skip $ WordsByDo s fs
1583 res <- step (adaptState gst) stt
1590 return $ Yield r (WordsByInit s)
1592 -- The above code does not fuse well. Need to check why
1593 -- GHC is not able to simplify it well. Using the code
1594 -- below, instead of jumping through the WordsByInit
1595 -- state always, we directly go to WordsByDo state in
1596 -- the common case of Partial.
1602 FL.Partial fs1 -> WordsByDo s fs1
1603 FL.Done b -> WordsByYield b (WordsByInit s)
1607 FL.Partial fs1 -> go SPEC s fs1
1608 FL.Done b -> return $ Yield b (WordsByInit s)
1609 Skip s -> go SPEC s acc
1610 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
1612 stepOuter _ WordsByDone = return Stop
1614 stepOuter _ (WordsByYield b next) = return $ Yield b next
1616------------------------------------------------------------------------------
1617-- Splitting on a sequence
1618------------------------------------------------------------------------------
1620-- String search algorithms:
1621-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1624-- TODO can we unify the splitting operations using a splitting configuration
1625-- like in the split package.
1627data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1628data SplitOptions = SplitOptions
1629 { style :: SplitStyle
1630 , withSep :: Bool -- ^ keep the separators in output
1631 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1632 -- , trimHead :: Bool -- ^ drop blank at head
1633 -- , trimTail :: Bool -- ^ drop blank at tail
1637-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
1638-- because we can use the constructor directly without having to create "jump"
1640{-# ANN type SplitOnSeqState Fuse #-}
1641data SplitOnSeqState rb rh ck w fs s b x =
1643 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1646 | SplitOnSeqEmpty !fs s
1648 | SplitOnSeqSingle !fs s x
1650 | SplitOnSeqWordInit !fs s
1651 | SplitOnSeqWordLoop !w s !fs
1652 | SplitOnSeqWordDone Int !fs !w
1654 | SplitOnSeqKRInit Int !fs s rb !rh
1655 | SplitOnSeqKRLoop fs s rb !rh !ck
1656 | SplitOnSeqKRCheck fs s rb !rh
1657 | SplitOnSeqKRDone Int !fs rb !rh
1659 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
1661{-# INLINE_NORMAL splitOnSeq #-}
1663 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1668splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1669 Stream stepOuter SplitOnSeqInit
1673 patLen = A.length patArr
1674 maxIndex = patLen - 1
1675 elemBits = SIZE_OF(a) * 8
1677 -- For word pattern case
1679 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1682 elemMask = (1 `shiftL` elemBits) - 1
1685 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1687 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1689 -- For Rabin-Karp search
1690 k = 2891336453 :: Word32
1693 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1695 deltaCksum cksum old new =
1696 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1698 -- XXX shall we use a random starting hash or 1 instead of 0?
1699 patHash = A.foldl' addCksum 0 patArr
1701 skip = return . Skip
1703 nextAfterInit nextGen stepRes =
1705 FL.Partial s -> nextGen s
1706 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
1708 {-# INLINE yieldProceed #-}
1709 yieldProceed nextGen fs =
1710 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
1712 {-# INLINE_LATE stepOuter #-}
1713 stepOuter _ SplitOnSeqInit = do
1718 then return $ Skip $ SplitOnSeqEmpty acc state
1721 pat <- liftIO $ A.unsafeIndexIO 0 patArr
1722 return $ Skip $ SplitOnSeqSingle acc state pat
1723 else if SIZE_OF(a) * patLen
1724 <= sizeOf (undefined :: Word)
1725 then return $ Skip $ SplitOnSeqWordInit acc state
1727 (rb, rhead) <- liftIO $ RB.new patLen
1728 skip $ SplitOnSeqKRInit 0 acc state rb rhead
1729 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
1731 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1733 ---------------------------
1735 ---------------------------
1737 stepOuter _ (SplitOnSeqReinit nextGen) =
1738 initial >>= skip . nextAfterInit nextGen
1740 ---------------------------
1742 ---------------------------
1744 stepOuter gst (SplitOnSeqEmpty acc st) = do
1745 res <- step (adaptState gst) st
1751 FL.Partial acc1 -> done acc1
1752 FL.Done b -> return b
1753 let jump c = SplitOnSeqEmpty c s
1754 in yieldProceed jump b1
1755 Skip s -> skip (SplitOnSeqEmpty acc s)
1762 stepOuter _ SplitOnSeqDone = return Stop
1768 stepOuter gst (SplitOnSeqSingle fs st pat) = do
1769 res <- step (adaptState gst) st
1772 let jump c = SplitOnSeqSingle c s pat
1774 then done fs >>= yieldProceed jump
1778 FL.Partial fs1 -> skip $ jump fs1
1779 FL.Done b -> yieldProceed jump b
1780 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1783 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1785 ---------------------------
1786 -- Short Pattern - Shift Or
1787 ---------------------------
1789 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1791 skip $ SplitOnSeqYield r SplitOnSeqDone
1792 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1793 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1794 r <- fstep fs (toEnum $ fromIntegral old)
1796 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1798 let jump c = SplitOnSeqWordDone (n - 1) c wrd
1801 stepOuter gst (SplitOnSeqWordInit fs st0) =
1807 go !_ !idx !wrd !st = do
1808 res <- step (adaptState gst) st
1811 let wrd1 = addToWord wrd x
1814 if wrd1 .&. wordMask == wordPat
1816 let jump c = SplitOnSeqWordInit c s
1817 done fs >>= yieldProceed jump
1818 else skip $ SplitOnSeqWordLoop wrd1 s fs
1819 else go SPEC (idx + 1) wrd1 s
1820 Skip s -> go SPEC idx wrd s
1823 then skip $ SplitOnSeqWordDone idx fs wrd
1826 skip $ SplitOnSeqYield r SplitOnSeqDone
1828 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1829 go SPEC wrd0 st0 fs0
1834 go !_ !wrd !st !fs = do
1835 res <- step (adaptState gst) st
1838 let jump c = SplitOnSeqWordInit c s
1839 wrd1 = addToWord wrd x
1840 old = (wordMask .&. wrd)
1841 `shiftR` (elemBits * (patLen - 1))
1842 r <- fstep fs (toEnum $ fromIntegral old)
1844 FL.Partial fs1 -> do
1845 if wrd1 .&. wordMask == wordPat
1846 then done fs1 >>= yieldProceed jump
1847 else go SPEC wrd1 s fs1
1848 FL.Done b -> yieldProceed jump b
1849 Skip s -> go SPEC wrd s fs
1850 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1852 -------------------------------
1853 -- General Pattern - Karp Rabin
1854 -------------------------------
1856 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
1857 res <- step (adaptState gst) st
1860 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1863 let fld = RB.unsafeFoldRing (RB.ringBound rb)
1864 let !ringHash = fld addCksum 0 rb
1865 if ringHash == patHash
1866 then skip $ SplitOnSeqKRCheck fs s rb rh1
1867 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1868 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
1869 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
1871 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1873 -- XXX The recursive "go" is more efficient than the state based recursion
1874 -- code commented out below. Perhaps its more efficient because of
1875 -- factoring out "rb" outside the loop.
1877 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1878 go SPEC fs0 st0 rh0 cksum0
1882 go !_ !fs !st !rh !cksum = do
1883 res <- step (adaptState gst) st
1886 old <- liftIO $ peek rh
1887 let cksum1 = deltaCksum cksum old x
1890 FL.Partial fs1 -> do
1891 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1892 if cksum1 == patHash
1893 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1894 else go SPEC fs1 s rh1 cksum1
1896 let rst = RB.startOf rb
1897 jump c = SplitOnSeqKRInit 0 c s rb rst
1899 Skip s -> go SPEC fs s rh cksum
1900 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1902 -- XXX The following code is 5 times slower compared to the recursive loop
1903 -- based code above. Need to investigate why. One possibility is that the
1904 -- go loop above does not thread around the ring buffer (rb). This code may
1905 -- be causing the state to bloat and getting allocated on each iteration.
1906 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1907 -- such problem is needed. One way to avoid this could be to use unboxed
1910 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1911 res <- step (adaptState gst) st
1914 old <- liftIO $ peek rh
1915 let cksum1 = deltaCksum cksum old x
1917 if (cksum1 == patHash)
1920 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1922 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1923 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1924 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1925 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1928 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1929 if RB.unsafeEqArray rb rh patArr
1932 let rst = RB.startOf rb
1933 jump c = SplitOnSeqKRInit 0 c st rb rst
1935 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1937 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1939 skip $ SplitOnSeqYield r SplitOnSeqDone
1940 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1941 old <- liftIO $ peek rh
1942 let rh1 = RB.advance rb rh
1945 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
1947 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
1950{-# ANN type SplitOnSuffixSeqState Fuse #-}
1951data SplitOnSuffixSeqState rb rh ck w fs s b x =
1952 SplitOnSuffixSeqInit
1953 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
1954 | SplitOnSuffixSeqDone
1956 | SplitOnSuffixSeqEmpty !fs s
1958 | SplitOnSuffixSeqSingleInit !fs s x
1959 | SplitOnSuffixSeqSingle !fs s x
1961 | SplitOnSuffixSeqWordInit !fs s
1962 | SplitOnSuffixSeqWordLoop !w s !fs
1963 | SplitOnSuffixSeqWordDone Int !fs !w
1965 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
1966 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
1967 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
1968 | SplitOnSuffixSeqKRCheck fs s rb !rh
1969 | SplitOnSuffixSeqKRDone Int !fs rb !rh
1971 | SplitOnSuffixSeqReinit
1972 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
1974{-# INLINE_NORMAL splitOnSuffixSeq #-}
1976 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1982splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
1983 Stream stepOuter SplitOnSuffixSeqInit
1987 patLen = A.length patArr
1988 maxIndex = patLen - 1
1989 elemBits = SIZE_OF(a) * 8
1991 -- For word pattern case
1993 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1996 elemMask = (1 `shiftL` elemBits) - 1
1999 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2001 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2003 nextAfterInit nextGen stepRes =
2005 FL.Partial s -> nextGen s
2007 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
2009 {-# INLINE yieldProceed #-}
2010 yieldProceed nextGen fs =
2011 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
2013 -- For single element pattern case
2014 {-# INLINE processYieldSingle #-}
2015 processYieldSingle pat x s fs = do
2016 let jump c = SplitOnSuffixSeqSingleInit c s pat
2019 r <- if withSep then fstep fs x else return $ FL.Partial fs
2022 FL.Partial fs1 -> done fs1
2023 FL.Done b -> return b
2024 yieldProceed jump b1
2028 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2029 FL.Done b -> yieldProceed jump b
2031 -- For Rabin-Karp search
2032 k = 2891336453 :: Word32
2035 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2037 deltaCksum cksum old new =
2038 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2040 -- XXX shall we use a random starting hash or 1 instead of 0?
2041 patHash = A.foldl' addCksum 0 patArr
2043 skip = return . Skip
2045 {-# INLINE_LATE stepOuter #-}
2046 stepOuter _ SplitOnSuffixSeqInit = do
2051 then skip $ SplitOnSuffixSeqEmpty fs state
2054 pat <- liftIO $ A.unsafeIndexIO 0 patArr
2055 skip $ SplitOnSuffixSeqSingleInit fs state pat
2056 else if SIZE_OF(a) * patLen
2057 <= sizeOf (undefined :: Word)
2058 then skip $ SplitOnSuffixSeqWordInit fs state
2060 (rb, rhead) <- liftIO $ RB.new patLen
2061 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
2062 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
2064 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
2066 ---------------------------
2068 ---------------------------
2070 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
2071 initial >>= skip . nextAfterInit nextGen
2073 ---------------------------
2075 ---------------------------
2077 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
2078 res <- step (adaptState gst) st
2081 let jump c = SplitOnSuffixSeqEmpty c s
2085 FL.Partial fs -> done fs
2086 FL.Done b -> return b
2087 yieldProceed jump b1
2088 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
2095 stepOuter _ SplitOnSuffixSeqDone = return Stop
2101 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
2102 res <- step (adaptState gst) st
2104 Yield x s -> processYieldSingle pat x s fs
2105 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
2108 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2109 res <- step (adaptState gst) st
2111 Yield x s -> processYieldSingle pat x s fs
2112 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2115 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2117 ---------------------------
2118 -- Short Pattern - Shift Or
2119 ---------------------------
2121 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2123 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2124 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2125 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2126 r <- fstep fs (toEnum $ fromIntegral old)
2128 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2130 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
2133 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
2134 res <- step (adaptState gst) st0
2137 let wrd = addToWord 0 x
2138 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
2140 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2142 let jump c = SplitOnSuffixSeqWordInit c s
2144 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
2150 go !_ !idx !wrd !st !fs = do
2151 res <- step (adaptState gst) st
2154 let jump c = SplitOnSuffixSeqWordInit c s
2155 let wrd1 = addToWord wrd x
2156 r <- if withSep then fstep fs x else return $ FL.Partial fs
2160 then go SPEC (idx + 1) wrd1 s fs1
2161 else if wrd1 .&. wordMask /= wordPat
2162 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2163 else do done fs >>= yieldProceed jump
2164 FL.Done b -> yieldProceed jump b
2165 Skip s -> go SPEC idx wrd s fs
2166 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2168 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2169 go SPEC wrd0 st0 fs0
2174 go !_ !wrd !st !fs = do
2175 res <- step (adaptState gst) st
2178 let jump c = SplitOnSuffixSeqWordInit c s
2179 wrd1 = addToWord wrd x
2180 old = (wordMask .&. wrd)
2181 `shiftR` (elemBits * (patLen - 1))
2185 else fstep fs (toEnum $ fromIntegral old)
2188 if wrd1 .&. wordMask == wordPat
2189 then done fs1 >>= yieldProceed jump
2190 else go SPEC wrd1 s fs1
2191 FL.Done b -> yieldProceed jump b
2192 Skip s -> go SPEC wrd s fs
2194 if wrd .&. wordMask == wordPat
2199 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2200 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2202 -------------------------------
2203 -- General Pattern - Karp Rabin
2204 -------------------------------
2206 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2207 res <- step (adaptState gst) st0
2210 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2211 r <- if withSep then fstep fs x else return $ FL.Partial fs
2214 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2216 let rst = RB.startOf rb
2217 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2219 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2222 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2223 go SPEC 1 rh0 st0 fs0
2227 go !_ !idx !rh st !fs = do
2228 res <- step (adaptState gst) st
2231 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2232 r <- if withSep then fstep fs x else return $ FL.Partial fs
2236 then go SPEC (idx + 1) rh1 s fs1
2238 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2239 !ringHash = fld addCksum 0 rb
2240 in if ringHash == patHash
2241 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2242 else SplitOnSuffixSeqKRLoop
2243 fs1 s rb rh1 ringHash
2245 let rst = RB.startOf rb
2246 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2248 Skip s -> go SPEC idx rh s fs
2250 -- do not issue a blank segment when we end at pattern
2251 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2256 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2257 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2259 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2260 go SPEC fs0 st0 rh0 cksum0
2264 go !_ !fs !st !rh !cksum = do
2265 res <- step (adaptState gst) st
2268 old <- liftIO $ peek rh
2269 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2270 let cksum1 = deltaCksum cksum old x
2271 r <- if withSep then fstep fs x else fstep fs old
2274 if cksum1 /= patHash
2275 then go SPEC fs1 s rh1 cksum1
2276 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2278 let rst = RB.startOf rb
2279 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2281 Skip s -> go SPEC fs s rh cksum
2283 if RB.unsafeEqArray rb rh patArr
2288 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2289 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2291 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2292 if RB.unsafeEqArray rb rh patArr
2295 let rst = RB.startOf rb
2296 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2298 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2300 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2302 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2303 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2304 old <- liftIO $ peek rh
2305 let rh1 = RB.advance rb rh
2308 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2310 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2313------------------------------------------------------------------------------
2314-- Nested Container Transformation
2315------------------------------------------------------------------------------
2317{-# ANN type SplitState Fuse #-}
2318data SplitState s arr
2320 | SplitBuffering s arr
2321 | SplitSplitting s arr
2322 | SplitYielding arr (SplitState s arr)
2325-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2326-- split using a splitBy like combinator. The Fold would consume upto the
2327-- separator and return any leftover which can then be fed to the next fold.
2329-- We can revisit this once we have partial folds/parsers.
2331-- | Performs infix separator style splitting.
2332{-# INLINE_NORMAL splitInnerBy #-}
2335 => (f a -> m (f a, Maybe (f a))) -- splitter
2336 -> (f a -> f a -> m (f a)) -- joiner
2339splitInnerBy splitter joiner (Stream step1 state1) =
2340 Stream step (SplitInitial state1)
2344 {-# INLINE_LATE step #-}
2345 step gst (SplitInitial st) = do
2349 (x1, mx2) <- splitter x
2350 return $ case mx2 of
2351 Nothing -> Skip (SplitBuffering s x1)
2352 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2353 Skip s -> return $ Skip (SplitInitial s)
2356 step gst (SplitBuffering st buf) = do
2360 (x1, mx2) <- splitter x
2361 buf' <- joiner buf x1
2362 return $ case mx2 of
2363 Nothing -> Skip (SplitBuffering s buf')
2364 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2365 Skip s -> return $ Skip (SplitBuffering s buf)
2366 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2368 step _ (SplitSplitting st buf) = do
2369 (x1, mx2) <- splitter buf
2370 return $ case mx2 of
2371 Nothing -> Skip $ SplitBuffering st x1
2372 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2374 step _ (SplitYielding x next) = return $ Yield x next
2375 step _ SplitFinishing = return Stop
2377-- | Performs infix separator style splitting.
2378{-# INLINE_NORMAL splitInnerBySuffix #-}
2380 :: (Monad m, Eq (f a), Monoid (f a))
2381 => (f a -> m (f a, Maybe (f a))) -- splitter
2382 -> (f a -> f a -> m (f a)) -- joiner
2385splitInnerBySuffix splitter joiner (Stream step1 state1) =
2386 Stream step (SplitInitial state1)
2390 {-# INLINE_LATE step #-}
2391 step gst (SplitInitial st) = do
2395 (x1, mx2) <- splitter x
2396 return $ case mx2 of
2397 Nothing -> Skip (SplitBuffering s x1)
2398 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2399 Skip s -> return $ Skip (SplitInitial s)
2402 step gst (SplitBuffering st buf) = do
2406 (x1, mx2) <- splitter x
2407 buf' <- joiner buf x1
2408 return $ case mx2 of
2409 Nothing -> Skip (SplitBuffering s buf')
2410 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2411 Skip s -> return $ Skip (SplitBuffering s buf)
2415 else Skip (SplitYielding buf SplitFinishing)
2417 step _ (SplitSplitting st buf) = do
2418 (x1, mx2) <- splitter buf
2419 return $ case mx2 of
2420 Nothing -> Skip $ SplitBuffering st x1
2421 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2423 step _ (SplitYielding x next) = return $ Yield x next
2424 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