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 (peek, sizeOf)
159import Fusion.Plugin.Types (Fuse(..))
160import GHC.Types (SPEC(..))
162import Streamly.Internal.Data.Array.Unboxed.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.Unboxed (Unboxed)
170import Streamly.Internal.Data.Unfold.Type (Unfold(..))
172import qualified Streamly.Internal.Data.Array.Unboxed.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.Unboxed 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{-# RULES "zipWithM xs xs"
427 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
429{-# INLINE zipWith #-}
430zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
431zipWith f = zipWithM (\a b -> return (f a b))
433------------------------------------------------------------------------------
435------------------------------------------------------------------------------
437{-# INLINE_NORMAL mergeByM #-}
440 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
441mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
442 Stream step (Just ta, Just tb, Nothing, Nothing)
444 {-# INLINE_LATE step #-}
446 -- one of the values is missing, and the corresponding stream is running
447 step gst (Just sa, sb, Nothing, b) = do
450 Yield a sa' -> Skip (Just sa', sb, Just a, b)
451 Skip sa' -> Skip (Just sa', sb, Nothing, b)
452 Stop -> Skip (Nothing, sb, Nothing, b)
454 step gst (sa, Just sb, a, Nothing) = do
457 Yield b sb' -> Skip (sa, Just sb', a, Just b)
458 Skip sb' -> Skip (sa, Just sb', a, Nothing)
459 Stop -> Skip (sa, Nothing, a, Nothing)
461 -- both the values are available
462 step _ (sa, sb, Just a, Just b) = do
465 GT -> Yield b (sa, sb, Just a, Nothing)
466 _ -> Yield a (sa, sb, Nothing, Just b)
468 -- one of the values is missing, corresponding stream is done
469 step _ (Nothing, sb, Nothing, Just b) =
470 return $ Yield b (Nothing, sb, Nothing, Nothing)
472 step _ (sa, Nothing, Just a, Nothing) =
473 return $ Yield a (sa, Nothing, Nothing, Nothing)
475 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
477{-# INLINE mergeBy #-}
480 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
481mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
483-------------------------------------------------------------------------------
484-- Intersection of sorted streams
485-------------------------------------------------------------------------------
487-- Assuming the streams are sorted in ascending order
488{-# INLINE_NORMAL intersectBySorted #-}
489intersectBySorted :: Monad m
490 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
491intersectBySorted cmp (Stream stepa ta) (Stream stepb tb) =
493 ( ta -- left stream state
494 , tb -- right stream state
495 , Nothing -- left value
496 , Nothing -- right value
501 {-# INLINE_LATE step #-}
502 -- step 1, fetch the first value
503 step gst (sa, sb, Nothing, b) = do
506 Yield a sa' -> Skip (sa', sb, Just a, b) -- step 2/3
507 Skip sa' -> Skip (sa', sb, Nothing, b)
510 -- step 2, fetch the second value
511 step gst (sa, sb, a@(Just _), Nothing) = do
514 Yield b sb' -> Skip (sa, sb', a, Just b) -- step 3
515 Skip sb' -> Skip (sa, sb', a, Nothing)
518 -- step 3, compare the two values
519 step _ (sa, sb, Just a, Just b) = do
522 GT -> Skip (sa, sb, Just a, Nothing) -- step 2
523 LT -> Skip (sa, sb, Nothing, Just b) -- step 1
524 EQ -> Yield a (sa, sb, Nothing, Just b) -- step 1
526------------------------------------------------------------------------------
527-- Combine N Streams - unfoldMany
528------------------------------------------------------------------------------
530data ConcatUnfoldInterleaveState o i =
531 ConcatUnfoldInterleaveOuter o [i]
532 | ConcatUnfoldInterleaveInner o [i]
533 | ConcatUnfoldInterleaveInnerL [i] [i]
534 | ConcatUnfoldInterleaveInnerR [i] [i]
536-- XXX use arrays to store state instead of lists?
538-- XXX In general we can use different scheduling strategies e.g. how to
539-- schedule the outer vs inner loop or assigning weights to different streams
540-- or outer and inner loops.
542-- After a yield, switch to the next stream. Do not switch streams on Skip.
543-- Yield from outer stream switches to the inner stream.
545-- There are two choices here, (1) exhaust the outer stream first and then
546-- start yielding from the inner streams, this is much simpler to implement,
547-- (2) yield at least one element from an inner stream before going back to
548-- outer stream and opening the next stream from it.
550-- Ideally, we need some scheduling bias to inner streams vs outer stream.
551-- Maybe we can configure the behavior.
553-- XXX Instead of using "concatPairsWith wSerial" we can implement an N-way
554-- interleaving CPS combinator which behaves like unfoldManyInterleave. Instead
555-- of pairing up the streams we just need to go yielding one element from each
556-- stream and storing the remaining streams and then keep doing rounds through
557-- those in a round robin fashion. This would be much like wAsync.
559-- See 'Streamly.Internal.Data.Stream.unfoldInterleave' documentation for more
562{-# INLINE_NORMAL unfoldManyInterleave #-}
563unfoldManyInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
564unfoldManyInterleave (Unfold istep inject) (Stream ostep ost) =
565 Stream step (ConcatUnfoldInterleaveOuter ost [])
569 {-# INLINE_LATE step #-}
570 step gst (ConcatUnfoldInterleaveOuter o ls) = do
571 r <- ostep (adaptState gst) o
575 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
576 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
577 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
579 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
580 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
583 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
584 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
585 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
587 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
588 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
589 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
591 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
594 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
595 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
596 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
598 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
599 step _ (ConcatUnfoldInterleaveInnerR ls []) =
600 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
602 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
605 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
606 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
607 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
609-- XXX In general we can use different scheduling strategies e.g. how to
610-- schedule the outer vs inner loop or assigning weights to different streams
611-- or outer and inner loops.
613-- This could be inefficient if the tasks are too small.
615-- Compared to unfoldManyInterleave this one switches streams on Skips.
617{-# INLINE_NORMAL unfoldManyRoundRobin #-}
618unfoldManyRoundRobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
619unfoldManyRoundRobin (Unfold istep inject) (Stream ostep ost) =
620 Stream step (ConcatUnfoldInterleaveOuter ost [])
622 {-# INLINE_LATE step #-}
623 step gst (ConcatUnfoldInterleaveOuter o ls) = do
624 r <- ostep (adaptState gst) o
628 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
629 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
630 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
632 step _ (ConcatUnfoldInterleaveInner o []) =
633 return $ Skip (ConcatUnfoldInterleaveOuter o [])
635 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
638 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
639 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
640 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
642 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
643 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
644 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
646 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
649 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
650 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
651 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
653 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
654 step _ (ConcatUnfoldInterleaveInnerR ls []) =
655 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
657 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
660 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
661 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
662 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
664------------------------------------------------------------------------------
665-- Combine N Streams - interpose
666------------------------------------------------------------------------------
668{-# ANN type InterposeSuffixState Fuse #-}
669data InterposeSuffixState s1 i1 =
670 InterposeSuffixFirst s1
671 -- | InterposeSuffixFirstYield s1 i1
672 | InterposeSuffixFirstInner s1 i1
673 | InterposeSuffixSecond s1
675-- Note that if an unfolded layer turns out to be nil we still emit the
676-- separator effect. An alternate behavior could be to emit the separator
677-- effect only if at least one element has been yielded by the unfolding.
678-- However, that becomes a bit complicated, so we have chosen the former
680{-# INLINE_NORMAL interposeSuffix #-}
683 => m c -> Unfold m b c -> Stream m b -> Stream m c
686 (Unfold istep1 inject1) (Stream step1 state1) =
687 Stream step (InterposeSuffixFirst state1)
691 {-# INLINE_LATE step #-}
692 step gst (InterposeSuffixFirst s1) = do
693 r <- step1 (adaptState gst) s1
697 i `seq` return (Skip (InterposeSuffixFirstInner s i))
698 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
699 Skip s -> return $ Skip (InterposeSuffixFirst s)
703 step _ (InterposeSuffixFirstYield s1 i1) = do
706 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
707 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
708 Stop -> Skip (InterposeSuffixFirst s1)
711 step _ (InterposeSuffixFirstInner s1 i1) = do
714 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
715 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
716 Stop -> Skip (InterposeSuffixSecond s1)
718 step _ (InterposeSuffixSecond s1) = do
720 return $ Yield r (InterposeSuffixFirst s1)
722{-# ANN type InterposeState Fuse #-}
723data InterposeState s1 i1 a =
725 -- | InterposeFirstYield s1 i1
726 | InterposeFirstInner s1 i1
727 | InterposeFirstInject s1
728 -- | InterposeFirstBuf s1 i1
729 | InterposeSecondYield s1 i1
730 -- -- | InterposeSecondYield s1 i1 a
731 -- -- | InterposeFirstResume s1 i1 a
733-- Note that this only interposes the pure values, we may run many effects to
734-- generate those values as some effects may not generate anything (Skip).
735{-# INLINE_NORMAL interpose #-}
736interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
739 (Unfold istep1 inject1) (Stream step1 state1) =
740 Stream step (InterposeFirst state1)
744 {-# INLINE_LATE step #-}
745 step gst (InterposeFirst s1) = do
746 r <- step1 (adaptState gst) s1
750 i `seq` return (Skip (InterposeFirstInner s i))
751 -- i `seq` return (Skip (InterposeFirstYield s i))
752 Skip s -> return $ Skip (InterposeFirst s)
756 step _ (InterposeFirstYield s1 i1) = do
759 Yield x i' -> Yield x (InterposeFirstInner s1 i')
760 Skip i' -> Skip (InterposeFirstYield s1 i')
761 Stop -> Skip (InterposeFirst s1)
764 step _ (InterposeFirstInner s1 i1) = do
767 Yield x i' -> Yield x (InterposeFirstInner s1 i')
768 Skip i' -> Skip (InterposeFirstInner s1 i')
769 Stop -> Skip (InterposeFirstInject s1)
771 step gst (InterposeFirstInject s1) = do
772 r <- step1 (adaptState gst) s1
776 -- i `seq` return (Skip (InterposeFirstBuf s i))
777 i `seq` return (Skip (InterposeSecondYield s i))
778 Skip s -> return $ Skip (InterposeFirstInject s)
782 step _ (InterposeFirstBuf s1 i1) = do
785 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
786 Skip i' -> Skip (InterposeFirstBuf s1 i')
791 step _ (InterposeSecondYield s1 i1 v) = do
793 return $ Yield r (InterposeFirstResume s1 i1 v)
795 step _ (InterposeSecondYield s1 i1) = do
797 return $ Yield r (InterposeFirstInner s1 i1)
800 step _ (InterposeFirstResume s1 i1 v) = do
801 return $ Yield v (InterposeFirstInner s1 i1)
804------------------------------------------------------------------------------
805-- Combine N Streams - intercalate
806------------------------------------------------------------------------------
808data ICUState s1 s2 i1 i2 =
813 | ICUFirstInner s1 s2 i1
814 | ICUSecondInner s1 s2 i2
815 | ICUFirstOnlyInner s1 i1
816 | ICUSecondOnlyInner s2 i2
818-- | Interleave streams (full streams, not the elements) unfolded from two
819-- input streams and concat. Stop when the first stream stops. If the second
820-- stream ends before the first one then first stream still keeps running alone
821-- without any interleaving with the second stream.
823-- [a1, a2, ... an] [b1, b2 ...]
824-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
825-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
826-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
828{-# INLINE_NORMAL gintercalateSuffix #-}
831 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
833 (Unfold istep1 inject1) (Stream step1 state1)
834 (Unfold istep2 inject2) (Stream step2 state2) =
835 Stream step (ICUFirst state1 state2)
839 {-# INLINE_LATE step #-}
840 step gst (ICUFirst s1 s2) = do
841 r <- step1 (adaptState gst) s1
845 i `seq` return (Skip (ICUFirstInner s s2 i))
846 Skip s -> return $ Skip (ICUFirst s s2)
849 step gst (ICUFirstOnly s1) = do
850 r <- step1 (adaptState gst) s1
854 i `seq` return (Skip (ICUFirstOnlyInner s i))
855 Skip s -> return $ Skip (ICUFirstOnly s)
858 step _ (ICUFirstInner s1 s2 i1) = do
861 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
862 Skip i' -> Skip (ICUFirstInner s1 s2 i')
863 Stop -> Skip (ICUSecond s1 s2)
865 step _ (ICUFirstOnlyInner s1 i1) = do
868 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
869 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
870 Stop -> Skip (ICUFirstOnly s1)
872 step gst (ICUSecond s1 s2) = do
873 r <- step2 (adaptState gst) s2
877 i `seq` return (Skip (ICUSecondInner s1 s i))
878 Skip s -> return $ Skip (ICUSecond s1 s)
879 Stop -> return $ Skip (ICUFirstOnly s1)
881 step _ (ICUSecondInner s1 s2 i2) = do
884 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
885 Skip i' -> Skip (ICUSecondInner s1 s2 i')
886 Stop -> Skip (ICUFirst s1 s2)
888 step _ (ICUSecondOnly _s2) = undefined
889 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
891data ICALState s1 s2 i1 i2 a =
893 -- | ICALFirstYield s1 s2 i1
894 | ICALFirstInner s1 s2 i1
896 | ICALFirstOnlyInner s1 i1
897 | ICALSecondInject s1 s2
898 | ICALFirstInject s1 s2 i2
899 -- | ICALFirstBuf s1 s2 i1 i2
900 | ICALSecondInner s1 s2 i1 i2
901 -- -- | ICALSecondInner s1 s2 i1 i2 a
902 -- -- | ICALFirstResume s1 s2 i1 i2 a
904-- | Interleave streams (full streams, not the elements) unfolded from two
905-- input streams and concat. Stop when the first stream stops. If the second
906-- stream ends before the first one then first stream still keeps running alone
907-- without any interleaving with the second stream.
909-- [a1, a2, ... an] [b1, b2 ...]
910-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
911-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
912-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
914{-# INLINE_NORMAL gintercalate #-}
917 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
919 (Unfold istep1 inject1) (Stream step1 state1)
920 (Unfold istep2 inject2) (Stream step2 state2) =
921 Stream step (ICALFirst state1 state2)
925 {-# INLINE_LATE step #-}
926 step gst (ICALFirst s1 s2) = do
927 r <- step1 (adaptState gst) s1
931 i `seq` return (Skip (ICALFirstInner s s2 i))
932 -- i `seq` return (Skip (ICALFirstYield s s2 i))
933 Skip s -> return $ Skip (ICALFirst s s2)
937 step _ (ICALFirstYield s1 s2 i1) = do
940 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
941 Skip i' -> Skip (ICALFirstYield s1 s2 i')
942 Stop -> Skip (ICALFirst s1 s2)
945 step _ (ICALFirstInner s1 s2 i1) = do
948 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
949 Skip i' -> Skip (ICALFirstInner s1 s2 i')
950 Stop -> Skip (ICALSecondInject s1 s2)
952 step gst (ICALFirstOnly s1) = do
953 r <- step1 (adaptState gst) s1
957 i `seq` return (Skip (ICALFirstOnlyInner s i))
958 Skip s -> return $ Skip (ICALFirstOnly s)
961 step _ (ICALFirstOnlyInner s1 i1) = do
964 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
965 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
966 Stop -> Skip (ICALFirstOnly s1)
968 -- We inject the second stream even before checking if the first stream
969 -- would yield any more elements. There is no clear choice whether we
970 -- should do this before or after that. Doing it after may make the state
971 -- machine a bit simpler though.
972 step gst (ICALSecondInject s1 s2) = do
973 r <- step2 (adaptState gst) s2
977 i `seq` return (Skip (ICALFirstInject s1 s i))
978 Skip s -> return $ Skip (ICALSecondInject s1 s)
979 Stop -> return $ Skip (ICALFirstOnly s1)
981 step gst (ICALFirstInject s1 s2 i2) = do
982 r <- step1 (adaptState gst) s1
986 i `seq` return (Skip (ICALSecondInner s s2 i i2))
987 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
988 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
992 step _ (ICALFirstBuf s1 s2 i1 i2) = do
995 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
996 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
999 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
1002 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
1003 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
1004 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
1007 step _ (ICALSecondInner s1 s2 i1 i2) = do
1010 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
1011 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
1012 Stop -> Skip (ICALFirstInner s1 s2 i1)
1013 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
1016 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
1017 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
1020------------------------------------------------------------------------------
1022------------------------------------------------------------------------------
1024{-# ANN type FIterState Fuse #-}
1025data FIterState s f m a b
1027 | forall fs. FIterStream s (fs -> a -> m (FL.Step fs b)) fs (fs -> m b)
1028 | FIterYield b (FIterState s f m a b)
1031{-# INLINE_NORMAL foldIterateM #-}
1033 Monad m => (b -> m (FL.Fold m a b)) -> m b -> Stream m a -> Stream m b
1034foldIterateM func seed0 (Stream step state) =
1035 Stream stepOuter (FIterInit state seed0)
1039 {-# INLINE iterStep #-}
1040 iterStep from st fstep extract = do
1045 FL.Partial fs -> FIterStream st fstep fs extract
1046 FL.Done fb -> FIterYield fb $ FIterInit st (return fb)
1048 {-# INLINE_LATE stepOuter #-}
1049 stepOuter _ (FIterInit st seed) = do
1050 (FL.Fold fstep initial extract) <- seed >>= func
1051 iterStep initial st fstep extract
1052 stepOuter gst (FIterStream st fstep fs extract) = do
1053 r <- step (adaptState gst) st
1056 iterStep (fstep fs x) s fstep extract
1057 Skip s -> return $ Skip $ FIterStream s fstep fs extract
1060 return $ Skip $ FIterYield b FIterStop
1061 stepOuter _ (FIterYield a next) = return $ Yield a next
1062 stepOuter _ FIterStop = return Stop
1064{-# ANN type CIterState Fuse #-}
1065data CIterState s f fs b
1068 | CIterYield b (CIterState s f fs b)
1071-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
1072-- much more efficient due to stream fusion.
1075{-# INLINE_NORMAL refoldIterateM #-}
1077 Monad m => Refold m b a b -> m b -> Stream m a -> Stream m b
1078refoldIterateM (Refold fstep finject fextract) initial (Stream step state) =
1079 Stream stepOuter (CIterInit state initial)
1083 {-# INLINE iterStep #-}
1084 iterStep st action = do
1089 FL.Partial fs -> CIterConsume st fs
1090 FL.Done fb -> CIterYield fb $ CIterInit st (return fb)
1092 {-# INLINE_LATE stepOuter #-}
1093 stepOuter _ (CIterInit st action) = do
1094 iterStep st (action >>= finject)
1095 stepOuter gst (CIterConsume st fs) = do
1096 r <- step (adaptState gst) st
1098 Yield x s -> iterStep s (fstep fs x)
1099 Skip s -> return $ Skip $ CIterConsume s fs
1102 return $ Skip $ CIterYield b CIterStop
1103 stepOuter _ (CIterYield a next) = return $ Yield a next
1104 stepOuter _ CIterStop = return Stop
1106-- "n" elements at the end are dropped by the fold.
1107{-# INLINE sliceBy #-}
1108sliceBy :: Monad m => Fold m a Int -> Int -> Refold m (Int, Int) a (Int, Int)
1109sliceBy (Fold step1 initial1 extract1) n = Refold step inject extract
1113 inject (i, len) = do
1116 Partial s -> Partial $ Tuple' (i + len + n) s
1117 Done l -> Done (i, l)
1119 step (Tuple' i s) x = do
1122 Partial s1 -> Partial $ Tuple' i s1
1123 Done len -> Done (i, len)
1125 extract (Tuple' i s) = (i,) <$> extract1 s
1127{-# INLINE sliceOnSuffix #-}
1128sliceOnSuffix :: Monad m => (a -> Bool) -> Stream m a -> Stream m (Int, Int)
1129sliceOnSuffix predicate =
1130 -- Scan the stream with the given refold
1132 (sliceBy (FL.takeEndBy_ predicate FL.length) 1)
1135------------------------------------------------------------------------------
1137------------------------------------------------------------------------------
1139{-# ANN type ParseChunksState Fuse #-}
1140data ParseChunksState x inpBuf st pst =
1141 ParseChunksInit inpBuf st
1142 | ParseChunksInitBuf inpBuf
1143 | ParseChunksInitLeftOver inpBuf
1144 | ParseChunksStream st inpBuf !pst
1145 | ParseChunksStop inpBuf !pst
1146 | ParseChunksBuf inpBuf st inpBuf !pst
1147 | ParseChunksExtract inpBuf inpBuf !pst
1148 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1150-- XXX This is in fact parseMany1 (a la foldMany1). Do we need a parseMany as
1152{-# INLINE_NORMAL parseMany #-}
1158parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1159 Stream stepOuter (ParseChunksInit [] state)
1163 {-# INLINE_LATE stepOuter #-}
1164 -- Buffer is empty, get the first element from the stream, initialize the
1165 -- fold and then go to stream processing loop.
1166 stepOuter gst (ParseChunksInit [] st) = do
1167 r <- step (adaptState gst) st
1173 return $ Skip $ ParseChunksBuf [x] s [] ps
1175 let next = ParseChunksInit [x] s
1176 in return $ Skip $ ParseChunksYield pb next
1177 PRD.IError err -> throwM $ ParseError err
1178 Skip s -> return $ Skip $ ParseChunksInit [] s
1181 -- Buffer is not empty, go to buffered processing loop
1182 stepOuter _ (ParseChunksInit src st) = do
1186 return $ Skip $ ParseChunksBuf src st [] ps
1188 let next = ParseChunksInit src st
1189 in return $ Skip $ ParseChunksYield pb next
1190 PRD.IError err -> throwM $ ParseError err
1192 -- This is simplified ParseChunksInit
1193 stepOuter _ (ParseChunksInitBuf src) = do
1197 return $ Skip $ ParseChunksExtract src [] ps
1199 let next = ParseChunksInitBuf src
1200 in return $ Skip $ ParseChunksYield pb next
1201 PRD.IError err -> throwM $ ParseError err
1203 -- XXX we just discard any leftover input at the end
1204 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1206 -- Buffer is empty, process elements from the stream
1207 stepOuter gst (ParseChunksStream st buf pst) = do
1208 r <- step (adaptState gst) st
1213 PR.Partial 0 pst1 ->
1214 return $ Skip $ ParseChunksStream s [] pst1
1215 PR.Partial n pst1 -> do
1216 assert (n <= length (x:buf)) (return ())
1217 let src0 = Prelude.take n (x:buf)
1218 src = Prelude.reverse src0
1219 return $ Skip $ ParseChunksBuf src s [] pst1
1220 PR.Continue 0 pst1 ->
1221 return $ Skip $ ParseChunksStream s (x:buf) pst1
1222 PR.Continue n pst1 -> do
1223 assert (n <= length (x:buf)) (return ())
1224 let (src0, buf1) = splitAt n (x:buf)
1225 src = Prelude.reverse src0
1226 return $ Skip $ ParseChunksBuf src s buf1 pst1
1229 ParseChunksYield b (ParseChunksInit [] s)
1231 assert (n <= length (x:buf)) (return ())
1232 let src = Prelude.reverse (Prelude.take n (x:buf))
1234 ParseChunksYield b (ParseChunksInit src s)
1235 PR.Error err -> throwM $ ParseError err
1236 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1237 Stop -> return $ Skip $ ParseChunksStop buf pst
1239 -- go back to stream processing mode
1240 stepOuter _ (ParseChunksBuf [] s buf pst) =
1241 return $ Skip $ ParseChunksStream s buf pst
1243 -- buffered processing loop
1244 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1247 PR.Partial 0 pst1 ->
1248 return $ Skip $ ParseChunksBuf xs s [] pst1
1249 PR.Partial n pst1 -> do
1250 assert (n <= length (x:buf)) (return ())
1251 let src0 = Prelude.take n (x:buf)
1252 src = Prelude.reverse src0 ++ xs
1253 return $ Skip $ ParseChunksBuf src s [] pst1
1254 PR.Continue 0 pst1 ->
1255 return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1256 PR.Continue n pst1 -> do
1257 assert (n <= length (x:buf)) (return ())
1258 let (src0, buf1) = splitAt n (x:buf)
1259 src = Prelude.reverse src0 ++ xs
1260 return $ Skip $ ParseChunksBuf src s buf1 pst1
1262 return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1264 assert (n <= length (x:buf)) (return ())
1265 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1266 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1267 PR.Error err -> throwM $ ParseError err
1269 -- This is simplified ParseChunksBuf
1270 stepOuter _ (ParseChunksExtract [] buf pst) =
1271 return $ Skip $ ParseChunksStop buf pst
1273 stepOuter _ (ParseChunksExtract (x:xs) buf pst) = do
1276 PR.Partial 0 pst1 ->
1277 return $ Skip $ ParseChunksExtract xs [] pst1
1278 PR.Partial n pst1 -> do
1279 assert (n <= length (x:buf)) (return ())
1280 let src0 = Prelude.take n (x:buf)
1281 src = Prelude.reverse src0 ++ xs
1282 return $ Skip $ ParseChunksExtract src [] pst1
1283 PR.Continue 0 pst1 ->
1284 return $ Skip $ ParseChunksExtract xs (x:buf) pst1
1285 PR.Continue n pst1 -> do
1286 assert (n <= length (x:buf)) (return ())
1287 let (src0, buf1) = splitAt n (x:buf)
1288 src = Prelude.reverse src0 ++ xs
1289 return $ Skip $ ParseChunksExtract src buf1 pst1
1291 return $ Skip $ ParseChunksYield b (ParseChunksInitBuf xs)
1293 assert (n <= length (x:buf)) (return ())
1294 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1295 return $ Skip $ ParseChunksYield b (ParseChunksInitBuf src)
1296 PR.Error err -> throwM $ ParseError err
1298 -- This is simplified ParseChunksExtract
1299 stepOuter _ (ParseChunksStop buf pst) = do
1302 PR.Partial _ _ -> error "Bug: parseMany: Partial in extract"
1304 error "parseMany: extract, Continue 0 creates infinite loop"
1305 PR.Continue n pst1 -> do
1306 assert (n <= length buf) (return ())
1307 let (src0, buf1) = splitAt n buf
1308 src = Prelude.reverse src0
1309 return $ Skip $ ParseChunksExtract src buf1 pst1
1312 ParseChunksYield b (ParseChunksInitLeftOver [])
1314 assert (n <= length buf) (return ())
1315 let src = Prelude.reverse (Prelude.take n buf)
1317 ParseChunksYield b (ParseChunksInitBuf src)
1318 PR.Error err -> throwM $ ParseError err
1320 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1322{-# ANN type ConcatParseState Fuse #-}
1323data ConcatParseState b inpBuf st p m a =
1324 ConcatParseInit inpBuf st p
1325 | ConcatParseInitBuf inpBuf p
1326 | ConcatParseInitLeftOver inpBuf
1327 | forall s. ConcatParseStop
1328 inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1329 | forall s. ConcatParseStream
1330 st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1331 | forall s. ConcatParseBuf
1332 inpBuf st inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1333 | forall s. ConcatParseExtract
1334 inpBuf inpBuf (s -> a -> m (PRD.Step s b)) s (s -> m (PRD.Step s b))
1335 | ConcatParseYield b (ConcatParseState b inpBuf st p m a)
1337-- XXX Review the changes
1338{-# INLINE_NORMAL parseIterate #-}
1341 => (b -> PRD.Parser m a b)
1345parseIterate func seed (Stream step state) =
1346 Stream stepOuter (ConcatParseInit [] state (func seed))
1350 {-# INLINE_LATE stepOuter #-}
1351 -- Buffer is empty, go to stream processing loop
1352 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1356 return $ Skip $ ConcatParseStream st [] pstep ps extract
1358 let next = ConcatParseInit [] st (func pb)
1359 in return $ Skip $ ConcatParseYield pb next
1360 PRD.IError err -> throwM $ ParseError err
1362 -- Buffer is not empty, go to buffered processing loop
1363 stepOuter _ (ConcatParseInit src st
1364 (PRD.Parser pstep initial extract)) = do
1368 return $ Skip $ ConcatParseBuf src st [] pstep ps extract
1370 let next = ConcatParseInit src st (func pb)
1371 in return $ Skip $ ConcatParseYield pb next
1372 PRD.IError err -> throwM $ ParseError err
1374 -- This is simplified ConcatParseInit
1375 stepOuter _ (ConcatParseInitBuf src
1376 (PRD.Parser pstep initial extract)) = do
1380 return $ Skip $ ConcatParseExtract src [] pstep ps extract
1382 let next = ConcatParseInitBuf src (func pb)
1383 in return $ Skip $ ConcatParseYield pb next
1384 PRD.IError err -> throwM $ ParseError err
1386 -- XXX we just discard any leftover input at the end
1387 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1389 -- Buffer is empty process elements from the stream
1390 stepOuter gst (ConcatParseStream st buf pstep pst extract) = do
1391 r <- step (adaptState gst) st
1396 PR.Partial 0 pst1 ->
1397 return $ Skip $ ConcatParseStream s [] pstep pst1 extract
1398 PR.Partial n pst1 -> do
1399 assert (n <= length (x:buf)) (return ())
1400 let src0 = Prelude.take n (x:buf)
1401 src = Prelude.reverse src0
1402 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1403 -- PR.Continue 0 pst1 ->
1404 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1405 PR.Continue n pst1 -> do
1406 assert (n <= length (x:buf)) (return ())
1407 let (src0, buf1) = splitAt n (x:buf)
1408 src = Prelude.reverse src0
1409 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1410 -- XXX Specialize for Stop 0 common case?
1412 assert (n <= length (x:buf)) (return ())
1413 let src = Prelude.reverse (Prelude.take n (x:buf))
1415 ConcatParseYield b (ConcatParseInit src s (func b))
1416 PR.Error err -> throwM $ ParseError err
1417 Skip s -> return $ Skip $ ConcatParseStream s buf pstep pst extract
1418 Stop -> return $ Skip $ ConcatParseStop buf pstep pst extract
1420 -- go back to stream processing mode
1421 stepOuter _ (ConcatParseBuf [] s buf pstep ps extract) =
1422 return $ Skip $ ConcatParseStream s buf pstep ps extract
1424 -- buffered processing loop
1425 stepOuter _ (ConcatParseBuf (x:xs) s buf pstep pst extract) = do
1428 PR.Partial 0 pst1 ->
1429 return $ Skip $ ConcatParseBuf xs s [] pstep pst1 extract
1430 PR.Partial n pst1 -> do
1431 assert (n <= length (x:buf)) (return ())
1432 let src0 = Prelude.take n (x:buf)
1433 src = Prelude.reverse src0 ++ xs
1434 return $ Skip $ ConcatParseBuf src s [] pstep pst1 extract
1435 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1436 PR.Continue n pst1 -> do
1437 assert (n <= length (x:buf)) (return ())
1438 let (src0, buf1) = splitAt n (x:buf)
1439 src = Prelude.reverse src0 ++ xs
1440 return $ Skip $ ConcatParseBuf src s buf1 pstep pst1 extract
1441 -- XXX Specialize for Stop 0 common case?
1443 assert (n <= length (x:buf)) (return ())
1444 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1445 return $ Skip $ ConcatParseYield b
1446 (ConcatParseInit src s (func b))
1447 PR.Error err -> throwM $ ParseError err
1449 -- This is simplified ConcatParseBuf
1450 stepOuter _ (ConcatParseExtract [] buf pstep pst extract) =
1451 return $ Skip $ ConcatParseStop buf pstep pst extract
1453 stepOuter _ (ConcatParseExtract (x:xs) buf pstep pst extract) = do
1456 PR.Partial 0 pst1 ->
1457 return $ Skip $ ConcatParseExtract xs [] pstep pst1 extract
1458 PR.Partial n pst1 -> do
1459 assert (n <= length (x:buf)) (return ())
1460 let src0 = Prelude.take n (x:buf)
1461 src = Prelude.reverse src0 ++ xs
1462 return $ Skip $ ConcatParseExtract src [] pstep pst1 extract
1463 PR.Continue 0 pst1 ->
1464 return $ Skip $ ConcatParseExtract xs (x:buf) pstep pst1 extract
1465 PR.Continue n pst1 -> do
1466 assert (n <= length (x:buf)) (return ())
1467 let (src0, buf1) = splitAt n (x:buf)
1468 src = Prelude.reverse src0 ++ xs
1469 return $ Skip $ ConcatParseExtract src buf1 pstep pst1 extract
1471 return $ Skip $ ConcatParseYield b (ConcatParseInitBuf xs (func b))
1473 assert (n <= length (x:buf)) (return ())
1474 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1475 return $ Skip $ ConcatParseYield b (ConcatParseInitBuf src (func b))
1476 PR.Error err -> throwM $ ParseError err
1478 -- This is simplified ConcatParseExtract
1479 stepOuter _ (ConcatParseStop buf pstep pst extract) = do
1482 PR.Partial _ _ -> error "Bug: parseIterate: Partial in extract"
1484 error "parseIterate: extract, Continue 0 creates infinite loop"
1485 PR.Continue n pst1 -> do
1486 assert (n <= length buf) (return ())
1487 let (src0, buf1) = splitAt n buf
1488 src = Prelude.reverse src0
1489 return $ Skip $ ConcatParseExtract src buf1 pstep pst1 extract
1492 ConcatParseYield b (ConcatParseInitLeftOver [])
1494 assert (n <= length buf) (return ())
1495 let src = Prelude.reverse (Prelude.take n buf)
1497 ConcatParseYield b (ConcatParseInitBuf src (func b))
1498 PR.Error err -> throwM $ ParseError err
1500 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1502------------------------------------------------------------------------------
1504------------------------------------------------------------------------------
1506data GroupByState st fs a b
1509 | GroupingInitWith st !a
1510 | GroupingDoWith st !fs !a
1511 | GroupingYield !b (GroupByState st fs a b)
1514{-# INLINE_NORMAL groupsBy #-}
1521groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1523groupsBy cmp (Fold fstep initial done) (Stream step state) =
1524 Stream stepOuter (GroupingInit state)
1528 {-# INLINE_LATE stepOuter #-}
1529 stepOuter _ (GroupingInit st) = do
1530 -- XXX Note that if the stream stops without yielding a single element
1531 -- in the group we discard the "initial" effect.
1535 FL.Partial s -> Skip $ GroupingDo st s
1536 FL.Done b -> Yield b $ GroupingInit st
1537 stepOuter gst (GroupingDo st fs) = do
1538 res <- step (adaptState gst) st
1543 FL.Partial fs1 -> go SPEC x s fs1
1544 FL.Done b -> return $ Yield b (GroupingInit s)
1545 Skip s -> return $ Skip $ GroupingDo s fs
1550 go !_ prev stt !acc = do
1551 res <- step (adaptState gst) stt
1558 FL.Partial fs1 -> go SPEC prev s fs1
1559 FL.Done b -> return $ Yield b (GroupingInit s)
1562 return $ Yield r (GroupingInitWith s x)
1563 Skip s -> go SPEC prev s acc
1564 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1565 stepOuter _ (GroupingInitWith st x) = do
1569 FL.Partial s -> Skip $ GroupingDoWith st s x
1570 FL.Done b -> Yield b $ GroupingInitWith st x
1571 stepOuter gst (GroupingDoWith st fs prev) = do
1572 res <- fstep fs prev
1574 FL.Partial fs1 -> go SPEC st fs1
1575 FL.Done b -> return $ Yield b (GroupingInit st)
1579 -- XXX code duplicated from the previous equation
1581 res <- step (adaptState gst) stt
1588 FL.Partial fs1 -> go SPEC s fs1
1589 FL.Done b -> return $ Yield b (GroupingInit s)
1592 return $ Yield r (GroupingInitWith s x)
1593 Skip s -> go SPEC s acc
1594 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1595 stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1596 stepOuter _ GroupingDone = return Stop
1598{-# INLINE_NORMAL groupsRollingBy #-}
1599groupsRollingBy :: Monad m
1605groupsRollingBy eq fld = parseMany (PRD.groupByRolling eq fld)
1607groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
1608 Stream stepOuter (GroupingInit state)
1612 {-# INLINE_LATE stepOuter #-}
1613 stepOuter _ (GroupingInit st) = do
1614 -- XXX Note that if the stream stops without yielding a single element
1615 -- in the group we discard the "initial" effect.
1619 FL.Partial fs -> Skip $ GroupingDo st fs
1620 FL.Done fb -> Yield fb $ GroupingInit st
1621 stepOuter gst (GroupingDo st fs) = do
1622 res <- step (adaptState gst) st
1627 FL.Partial fs1 -> go SPEC x s fs1
1628 FL.Done fb -> return $ Yield fb (GroupingInit s)
1629 Skip s -> return $ Skip $ GroupingDo s fs
1634 go !_ prev stt !acc = do
1635 res <- step (adaptState gst) stt
1642 FL.Partial fs1 -> go SPEC x s fs1
1643 FL.Done b -> return $ Yield b (GroupingInit s)
1646 return $ Yield r (GroupingInitWith s x)
1647 Skip s -> go SPEC prev s acc
1648 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1649 stepOuter _ (GroupingInitWith st x) = do
1653 FL.Partial s -> Skip $ GroupingDoWith st s x
1654 FL.Done b -> Yield b $ GroupingInitWith st x
1655 stepOuter gst (GroupingDoWith st fs previous) = do
1656 res <- fstep fs previous
1658 FL.Partial s -> go SPEC previous st s
1659 FL.Done b -> return $ Yield b (GroupingInit st)
1663 -- XXX GHC: groupsBy has one less parameter in this go loop and it
1664 -- fuses. However, groupsRollingBy does not fuse, removing the prev
1665 -- parameter makes it fuse. Something needs to be fixed in GHC. The
1666 -- workaround for this is noted in the comments below.
1667 go !_ prev !stt !acc = do
1668 res <- step (adaptState gst) stt
1675 FL.Partial fs1 -> go SPEC x s fs1
1676 FL.Done b -> return $ Yield b (GroupingInit st)
1680 return $ Yield r (GroupingInitWith s x)
1682 -- The code above does not let groupBy fuse. We use the
1683 -- alternative code below instead. Instead of jumping
1684 -- to GroupingInitWith state, we unroll the code of
1685 -- GroupingInitWith state here to help GHC with stream
1692 FL.Partial fsi -> GroupingDoWith s fsi x
1693 FL.Done b -> GroupingYield b (GroupingInit s)
1694 Skip s -> go SPEC prev s acc
1695 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1696 stepOuter _ (GroupingYield r next) = return $ Yield r next
1697 stepOuter _ GroupingDone = return Stop
1699------------------------------------------------------------------------------
1700-- Splitting - by a predicate
1701------------------------------------------------------------------------------
1703data WordsByState st fs b
1707 | WordsByYield !b (WordsByState st fs b)
1709{-# INLINE_NORMAL wordsBy #-}
1710wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1711wordsBy predicate (Fold fstep initial done) (Stream step state) =
1712 Stream stepOuter (WordsByInit state)
1716 {-# INLINE_LATE stepOuter #-}
1717 stepOuter _ (WordsByInit st) = do
1721 FL.Partial s -> Skip $ WordsByDo st s
1722 FL.Done b -> Yield b (WordsByInit st)
1724 stepOuter gst (WordsByDo st fs) = do
1725 res <- step (adaptState gst) st
1733 FL.Partial fs1 -> Skip $ WordsByDo s fs1
1734 FL.Done b -> Yield b (WordsByInit s)
1738 FL.Partial fs1 -> go SPEC s fs1
1739 FL.Done b -> return $ Yield b (WordsByInit s)
1740 Skip s -> return $ Skip $ WordsByDo s fs
1746 res <- step (adaptState gst) stt
1753 return $ Yield r (WordsByInit s)
1755 -- The above code does not fuse well. Need to check why
1756 -- GHC is not able to simplify it well. Using the code
1757 -- below, instead of jumping through the WordsByInit
1758 -- state always, we directly go to WordsByDo state in
1759 -- the common case of Partial.
1765 FL.Partial fs1 -> WordsByDo s fs1
1766 FL.Done b -> WordsByYield b (WordsByInit s)
1770 FL.Partial fs1 -> go SPEC s fs1
1771 FL.Done b -> return $ Yield b (WordsByInit s)
1772 Skip s -> go SPEC s acc
1773 Stop -> done acc >>= \r -> return $ Yield r WordsByDone
1775 stepOuter _ WordsByDone = return Stop
1777 stepOuter _ (WordsByYield b next) = return $ Yield b next
1779------------------------------------------------------------------------------
1780-- Splitting on a sequence
1781------------------------------------------------------------------------------
1783-- String search algorithms:
1784-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1787-- TODO can we unify the splitting operations using a splitting configuration
1788-- like in the split package.
1790data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1791data SplitOptions = SplitOptions
1792 { style :: SplitStyle
1793 , withSep :: Bool -- ^ keep the separators in output
1794 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1795 -- , trimHead :: Bool -- ^ drop blank at head
1796 -- , trimTail :: Bool -- ^ drop blank at tail
1800-- XXX using "fs" as the last arg in Constructors may simplify the code a bit,
1801-- because we can use the constructor directly without having to create "jump"
1803{-# ANN type SplitOnSeqState Fuse #-}
1804data SplitOnSeqState rb rh ck w fs s b x =
1806 | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1809 | SplitOnSeqEmpty !fs s
1811 | SplitOnSeqSingle !fs s x
1813 | SplitOnSeqWordInit !fs s
1814 | SplitOnSeqWordLoop !w s !fs
1815 | SplitOnSeqWordDone Int !fs !w
1817 | SplitOnSeqKRInit Int !fs s rb !rh
1818 | SplitOnSeqKRLoop fs s rb !rh !ck
1819 | SplitOnSeqKRCheck fs s rb !rh
1820 | SplitOnSeqKRDone Int !fs rb !rh
1822 | SplitOnSeqReinit (fs -> SplitOnSeqState rb rh ck w fs s b x)
1824{-# INLINE_NORMAL splitOnSeq #-}
1826 :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a)
1831splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1832 Stream stepOuter SplitOnSeqInit
1836 patLen = A.length patArr
1837 maxIndex = patLen - 1
1838 elemBits = SIZE_OF(a) * 8
1840 -- For word pattern case
1842 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1845 elemMask = (1 `shiftL` elemBits) - 1
1848 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1850 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1852 -- For Rabin-Karp search
1853 k = 2891336453 :: Word32
1856 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1858 deltaCksum cksum old new =
1859 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1861 -- XXX shall we use a random starting hash or 1 instead of 0?
1862 patHash = A.foldl' addCksum 0 patArr
1864 skip = return . Skip
1866 nextAfterInit nextGen stepRes =
1868 FL.Partial s -> nextGen s
1869 FL.Done b -> SplitOnSeqYield b (SplitOnSeqReinit nextGen)
1871 {-# INLINE yieldProceed #-}
1872 yieldProceed nextGen fs =
1873 initial >>= skip . SplitOnSeqYield fs . nextAfterInit nextGen
1875 {-# INLINE_LATE stepOuter #-}
1876 stepOuter _ SplitOnSeqInit = do
1881 then return $ Skip $ SplitOnSeqEmpty acc state
1884 pat <- liftIO $ A.unsafeIndexIO 0 patArr
1885 return $ Skip $ SplitOnSeqSingle acc state pat
1886 else if SIZE_OF(a) * patLen
1887 <= sizeOf (undefined :: Word)
1888 then return $ Skip $ SplitOnSeqWordInit acc state
1890 (rb, rhead) <- liftIO $ RB.new patLen
1891 skip $ SplitOnSeqKRInit 0 acc state rb rhead
1892 FL.Done b -> skip $ SplitOnSeqYield b SplitOnSeqInit
1894 stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1896 ---------------------------
1898 ---------------------------
1900 stepOuter _ (SplitOnSeqReinit nextGen) =
1901 initial >>= skip . nextAfterInit nextGen
1903 ---------------------------
1905 ---------------------------
1907 stepOuter gst (SplitOnSeqEmpty acc st) = do
1908 res <- step (adaptState gst) st
1914 FL.Partial acc1 -> done acc1
1915 FL.Done b -> return b
1916 let jump c = SplitOnSeqEmpty c s
1917 in yieldProceed jump b1
1918 Skip s -> skip (SplitOnSeqEmpty acc s)
1925 stepOuter _ SplitOnSeqDone = return Stop
1931 stepOuter gst (SplitOnSeqSingle fs st pat) = do
1932 res <- step (adaptState gst) st
1935 let jump c = SplitOnSeqSingle c s pat
1937 then done fs >>= yieldProceed jump
1941 FL.Partial fs1 -> skip $ jump fs1
1942 FL.Done b -> yieldProceed jump b
1943 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1946 return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1948 ---------------------------
1949 -- Short Pattern - Shift Or
1950 ---------------------------
1952 stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1954 skip $ SplitOnSeqYield r SplitOnSeqDone
1955 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1956 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1957 r <- fstep fs (toEnum $ fromIntegral old)
1959 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1961 let jump c = SplitOnSeqWordDone (n - 1) c wrd
1964 stepOuter gst (SplitOnSeqWordInit fs st0) =
1970 go !_ !idx !wrd !st = do
1971 res <- step (adaptState gst) st
1974 let wrd1 = addToWord wrd x
1977 if wrd1 .&. wordMask == wordPat
1979 let jump c = SplitOnSeqWordInit c s
1980 done fs >>= yieldProceed jump
1981 else skip $ SplitOnSeqWordLoop wrd1 s fs
1982 else go SPEC (idx + 1) wrd1 s
1983 Skip s -> go SPEC idx wrd s
1986 then skip $ SplitOnSeqWordDone idx fs wrd
1989 skip $ SplitOnSeqYield r SplitOnSeqDone
1991 stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1992 go SPEC wrd0 st0 fs0
1997 go !_ !wrd !st !fs = do
1998 res <- step (adaptState gst) st
2001 let jump c = SplitOnSeqWordInit c s
2002 wrd1 = addToWord wrd x
2003 old = (wordMask .&. wrd)
2004 `shiftR` (elemBits * (patLen - 1))
2005 r <- fstep fs (toEnum $ fromIntegral old)
2007 FL.Partial fs1 -> do
2008 if wrd1 .&. wordMask == wordPat
2009 then done fs1 >>= yieldProceed jump
2010 else go SPEC wrd1 s fs1
2011 FL.Done b -> yieldProceed jump b
2012 Skip s -> go SPEC wrd s fs
2013 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
2015 -------------------------------
2016 -- General Pattern - Karp Rabin
2017 -------------------------------
2019 stepOuter gst (SplitOnSeqKRInit idx fs st rb rh) = do
2020 res <- step (adaptState gst) st
2023 rh1 <- liftIO $ RB.unsafeInsert rb rh x
2026 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2027 let !ringHash = fld addCksum 0 rb
2028 if ringHash == patHash
2029 then skip $ SplitOnSeqKRCheck fs s rb rh1
2030 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
2031 else skip $ SplitOnSeqKRInit (idx + 1) fs s rb rh1
2032 Skip s -> skip $ SplitOnSeqKRInit idx fs s rb rh
2034 skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
2036 -- XXX The recursive "go" is more efficient than the state based recursion
2037 -- code commented out below. Perhaps its more efficient because of
2038 -- factoring out "rb" outside the loop.
2040 stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
2041 go SPEC fs0 st0 rh0 cksum0
2045 go !_ !fs !st !rh !cksum = do
2046 res <- step (adaptState gst) st
2049 old <- liftIO $ peek rh
2050 let cksum1 = deltaCksum cksum old x
2053 FL.Partial fs1 -> do
2054 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2055 if cksum1 == patHash
2056 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
2057 else go SPEC fs1 s rh1 cksum1
2059 let rst = RB.startOf rb
2060 jump c = SplitOnSeqKRInit 0 c s rb rst
2062 Skip s -> go SPEC fs s rh cksum
2063 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
2065 -- XXX The following code is 5 times slower compared to the recursive loop
2066 -- based code above. Need to investigate why. One possibility is that the
2067 -- go loop above does not thread around the ring buffer (rb). This code may
2068 -- be causing the state to bloat and getting allocated on each iteration.
2069 -- We can check the cmm/asm code to confirm. If so a good GHC solution to
2070 -- such problem is needed. One way to avoid this could be to use unboxed
2073 stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
2074 res <- step (adaptState gst) st
2077 old <- liftIO $ peek rh
2078 let cksum1 = deltaCksum cksum old x
2080 if (cksum1 == patHash)
2083 skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
2085 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2086 skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
2087 Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
2088 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
2091 stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
2092 if RB.unsafeEqArray rb rh patArr
2095 let rst = RB.startOf rb
2096 jump c = SplitOnSeqKRInit 0 c st rb rst
2098 else skip $ SplitOnSeqKRLoop fs st rb rh patHash
2100 stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
2102 skip $ SplitOnSeqYield r SplitOnSeqDone
2103 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
2104 old <- liftIO $ peek rh
2105 let rh1 = RB.advance rb rh
2108 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
2110 let jump c = SplitOnSeqKRDone (n - 1) c rb rh1
2113{-# ANN type SplitOnSuffixSeqState Fuse #-}
2114data SplitOnSuffixSeqState rb rh ck w fs s b x =
2115 SplitOnSuffixSeqInit
2116 | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
2117 | SplitOnSuffixSeqDone
2119 | SplitOnSuffixSeqEmpty !fs s
2121 | SplitOnSuffixSeqSingleInit !fs s x
2122 | SplitOnSuffixSeqSingle !fs s x
2124 | SplitOnSuffixSeqWordInit !fs s
2125 | SplitOnSuffixSeqWordLoop !w s !fs
2126 | SplitOnSuffixSeqWordDone Int !fs !w
2128 | SplitOnSuffixSeqKRInit Int !fs s rb !rh
2129 | SplitOnSuffixSeqKRInit1 !fs s rb !rh
2130 | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
2131 | SplitOnSuffixSeqKRCheck fs s rb !rh
2132 | SplitOnSuffixSeqKRDone Int !fs rb !rh
2134 | SplitOnSuffixSeqReinit
2135 (fs -> SplitOnSuffixSeqState rb rh ck w fs s b x)
2137{-# INLINE_NORMAL splitOnSuffixSeq #-}
2139 :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a)
2145splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2146 Stream stepOuter SplitOnSuffixSeqInit
2150 patLen = A.length patArr
2151 maxIndex = patLen - 1
2152 elemBits = SIZE_OF(a) * 8
2154 -- For word pattern case
2156 wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2159 elemMask = (1 `shiftL` elemBits) - 1
2162 wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2164 addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2166 nextAfterInit nextGen stepRes =
2168 FL.Partial s -> nextGen s
2170 SplitOnSuffixSeqYield b (SplitOnSuffixSeqReinit nextGen)
2172 {-# INLINE yieldProceed #-}
2173 yieldProceed nextGen fs =
2174 initial >>= skip . SplitOnSuffixSeqYield fs . nextAfterInit nextGen
2176 -- For single element pattern case
2177 {-# INLINE processYieldSingle #-}
2178 processYieldSingle pat x s fs = do
2179 let jump c = SplitOnSuffixSeqSingleInit c s pat
2182 r <- if withSep then fstep fs x else return $ FL.Partial fs
2185 FL.Partial fs1 -> done fs1
2186 FL.Done b -> return b
2187 yieldProceed jump b1
2191 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2192 FL.Done b -> yieldProceed jump b
2194 -- For Rabin-Karp search
2195 k = 2891336453 :: Word32
2198 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2200 deltaCksum cksum old new =
2201 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2203 -- XXX shall we use a random starting hash or 1 instead of 0?
2204 patHash = A.foldl' addCksum 0 patArr
2206 skip = return . Skip
2208 {-# INLINE_LATE stepOuter #-}
2209 stepOuter _ SplitOnSuffixSeqInit = do
2214 then skip $ SplitOnSuffixSeqEmpty fs state
2217 pat <- liftIO $ A.unsafeIndexIO 0 patArr
2218 skip $ SplitOnSuffixSeqSingleInit fs state pat
2219 else if SIZE_OF(a) * patLen
2220 <= sizeOf (undefined :: Word)
2221 then skip $ SplitOnSuffixSeqWordInit fs state
2223 (rb, rhead) <- liftIO $ RB.new patLen
2224 skip $ SplitOnSuffixSeqKRInit 0 fs state rb rhead
2225 FL.Done fb -> skip $ SplitOnSuffixSeqYield fb SplitOnSuffixSeqInit
2227 stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
2229 ---------------------------
2231 ---------------------------
2233 stepOuter _ (SplitOnSuffixSeqReinit nextGen) =
2234 initial >>= skip . nextAfterInit nextGen
2236 ---------------------------
2238 ---------------------------
2240 stepOuter gst (SplitOnSuffixSeqEmpty acc st) = do
2241 res <- step (adaptState gst) st
2244 let jump c = SplitOnSuffixSeqEmpty c s
2248 FL.Partial fs -> done fs
2249 FL.Done b -> return b
2250 yieldProceed jump b1
2251 Skip s -> skip (SplitOnSuffixSeqEmpty acc s)
2258 stepOuter _ SplitOnSuffixSeqDone = return Stop
2264 stepOuter gst (SplitOnSuffixSeqSingleInit fs st pat) = do
2265 res <- step (adaptState gst) st
2267 Yield x s -> processYieldSingle pat x s fs
2268 Skip s -> skip $ SplitOnSuffixSeqSingleInit fs s pat
2271 stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2272 res <- step (adaptState gst) st
2274 Yield x s -> processYieldSingle pat x s fs
2275 Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2278 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2280 ---------------------------
2281 -- Short Pattern - Shift Or
2282 ---------------------------
2284 stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2286 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2287 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2288 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2289 r <- fstep fs (toEnum $ fromIntegral old)
2291 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2293 let jump c = SplitOnSuffixSeqWordDone (n - 1) c wrd
2296 stepOuter gst (SplitOnSuffixSeqWordInit fs0 st0) = do
2297 res <- step (adaptState gst) st0
2300 let wrd = addToWord 0 x
2301 r <- if withSep then fstep fs0 x else return $ FL.Partial fs0
2303 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2305 let jump c = SplitOnSuffixSeqWordInit c s
2307 Skip s -> skip (SplitOnSuffixSeqWordInit fs0 s)
2313 go !_ !idx !wrd !st !fs = do
2314 res <- step (adaptState gst) st
2317 let jump c = SplitOnSuffixSeqWordInit c s
2318 let wrd1 = addToWord wrd x
2319 r <- if withSep then fstep fs x else return $ FL.Partial fs
2323 then go SPEC (idx + 1) wrd1 s fs1
2324 else if wrd1 .&. wordMask /= wordPat
2325 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2326 else do done fs >>= yieldProceed jump
2327 FL.Done b -> yieldProceed jump b
2328 Skip s -> go SPEC idx wrd s fs
2329 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2331 stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2332 go SPEC wrd0 st0 fs0
2337 go !_ !wrd !st !fs = do
2338 res <- step (adaptState gst) st
2341 let jump c = SplitOnSuffixSeqWordInit c s
2342 wrd1 = addToWord wrd x
2343 old = (wordMask .&. wrd)
2344 `shiftR` (elemBits * (patLen - 1))
2348 else fstep fs (toEnum $ fromIntegral old)
2351 if wrd1 .&. wordMask == wordPat
2352 then done fs1 >>= yieldProceed jump
2353 else go SPEC wrd1 s fs1
2354 FL.Done b -> yieldProceed jump b
2355 Skip s -> go SPEC wrd s fs
2357 if wrd .&. wordMask == wordPat
2362 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2363 else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2365 -------------------------------
2366 -- General Pattern - Karp Rabin
2367 -------------------------------
2369 stepOuter gst (SplitOnSuffixSeqKRInit idx0 fs st0 rb rh0) = do
2370 res <- step (adaptState gst) st0
2373 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2374 r <- if withSep then fstep fs x else return $ FL.Partial fs
2377 skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2379 let rst = RB.startOf rb
2380 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2382 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 fs s rb rh0
2385 stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2386 go SPEC 1 rh0 st0 fs0
2390 go !_ !idx !rh st !fs = do
2391 res <- step (adaptState gst) st
2394 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2395 r <- if withSep then fstep fs x else return $ FL.Partial fs
2399 then go SPEC (idx + 1) rh1 s fs1
2401 let fld = RB.unsafeFoldRing (RB.ringBound rb)
2402 !ringHash = fld addCksum 0 rb
2403 in if ringHash == patHash
2404 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2405 else SplitOnSuffixSeqKRLoop
2406 fs1 s rb rh1 ringHash
2408 let rst = RB.startOf rb
2409 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2411 Skip s -> go SPEC idx rh s fs
2413 -- do not issue a blank segment when we end at pattern
2414 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2419 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2420 else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2422 stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2423 go SPEC fs0 st0 rh0 cksum0
2427 go !_ !fs !st !rh !cksum = do
2428 res <- step (adaptState gst) st
2431 old <- liftIO $ peek rh
2432 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2433 let cksum1 = deltaCksum cksum old x
2434 r <- if withSep then fstep fs x else fstep fs old
2437 if cksum1 /= patHash
2438 then go SPEC fs1 s rh1 cksum1
2439 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2441 let rst = RB.startOf rb
2442 jump c = SplitOnSuffixSeqKRInit 0 c s rb rst
2444 Skip s -> go SPEC fs s rh cksum
2446 if RB.unsafeEqArray rb rh patArr
2451 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2452 else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2454 stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2455 if RB.unsafeEqArray rb rh patArr
2458 let rst = RB.startOf rb
2459 jump c = SplitOnSuffixSeqKRInit 0 c st rb rst
2461 else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2463 stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2465 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2466 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2467 old <- liftIO $ peek rh
2468 let rh1 = RB.advance rb rh
2471 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2473 let jump c = SplitOnSuffixSeqKRDone (n - 1) c rb rh1
2476------------------------------------------------------------------------------
2477-- Nested Container Transformation
2478------------------------------------------------------------------------------
2480{-# ANN type SplitState Fuse #-}
2481data SplitState s arr
2483 | SplitBuffering s arr
2484 | SplitSplitting s arr
2485 | SplitYielding arr (SplitState s arr)
2488-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2489-- split using a splitBy like combinator. The Fold would consume upto the
2490-- separator and return any leftover which can then be fed to the next fold.
2492-- We can revisit this once we have partial folds/parsers.
2494-- | Performs infix separator style splitting.
2495{-# INLINE_NORMAL splitInnerBy #-}
2498 => (f a -> m (f a, Maybe (f a))) -- splitter
2499 -> (f a -> f a -> m (f a)) -- joiner
2502splitInnerBy splitter joiner (Stream step1 state1) =
2503 Stream step (SplitInitial state1)
2507 {-# INLINE_LATE step #-}
2508 step gst (SplitInitial st) = do
2512 (x1, mx2) <- splitter x
2513 return $ case mx2 of
2514 Nothing -> Skip (SplitBuffering s x1)
2515 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2516 Skip s -> return $ Skip (SplitInitial s)
2519 step gst (SplitBuffering st buf) = do
2523 (x1, mx2) <- splitter x
2524 buf' <- joiner buf x1
2525 return $ case mx2 of
2526 Nothing -> Skip (SplitBuffering s buf')
2527 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2528 Skip s -> return $ Skip (SplitBuffering s buf)
2529 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2531 step _ (SplitSplitting st buf) = do
2532 (x1, mx2) <- splitter buf
2533 return $ case mx2 of
2534 Nothing -> Skip $ SplitBuffering st x1
2535 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2537 step _ (SplitYielding x next) = return $ Yield x next
2538 step _ SplitFinishing = return Stop
2540-- | Performs infix separator style splitting.
2541{-# INLINE_NORMAL splitInnerBySuffix #-}
2543 :: (Monad m, Eq (f a), Monoid (f a))
2544 => (f a -> m (f a, Maybe (f a))) -- splitter
2545 -> (f a -> f a -> m (f a)) -- joiner
2548splitInnerBySuffix splitter joiner (Stream step1 state1) =
2549 Stream step (SplitInitial state1)
2553 {-# INLINE_LATE step #-}
2554 step gst (SplitInitial st) = do
2558 (x1, mx2) <- splitter x
2559 return $ case mx2 of
2560 Nothing -> Skip (SplitBuffering s x1)
2561 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2562 Skip s -> return $ Skip (SplitInitial s)
2565 step gst (SplitBuffering st buf) = do
2569 (x1, mx2) <- splitter x
2570 buf' <- joiner buf x1
2571 return $ case mx2 of
2572 Nothing -> Skip (SplitBuffering s buf')
2573 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2574 Skip s -> return $ Skip (SplitBuffering s buf)
2578 else Skip (SplitYielding buf SplitFinishing)
2580 step _ (SplitSplitting st buf) = do
2581 (x1, mx2) <- splitter buf
2582 return $ case mx2 of
2583 Nothing -> Skip $ SplitBuffering st x1
2584 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2586 step _ (SplitYielding x next) = return $ Yield x next
2587 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