@@ -83,6 +83,7 @@ module Streamly.Internal.Data.Stream.StreamK
83 , foldlMx'
83 , foldlMx'
85 , foldBreak
85 , foldBreak
87 -- ** Specialized Folds
88 -- ** Specialized Folds
@@ -174,17 +175,21 @@ module Streamly.Internal.Data.Stream.StreamK
178+import Control.Exception (assert)
179+import Control.Monad.Catch (MonadThrow, throwM)
177import Control.Monad.Trans.Class (MonadTrans(lift))
180import Control.Monad.Trans.Class (MonadTrans(lift))
178import Control.Monad (void, join)
181import Control.Monad (void, join)
179import Streamly.Internal.Data.SVar.Type (adaptState, defState)
182import Streamly.Internal.Data.SVar.Type (adaptState, defState)
181import qualified Streamly.Internal.Data.Fold.Type as FL
184import qualified Streamly.Internal.Data.Fold.Type as FL
185+import qualified Streamly.Internal.Data.Parser.ParserD.Type as PR
186+import qualified Prelude
183import Prelude
188import Prelude
184 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
189 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
185 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
190 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
186 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
191 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
187− foldr1, (!!), replicate, reverse, concatMap, iterate)
192+ foldr1, (!!), replicate, reverse, concatMap, iterate, splitAt)
189import Streamly.Internal.Data.Stream.StreamK.Type
194import Streamly.Internal.Data.Stream.StreamK.Type
@@ -979,3 +984,95 @@ withCatchError m h =
979 yieldk a r = yld a (withCatchError r h)
984 yieldk a r = yld a (withCatchError r h)
980 in handle $ run m
985 in handle $ run m
988+-------------------------------------------------------------------------------
990+-------------------------------------------------------------------------------
992+-- Inlined definition.
993+{-# INLINE splitAt #-}
994+splitAt :: Int -> [a] -> ([a],[a])
997+ | otherwise = splitAt' n ls
999+ splitAt' :: Int -> [a] -> ([a], [a])
1000+ splitAt' _ [] = ([], [])
1001+ splitAt' 1 (x:xs) = ([x], xs)
1002+ splitAt' m (x:xs) = (x:xs', xs'')
1004+ (xs', xs'') = splitAt' (m - 1) xs
1006+-- | Run a 'Parser' over a stream and return rest of the Stream.
1007+{-# INLINE_NORMAL parseBreak #-}
1012+ -> m (b, Stream m a)
1013+parseBreak (PR.Parser pstep initial extract) stream = do
1016+ PR.IPartial s -> goStream stream [] s
1017+ PR.IDone b -> return (b, stream)
1018+ PR.IError err -> throwM $ PR.ParseError err
1022+ -- "buf" contains last few items in the stream that we may have to
1025+ -- XXX currently we are using a dumb list based approach for backtracking
1026+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
1027+ -- That will allow us more efficient random back and forth movement.
1028+ goStream st buf !pst =
1031+ return (b, fromList buf)
1032+ single x = yieldk x nil
1036+ PR.Partial 0 s -> goStream r [] s
1037+ PR.Partial n s -> do
1038+ assert (n <= length (x:buf)) (return ())
1039+ let src0 = Prelude.take n (x:buf)
1040+ src = Prelude.reverse src0
1042+ PR.Continue 0 s -> goStream r (x:buf) s
1043+ PR.Continue n s -> do
1044+ assert (n <= length (x:buf)) (return ())
1045+ let (src0, buf1) = splitAt n (x:buf)
1046+ src = Prelude.reverse src0
1048+ PR.Done 0 b -> return (b, r)
1050+ assert (n <= length (x:buf)) (return ())
1051+ let src0 = Prelude.take n (x:buf)
1052+ src = Prelude.reverse src0
1053+ return (b, serial (fromList src) r)
1054+ PR.Error err -> throwM $ PR.ParseError err
1055+ in foldStream defState yieldk single stop st
1057+ goBuf st buf [] !pst = goStream st buf pst
1058+ goBuf st buf (x:xs) !pst = do
1059+ pRes <- pstep pst x
1061+ PR.Partial 0 s -> goBuf st [] xs s
1062+ PR.Partial n s -> do
1063+ assert (n <= length (x:buf)) (return ())
1064+ let src0 = Prelude.take n (x:buf)
1065+ src = Prelude.reverse src0 ++ xs
1067+ PR.Continue 0 s -> goBuf st (x:buf) xs s
1068+ PR.Continue n s -> do
1069+ assert (n <= length (x:buf)) (return ())
1070+ let (src0, buf1) = splitAt n (x:buf)
1071+ src = Prelude.reverse src0 ++ xs
1072+ goBuf st buf1 src s
1074+ assert (n <= length (x:buf)) (return ())
1075+ let src0 = Prelude.take n (x:buf)
1076+ src = Prelude.reverse src0
1077+ return (b, serial (fromList src) st)
1078+ PR.Error err -> throwM $ PR.ParseError err