on master help sign in
Use chunked parsing by default
commit4840f43d6269f82a2830fc834de01876aee47471 authorHarendra Kumar <harendra@composewell.com> dateTue 14 Feb 2023, 18:35 (4 years ago) parent96d222e
11 files changed+491−292
benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs+29−26 core/src/Streamly/Data/Parser/ParserK.hs+6−15 core/src/Streamly/Data/Stream.hs+1−1 core/src/Streamly/Data/Stream/StreamK.hs+2−1 core/src/Streamly/Internal/Data/Parser/Chunked.hs−1 core/src/Streamly/Internal/Data/Parser/ParserD.hs−4 core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs−179 core/src/Streamly/Internal/Data/Parser/ParserK/Type.hs+291−56 core/src/Streamly/Internal/Data/Producer/Source.hs+10−8 core/src/Streamly/Internal/Data/Stream/StreamK.hs+151 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+1−1
benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs+29−26
@@ -15,7 +15,10 @@ module Main
1515 ) where
1616
1717import Control.DeepSeq (NFData(..))
18+import Control.Monad.IO.Class (MonadIO)
1819import Data.Foldable (asum)
20+import Streamly.Data.Array (Array, Unbox)
21+import Streamly.Data.Stream.StreamK (StreamK)
1922import Streamly.Internal.Data.Parser (ParseError(..))
2023import Streamly.Internal.Data.Stream.StreamD (Stream)
2124import System.Random (randomRIO)
@@ -25,11 +28,11 @@ import Prelude hiding
2528import qualified Control.Applicative as AP
2629import qualified Data.Foldable as F
2730import qualified Data.Traversable as TR
28−import qualified Streamly.Data.Parser.ParserK as ParserK
29−import qualified Streamly.Internal.Data.Fold as FL
30−import qualified Streamly.Internal.Data.Parser.ParserK.Type as PR
31−import qualified Streamly.Internal.Data.Parser.ParserD as PRD
32−import qualified Streamly.Internal.Data.Stream.StreamD as Stream
31+import qualified Streamly.Data.Stream as Stream
32+import qualified Streamly.Data.Fold as FL
33+import qualified Streamly.Data.Parser as PRD
34+import qualified Streamly.Data.Parser.ParserK as PR
35+import qualified Streamly.Internal.Data.Stream.StreamK as StreamK
3336
3437import Gauge
3538import Streamly.Benchmark.Common
@@ -53,48 +56,48 @@ sourceUnfoldrM value n = Stream.unfoldrM step n
5356{-# INLINE benchIOSink #-}
5457benchIOSink
5558 :: NFData b
56− => Int -> String -> (Stream IO Int -> IO b) -> Benchmark
59+ => Int -> String -> (StreamK IO (Array Int) -> IO b) -> Benchmark
5760benchIOSink value name f =
58− bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
61+ bench name $ nfIO $ randomRIO (1,1) >>= f . StreamK.fromStream . Stream.arraysOf 32000 . sourceUnfoldrM value
5962
6063-------------------------------------------------------------------------------
6164-- Parsers
6265-------------------------------------------------------------------------------
6366
64−#define PARSE_OP (Stream.parse . PRD.fromParserK)
67+#define PARSE_OP StreamK.parseKChunks
6568
6669{-# INLINE one #-}
67−one :: Monad m => Int -> Stream m Int -> m (Either ParseError (Maybe Int))
68−one value = Stream.parse (ParserK.toParser p)
70+one :: MonadIO m => Int -> StreamK m (Array Int) -> m (Either ParseError (Maybe Int))
71+one value = StreamK.parseKChunks p
6972
7073 where
7174
7275 p = do
73− m <- ParserK.fromFold FL.one
76+ m <- PR.fromFold FL.one
7477 case m of
7578 Just i -> if i >= value then pure m else p
7679 Nothing -> pure Nothing
7780
7881{-# INLINE satisfy #-}
79−satisfy :: Monad m => (a -> Bool) -> PR.Parser a m a
80−satisfy = PRD.toParserK . PRD.satisfy
82+satisfy :: (MonadIO m, Unbox a) => (a -> Bool) -> PR.Parser a m a
83+satisfy = PR.fromParser . PRD.satisfy
8184
8285{-# INLINE takeWhile #-}
83−takeWhile :: Monad m => (a -> Bool) -> PR.Parser a m ()
84−takeWhile p = PRD.toParserK $ PRD.takeWhile p FL.drain
86+takeWhile :: (MonadIO m, Unbox a) => (a -> Bool) -> PR.Parser a m ()
87+takeWhile p = PR.fromParser $ PRD.takeWhile p FL.drain
8588
8689{-# INLINE takeWhileK #-}
87−takeWhileK :: Monad m => Int -> Stream m Int -> m (Either ParseError ())
90+takeWhileK :: MonadIO m => Int -> StreamK m (Array Int) -> m (Either ParseError ())
8891takeWhileK value = PARSE_OP (takeWhile (<= value))
8992
9093{-# INLINE splitApp #-}
91−splitApp :: Monad m
92− => Int -> Stream m Int -> m (Either ParseError ((), ()))
94+splitApp :: MonadIO m
95+ => Int -> StreamK m (Array Int) -> m (Either ParseError ((), ()))
9396splitApp value =
9497 PARSE_OP ((,) <$> takeWhile (<= (value `div` 2)) <*> takeWhile (<= value))
9598
9699{-# INLINE sequenceA #-}
97−sequenceA :: Monad m => Int -> Stream m Int -> m Int
100+sequenceA :: MonadIO m => Int -> StreamK m (Array Int) -> m Int
98101sequenceA value xs = do
99102 let parser = satisfy (> 0)
100103 list = Prelude.replicate value parser
@@ -102,14 +105,14 @@ sequenceA value xs = do
102105 return $ Prelude.length x
103106
104107{-# INLINE sequenceA_ #-}
105−sequenceA_ :: Monad m => Int -> Stream m Int -> m (Either ParseError ())
108+sequenceA_ :: MonadIO m => Int -> StreamK m (Array Int) -> m (Either ParseError ())
106109sequenceA_ value xs = do
107110 let parser = satisfy (> 0)
108111 list = Prelude.replicate value parser
109112 PARSE_OP (F.sequenceA_ list) xs
110113
111114{-# INLINE sequence #-}
112−sequence :: Monad m => Int -> Stream m Int -> m Int
115+sequence :: MonadIO m => Int -> StreamK m (Array Int) -> m Int
113116sequence value xs = do
114117 let parser = satisfy (> 0)
115118 list = Prelude.replicate value parser
@@ -117,26 +120,26 @@ sequence value xs = do
117120 return $ Prelude.length x
118121
119122{-# INLINE sequence_ #-}
120−sequence_ :: Monad m => Int -> Stream m Int -> m (Either ParseError ())
123+sequence_ :: MonadIO m => Int -> StreamK m (Array Int) -> m (Either ParseError ())
121124sequence_ value =
122125 let parser = satisfy (> 0)
123126 list = Prelude.replicate value parser
124127 in PARSE_OP (F.sequence_ list)
125128
126129{-# INLINE manyAlt #-}
127−manyAlt :: Monad m => Stream m Int -> m Int
130+manyAlt :: MonadIO m => StreamK m (Array Int) -> m Int
128131manyAlt xs = do
129132 x <- PARSE_OP (AP.many (satisfy (> 0))) xs
130133 return $ Prelude.length x
131134
132135{-# INLINE someAlt #-}
133−someAlt :: Monad m => Stream m Int -> m Int
136+someAlt :: MonadIO m => StreamK m (Array Int) -> m Int
134137someAlt xs = do
135138 x <- PARSE_OP (AP.some (satisfy (> 0))) xs
136139 return $ Prelude.length x
137140
138141{-# INLINE choice #-}
139−choice :: Monad m => Int -> Stream m Int -> m (Either ParseError Int)
142+choice :: MonadIO m => Int -> StreamK m (Array Int) -> m (Either ParseError Int)
140143choice value =
141144 PARSE_OP (asum (replicate value (satisfy (< 0)))
142145 AP.<|> satisfy (> 0))
@@ -159,7 +162,7 @@ o_1_space_serial value =
159162 ]
160163
161164{-# INLINE sepBy1 #-}
162−sepBy1 :: Monad m => Stream m Int -> m Int
165+sepBy1 :: MonadIO m => StreamK m (Array Int) -> m Int
163166sepBy1 xs = do
164167 x <- PARSE_OP (parser (satisfy odd) (satisfy even)) xs
165168 return $ Prelude.length x
core/src/Streamly/Data/Parser/ParserK.hs+6−15
@@ -31,24 +31,15 @@ module Streamly.Data.Parser.ParserK
3131
3232where
3333
34+import Control.Monad.IO.Class (MonadIO)
3435import Streamly.Internal.Data.Fold (Fold)
35−import Streamly.Internal.Data.Parser.ParserK.Type
36+import Streamly.Internal.Data.Unboxed (Unbox)
3637import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
3738
39+import Streamly.Internal.Data.Parser.ParserK.Type
40+
3841-- | Convert a 'Fold' to a 'ParserK'.
3942--
4043{-# INLINE fromFold #-}
41−fromFold :: Monad m => Fold m a b -> ParserK a m b
42−fromFold = ParserD.toParserK . ParserD.fromFold
43−
44−-- | Convert a 'Parser' to a 'ParserK'.
45−--
46−{-# INLINE fromParser #-}
47−fromParser :: Monad m => ParserD.Parser a m b -> ParserK a m b
48−fromParser = ParserD.toParserK
49−
50−-- | Convert a 'ParserK' to a 'Parser'.
51−--
52−{-# INLINE toParser #-}
53−toParser :: Monad m => ParserK a m b -> ParserD.Parser a m b
54−toParser = ParserD.fromParserK
44+fromFold :: (MonadIO m, Unbox a) => Fold m a b -> ParserK a m b
45+fromFold = fromParser . ParserD.fromFold
core/src/Streamly/Data/Stream.hs+1−1
@@ -246,7 +246,7 @@ module Streamly.Data.Stream
246246
247247 -- ** Parsing
248248 , parse
249− , parseBreak
249+ -- , parseBreak
250250
251251 -- -- ** Lazy Right Folds
252252 -- Consuming a stream to build a right associated expression, suitable
core/src/Streamly/Data/Stream/StreamK.hs+2−1
@@ -52,7 +52,8 @@ module Streamly.Data.Stream.StreamK
5252 -- , foldBreak
5353
5454 -- ** Parsing
55− , parseBreak
55+ -- , parseBreak
56+ , parseKBreakChunks
5657
5758 -- * Combining Two Streams
5859 -- ** Appending
core/src/Streamly/Internal/Data/Parser/Chunked.hs−1
@@ -49,7 +49,6 @@ import Streamly.Internal.Data.Unboxed (peekWith, sizeOf, Unbox)
4949import qualified Streamly.Internal.Data.Array as Array
5050import qualified Streamly.Internal.Data.Parser.Chunked.Type as K
5151import qualified Streamly.Internal.Data.Parser.ParserD as D
52− hiding (fromParserK, toParserK)
5352import qualified Streamly.Internal.Data.Stream.StreamK as StreamK
5453import Streamly.Internal.Data.Parser.ParserD (ParseError(..))
5554
core/src/Streamly/Internal/Data/Parser/ParserD.hs−4
@@ -50,10 +50,6 @@ module Streamly.Internal.Data.Parser.ParserD
5050 , Step (..)
5151 , Initial (..)
5252
53− -- * Conversion to/from ParserK
54− , fromParserK
55− , toParserK
56−
5753 -- * Downgrade to Fold
5854 , toFold
5955
core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs−179
@@ -172,10 +172,6 @@ module Streamly.Internal.Data.Parser.ParserD.Type
172172 , ParseError (..)
173173 , rmapM
174174
175− -- * Conversion to/from ParserK
176− , fromParserK
177− , toParserK
178−
179175 -- * Constructors
180176
181177 , fromPure
@@ -216,7 +212,6 @@ import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
216212
217213import qualified Control.Monad.Fail as Fail
218214import qualified Streamly.Internal.Data.Fold.Type as FL
219−import qualified Streamly.Internal.Data.Parser.ParserK.Type as K
220215
221216import Prelude hiding (concatMap, filter)
222217--
@@ -449,180 +444,6 @@ instance Functor m => Functor (Parser a m) where
449444 fmap2 g = fmap (fmap g)
450445 fmap3 g = fmap2 (fmap g)
451446
452−-------------------------------------------------------------------------------
453−-- Convert direct style 'Parser' to CPS style 'K.Parser'
454−-------------------------------------------------------------------------------
455−
456−-- XXX Unlike the direct style folds/parsers, the initial action in CPS parsers
457−-- is not performed when the fold is initialized. It is performed when the
458−-- first element is processed by the fold or if no elements are processed then
459−-- at the extraction. We should either make the direct folds like this or make
460−-- the CPS folds behavior also like the direct ones.
461−--
462−-- | Convert a direct style parser ('D.Parser') to a CPS style parser
463−-- ('Parser').
464−--
465−{-# INLINE_NORMAL parseDToK #-}
466−parseDToK
467− :: Monad m
468− => (s -> a -> m (Step s b))
469− -> m (Initial s b)
470− -> (s -> m (Step s b))
471− -> Int
472− -> (Int, Int)
473− -> ((Int, Int) -> K.Parse b -> m (K.Step m a r))
474− -> m (K.Step m a r)
475−
476−-- Non 'Alternative' case.
477−parseDToK pstep initial extract leftover (0, _) cont = do
478− res <- initial
479− case res of
480− IPartial r -> return $ K.Partial leftover (parseCont (return r))
481− IDone b -> cont state (K.Success 0 b)
482− IError err -> cont state (K.Failure err)
483−
484− where
485−
486− -- The continuation is called with (0,0) state i.e. Alternative level
487− -- is 0 and the used count is 0. Alternative level is 0 because the level
488− -- passed in the argument above is 0, the "used" count is 0 because it is
489− -- not useful when Alternative level is 0. We should probably use a Maybe
490− -- type for the state but that might impact performance, need to measure.
491− state = (0,0)
492−
493− parseCont pst (Just x) = do
494− r <- pst
495− pRes <- pstep r x
496− case pRes of
497− Done n b -> cont state (K.Success n b)
498− Error err -> cont state (K.Failure err)
499− Partial n pst1 -> return $ K.Partial n (parseCont (return pst1))
500− Continue n pst1 -> return $ K.Continue n (parseCont (return pst1))
501−
502− parseCont acc Nothing = do
503− pst <- acc
504− r <- extract pst
505− case r of
506− Done n b -> cont state (K.Success n b)
507− Error err -> cont state (K.Failure err)
508− Partial _ _ -> error "Bug: parseDToK Partial unreachable"
509− Continue n pst1 -> return $ K.Continue n (parseCont (return pst1))
510−
511−-- XXX Pass on the stream to parserK and inside parserK drive the parserD
512−-- directly from the stream. That way we can feed full chunks efficiently to
513−-- parserD with fusion. The remaining stream can be passed on to the
514−-- continuation and at the end the leftover stream can be returned.
515−--
516−-- contification of parserD completely breaks fusion. We can avoid that by
517−-- fusing the parserD with the source stream.
518−
519−-- 'Alternative' case. Used count needs to be maintained when inside an
520−-- Alternative.
521−parseDToK pstep initial extract leftover (level, count) cont = do
522− res <- initial
523− case res of
524− IPartial r -> return $ K.Partial leftover (parseCont count (return r))
525− IDone b -> cont (level,count) (K.Success 0 b)
526− IError err -> cont (level,count) (K.Failure err)
527−
528− where
529−
530− parseCont !cnt pst (Just x) = do
531− let !cnt1 = cnt + 1
532− r <- pst
533− pRes <- pstep r x
534− case pRes of
535− Done n b -> do
536− assertM(n <= cnt1)
537− cont (level, cnt1 - n) (K.Success n b)
538− Error err ->
539− cont (level, cnt1) (K.Failure err)
540− Partial n pst1 -> do
541− assertM(n <= cnt1)
542− return $ K.Partial n (parseCont (cnt1 - n) (return pst1))
543− Continue n pst1 -> do
544− assertM(n <= cnt1)
545− return $ K.Continue n (parseCont (cnt1 - n) (return pst1))
546− parseCont cnt acc Nothing = do
547− pst <- acc
548− r <- extract pst
549− let s = (level, cnt)
550− case r of
551− Done n b -> do
552− assertM(n <= cnt)
553− cont s (K.Success n b)
554− Partial _ _ -> error "Bug: parseDToK Partial unreachable"
555− Error e ->
556− cont s (K.Failure e)
557− Continue n pst1 -> do
558− assertM(n <= cnt)
559− return $ K.Continue n (parseCont (cnt - n) (return pst1))
560−
561−-- | Convert a direct style 'Parser' to a CPS style 'K.Parser'.
562−--
563−-- /Pre-release/
564−--
565−{-# INLINE_LATE toParserK #-}
566−toParserK :: Monad m => Parser a m b -> K.Parser a m b
567−toParserK (Parser step initial extract) =
568− K.MkParser $ parseDToK step initial extract
569−
570−-------------------------------------------------------------------------------
571−-- Convert CPS style 'Parser' to direct style 'D.Parser'
572−-------------------------------------------------------------------------------
573−
574−-- | A continuation to extract the result when a CPS parser is done.
575−{-# INLINE parserDone #-}
576−parserDone :: Monad m => (Int, Int) -> K.Parse b -> m (K.Step m a b)
577−parserDone (0,_) (K.Success n b) = return $ K.Done n b
578−parserDone (0,_) (K.Failure e) = return $ K.Error e
579−parserDone st _ =
580− error $ "Bug: fromParserK: parser done inside alternative: " ++ show st
581−
582−-- | Convert a CPS style 'K.Parser' to a direct style 'Parser'.
583−--
584−-- "initial" returns a continuation which can be called one input at a time
585−-- using the "step" function.
586−--
587−-- /Pre-release/
588−--
589−{-# INLINE_LATE fromParserK #-}
590−fromParserK :: Monad m => K.Parser a m b -> Parser a m b
591−fromParserK parser = Parser step initial extract
592−
593− where
594−
595− initial = do
596− r <- K.runParser parser 0 (0,0) parserDone
597− return $ case r of
598− K.Done n b -> assert (n == 0) (IDone b)
599− K.Error e -> IError e
600− K.Partial n cont -> assert (n == 0) (IPartial cont)
601− K.Continue n cont -> assert (n == 0) (IPartial cont)
602−
603− step cont a = do
604− r <- cont (Just a)
605− return $ case r of
606− K.Done n b -> Done n b
607− K.Error e -> Error e
608− K.Partial n cont1 -> Partial n cont1
609− K.Continue n cont1 -> Continue n cont1
610−
611− extract cont = do
612− r <- cont Nothing
613− case r of
614− K.Done n b -> return $ Done n b
615− K.Error e -> return $ Error e
616− K.Partial _ cont1 -> extract cont1
617− K.Continue n cont1 -> return $ Continue n cont1
618−
619−#ifndef DISABLE_FUSION
620−{-# RULES "fromParserK/toParserK fusion" [2]
621− forall s. toParserK (fromParserK s) = s #-}
622−{-# RULES "toParserK/fromParserK fusion" [2]
623− forall s. fromParserK (toParserK s) = s #-}
624−#endif
625−
626447------------------------------------------------------------------------------
627448-- Mapping on the output
628449------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Parser/ParserK/Type.hs+291−56
@@ -19,22 +19,36 @@
1919module Streamly.Internal.Data.Parser.ParserK.Type
2020 (
2121 Step (..)
22− , Parse (..)
23− , Parser (..) -- XXX Stop exporting this
22+ , Input (..)
23+ , ParseResult (..)
24+ , Parser (..)
2425 , ParserK
26+ , fromParser
27+ , toParser
2528 , fromPure
2629 , fromEffect
2730 , die
2831 )
2932where
3033
34+#include "ArrayMacros.h"
35+#include "assert.hs"
3136#include "inline.hs"
3237
3338import Control.Applicative (Alternative(..), liftA2)
3439import Control.Monad (MonadPlus(..), ap)
3540import Control.Monad.IO.Class (MonadIO, liftIO)
3641-- import Control.Monad.Trans.Class (MonadTrans(lift))
42+import Data.Proxy (Proxy(..))
43+import GHC.Types (SPEC(..))
44+import Streamly.Internal.Data.Array.Type (Array(..))
45+import Streamly.Internal.Data.Unboxed (peekWith, sizeOf, Unbox)
46+
3747import qualified Control.Monad.Fail as Fail
48+import qualified Streamly.Internal.Data.Array.Type as Array
49+import qualified Streamly.Internal.Data.Parser.ParserD.Type as ParserD
50+
51+data Input a = None | Single a | Chunk (Array a)
3852
3953-- | The intermediate result of running a parser step. The parser driver may
4054-- stop with a final result, pause with a continuation to resume, or fail with
@@ -46,32 +60,45 @@ import qualified Control.Monad.Fail as Fail
4660--
4761-- /Pre-release/
4862--
49−data Step m a r =
63+data Step a m r =
64+ -- The Int is the current stream position index wrt to the start of the
65+ -- array.
5066 Done !Int r
5167 -- XXX we can use a "resume" and a "stop" continuations instead of Maybe.
5268 -- measure if that works any better.
53− | Partial !Int (Maybe a -> m (Step m a r))
54− | Continue !Int (Maybe a -> m (Step m a r))
55− | Error String
69+ -- Array a -> m (Step a m r), m (Step a m r)
70+ | Partial !Int (Input a -> m (Step a m r))
71+ | Continue !Int (Input a -> m (Step a m r))
72+ | Error !Int String
5673
57−instance Functor m => Functor (Step m a) where
74+instance Functor m => Functor (Step a m) where
5875 fmap f (Done n r) = Done n (f r)
5976 fmap f (Partial n k) = Partial n (fmap (fmap f) . k)
6077 fmap f (Continue n k) = Continue n (fmap (fmap f) . k)
61− fmap _ (Error e) = Error e
78+ fmap _ (Error n e) = Error n e
6279
6380-- | The parser's result.
6481--
82+-- Int is the position index into the current input array. Could be negative.
83+-- Cannot be beyond the input array max bound.
84+--
6585-- /Pre-release/
6686--
67−data Parse b =
68− Success !Int !b -- Leftover count, result
69− | Failure !String -- Error
87+data ParseResult b =
88+ Success !Int !b -- Position index, result
89+ | Failure !Int !String -- Position index, error
7090
7191-- | Map a function over 'Success'.
72−instance Functor Parse where
92+instance Functor ParseResult where
7393 fmap f (Success n b) = Success n (f b)
74− fmap _ (Failure e) = Failure e
94+ fmap _ (Failure n e) = Failure n e
95+
96+-- XXX Change the type to the shape (a -> m r -> m r) -> (m r -> m r) -> m r
97+--
98+-- The parse continuation would be: Array a -> m (Step a m r) -> m (Step a m r)
99+-- The extract continuation would be: m (Step a m r) -> m (Step a m r)
100+--
101+-- Use Step itself in place of ParseResult.
75102
76103-- | A continuation passing style parser representation. A continuation of
77104-- 'Step's, each step passes a state and a parse result to the next 'Step'. The
@@ -82,24 +109,27 @@ instance Functor Parse where
82109--
83110newtype Parser a m b = MkParser
84111 { runParser :: forall r.
85− -- leftover: the number of elements that were not used by the
86− -- previous consumer and should be carried forward.
112+ -- XXX Maintain and pass the original position in the stream. that
113+ -- way we can also report better errors. Use a Context structure for
114+ -- passing the state.
115+
116+ -- Stream position index wrt to the current input array start. If
117+ -- negative then backtracking is required before using the array.
118+ -- The parser should use "Continue -n" in this case if it needs to
119+ -- consume input. Negative value cannot be beyond the current
120+ -- backtrack buffer. Positive value cannot be beyond array length.
121+ -- If the parser needs to advance beyond the array length it should
122+ -- use "Continue +n".
87123 Int
88− -- (alt nesting level, alt used elem count). Nesting level is
89− -- increased whenever we enter an Alternative composition and
90− -- decreased when it is done. The used element count is a count of
91− -- elements consumed by the Alternative. If the Alternative fails we
92− -- need to backtrack by this amount.
93− --
94− -- The nesting level is used in parseDToK to optimize the case when
95− -- we are not in an alternative, in that case we do not need to
96− -- maintain the element count for backtracking.
97− -> (Int, Int)
98− -- The first argument is the (nest level, used count) tuple as
99− -- described above. The leftover element count is carried as part of
100− -- 'Success' constructor of 'Parse'.
101− -> ((Int, Int) -> Parse b -> m (Step m a r))
102− -> m (Step m a r)
124+ -- used elem count, a count of elements consumed by the parser. If
125+ -- an Alternative fails we need to backtrack by this amount.
126+ -> Int
127+ -- The second argument is the used count as described above. The
128+ -- current input position is carried as part of 'Success'
129+ -- constructor of 'ParseResult'.
130+ -> Input a
131+ -> (ParseResult b -> Int -> Input a -> m (Step a m r))
132+ -> m (Step a m r)
103133 }
104134
105135type ParserK = Parser
@@ -113,9 +143,9 @@ type ParserK = Parser
113143--
114144instance Functor m => Functor (Parser a m) where
115145 {-# INLINE fmap #-}
116− fmap f parser = MkParser $ \n st k ->
117− let k1 s res = k s (fmap f res)
118− in runParser parser n st k1
146+ fmap f parser = MkParser $ \n st arr pk ->
147+ let pk1 res = pk (fmap f res)
148+ in runParser parser n st arr pk1
119149
120150-------------------------------------------------------------------------------
121151-- Sequential applicative
@@ -129,7 +159,7 @@ instance Functor m => Functor (Parser a m) where
129159--
130160{-# INLINE fromPure #-}
131161fromPure :: b -> Parser a m b
132−fromPure b = MkParser $ \n st k -> k st (Success n b)
162+fromPure b = MkParser $ \n st arr pk -> pk (Success n b) st arr
133163
134164-- | See 'Streamly.Internal.Data.Parser.fromEffect'.
135165--
@@ -137,7 +167,8 @@ fromPure b = MkParser $ \n st k -> k st (Success n b)
137167--
138168{-# INLINE fromEffect #-}
139169fromEffect :: Monad m => m b -> Parser a m b
140−fromEffect eff = MkParser $ \n st k -> eff >>= \b -> k st (Success n b)
170+fromEffect eff =
171+ MkParser $ \n st arr pk -> eff >>= \b -> pk (Success n b) st arr
141172
142173-- | 'Applicative' form of 'Streamly.Internal.Data.Parser.splitWith'. Note that
143174-- this operation does not fuse, use 'Streamly.Internal.Data.Parser.splitWith'
@@ -151,19 +182,19 @@ instance Monad m => Applicative (Parser a m) where
151182 (<*>) = ap
152183
153184 {-# INLINE (*>) #-}
154− p1 *> p2 = MkParser $ \n st k ->
155− let k1 s (Success n1 _) = runParser p2 n1 s k
156− k1 s (Failure e) = k s (Failure e)
157− in runParser p1 n st k1
185+ p1 *> p2 = MkParser $ \n st arr k ->
186+ let k1 (Success n1 _) s input = runParser p2 n1 s input k
187+ k1 (Failure n1 e) s input = k (Failure n1 e) s input
188+ in runParser p1 n st arr k1
158189
159190 {-# INLINE (<*) #-}
160− p1 <* p2 = MkParser $ \n st k ->
161− let k1 s1 (Success n1 b) =
162− let k2 s2 (Success n2 _) = k s2 (Success n2 b)
163− k2 s2 (Failure e) = k s2 (Failure e)
164− in runParser p2 n1 s1 k2
165− k1 s1 (Failure e) = k s1 (Failure e)
166− in runParser p1 n st k1
191+ p1 <* p2 = MkParser $ \n st arr k ->
192+ let k1 (Success n1 b) s1 input =
193+ let k2 (Success n2 _) = k (Success n2 b)
194+ k2 (Failure n2 e) = k (Failure n2 e)
195+ in runParser p2 n1 s1 input k2
196+ k1 (Failure n1 e) s1 input = k (Failure n1 e) s1 input
197+ in runParser p1 n st arr k1
167198
168199 {-# INLINE liftA2 #-}
169200 liftA2 f p = (<*>) (fmap f p)
@@ -181,7 +212,7 @@ instance Monad m => Applicative (Parser a m) where
181212--
182213{-# INLINE die #-}
183214die :: String -> Parser a m b
184−die err = MkParser (\_ st k -> k st (Failure err))
215+die err = MkParser (\n st arr pk -> pk (Failure n err) st arr)
185216
186217-- | Monad composition can be used for lookbehind parsers, we can make the
187218-- future parses depend on the previously parsed values.
@@ -230,10 +261,10 @@ instance Monad m => Monad (Parser a m) where
230261 return = pure
231262
232263 {-# INLINE (>>=) #-}
233− p >>= f = MkParser $ \n st k ->
234− let k1 s1 (Success n1 b) = runParser (f b) n1 s1 k
235− k1 s1 (Failure e) = k s1 (Failure e)
236− in runParser p n st k1
264+ p >>= f = MkParser $ \n st arr pk ->
265+ let pk1 (Success n1 b) s1 inp = runParser (f b) n1 s1 inp pk
266+ pk1 (Failure n1 e) s1 inp = pk (Failure n1 e) s1 inp
267+ in runParser p n st arr pk1
237268
238269 {-# INLINE (>>) #-}
239270 (>>) = (*>)
@@ -274,11 +305,11 @@ instance Monad m => Alternative (Parser a m) where
274305 empty = die "empty"
275306
276307 {-# INLINE (<|>) #-}
277− p1 <|> p2 = MkParser $ \n (level, _) k ->
278− let k1 (0, _) _ = error "Bug: 0 nest level in Alternative"
279− k1 (l1, n1) (Failure _) = runParser p2 n1 (l1 - 1, 0) k
280− k1 (l1, _) success = k (l1 - 1, 0) success
281− in runParser p1 n (level + 1, 0) k1
308+ p1 <|> p2 = MkParser $ \n _ arr k ->
309+ let
310+ k1 (Failure pos _) used input = runParser p2 (pos - used) 0 input k
311+ k1 success _ input = k success 0 input
312+ in runParser p1 n 0 arr k1
282313
283314 -- some and many are implemented here instead of using default definitions
284315 -- so that we can use INLINE on them. It gives 50% performance improvement.
@@ -314,3 +345,207 @@ instance MonadTrans (Parser a) where
314345 {-# INLINE lift #-}
315346 lift = fromEffect
316347-}
348+
349+-------------------------------------------------------------------------------
350+-- Convert ParserD to ParserK
351+-------------------------------------------------------------------------------
352+
353+data ChunkResult s b =
354+ ChunkDone !Int !b
355+ | ChunkPartial !Int !s
356+ | ChunkContinue !Int !s
357+ | ChunkError !Int String
358+
359+-- This is very similar to fromParserD in the Array/Unboxed/Fold module.
360+{-# INLINE parseChunk #-}
361+parseChunk
362+ :: forall m a s b. (MonadIO m, Unbox a)
363+ => (s -> a -> m (ParserD.Step s b))
364+ -> s
365+ -> Array a
366+ -> Int
367+ -> m (ChunkResult s b)
368+parseChunk pstep state (Array contents start end) offset = do
369+ if offset >= 0
370+ then go SPEC (start + offset * SIZE_OF(a)) state
371+ else return $ ChunkContinue offset state
372+
373+ where
374+
375+ {-# INLINE onBack #-}
376+ onBack offset1 elemSize constr pst = do
377+ let pos = offset1 - start
378+ in if pos >= 0
379+ then go SPEC offset1 pst
380+ else return $ constr (pos `div` elemSize) pst
381+
382+ -- Note: div may be expensive but the alternative is to maintain an element
383+ -- offset in addition to a byte offset or just the element offset and use
384+ -- multiplication to get the byte offset every time, both these options
385+ -- turned out to be more expensive than using div.
386+ go !_ !cur !pst | cur >= end =
387+ return $ ChunkContinue ((end - start) `div` SIZE_OF(a)) pst
388+ go !_ !cur !pst = do
389+ x <- liftIO $ peekWith contents cur
390+ pRes <- pstep pst x
391+ let elemSize = SIZE_OF(a)
392+ next = INDEX_NEXT(cur,a)
393+ back n = next - n * elemSize
394+ curOff = (cur - start) `div` elemSize
395+ nextOff = (next - start) `div` elemSize
396+ case pRes of
397+ ParserD.Done 0 b ->
398+ return $ ChunkDone nextOff b
399+ ParserD.Done 1 b ->
400+ return $ ChunkDone curOff b
401+ ParserD.Done n b ->
402+ return $ ChunkDone ((back n - start) `div` elemSize) b
403+ ParserD.Partial 0 pst1 ->
404+ go SPEC next pst1
405+ ParserD.Partial 1 pst1 ->
406+ go SPEC cur pst1
407+ ParserD.Partial n pst1 ->
408+ onBack (back n) elemSize ChunkPartial pst1
409+ ParserD.Continue 0 pst1 ->
410+ go SPEC next pst1
411+ ParserD.Continue 1 pst1 ->
412+ go SPEC cur pst1
413+ ParserD.Continue n pst1 ->
414+ onBack (back n) elemSize ChunkContinue pst1
415+ ParserD.Error err ->
416+ return $ ChunkError curOff err
417+
418+{-# INLINE parseDToK #-}
419+parseDToK
420+ :: forall m a s b r. (MonadIO m, Unbox a)
421+ => (s -> a -> m (ParserD.Step s b))
422+ -> m (ParserD.Initial s b)
423+ -> (s -> m (ParserD.Step s b))
424+ -> Int
425+ -> Int
426+ -> Input a
427+ -> (ParseResult b -> Int -> Input a -> m (Step a m r))
428+ -> m (Step a m r)
429+parseDToK pstep initial extract offset usedCount input cont = do
430+ res <- initial
431+ case res of
432+ ParserD.IPartial pst -> do
433+ case input of
434+ Chunk arr -> parseContChunk usedCount offset pst arr
435+ Single x -> parseContSingle usedCount offset pst x
436+ None -> parseContNothing usedCount pst
437+ ParserD.IDone b -> cont (Success offset b) usedCount input
438+ ParserD.IError err -> cont (Failure offset err) usedCount input
439+
440+ where
441+
442+ -- XXX We can maintain an absolute position instead of relative that will
443+ -- help in reporting of error location in the stream.
444+ {-# NOINLINE parseContChunk #-}
445+ parseContChunk count off pst arr = do
446+ pRes <- parseChunk pstep pst arr off
447+ -- The "n" here is stream position index wrt the array start, and not
448+ -- the backtrack count as returned by byte stream parsers.
449+ case pRes of
450+ ChunkDone n b ->
451+ assert (n <= Array.length arr)
452+ (cont (Success n b) (count + n - off) (Chunk arr))
453+ ChunkPartial n pst1 ->
454+ assert (n < 0 || n >= Array.length arr)
455+ (return $ Partial n (parseCont (count + n - off) pst1))
456+ ChunkContinue n pst1 ->
457+ assert (n < 0 || n >= Array.length arr)
458+ (return $ Continue n (parseCont (count + n - off) pst1))
459+ ChunkError n err ->
460+ cont (Failure n err) (count + n - off) (Chunk arr)
461+
462+ -- XXX This is not yet finished
463+ {-# NOINLINE parseContSingle #-}
464+ parseContSingle _count off pst x = do
465+ pRes <- pstep pst x
466+ case pRes of
467+ ParserD.Done _n b -> do
468+ cont (Success (off + 1) b) undefined undefined
469+ _ -> undefined
470+
471+ {-# NOINLINE parseContNothing #-}
472+ parseContNothing count pst = do
473+ r <- extract pst
474+ case r of
475+ -- IMPORTANT: the n here is from the byte stream parser, that means
476+ -- it is the backtrack element count and not the stream position
477+ -- index into the current input array.
478+ ParserD.Done n b ->
479+ assert (n >= 0)
480+ (cont (Success (- n) b) (count - n) None)
481+ ParserD.Continue n pst1 ->
482+ assert (n >= 0)
483+ (return $ Continue (- n) (parseCont (count - n) pst1))
484+ ParserD.Error err ->
485+ -- XXX It is called only when there is no input arr. So using 0
486+ -- as the position is correct?
487+ cont (Failure 0 err) count None
488+ ParserD.Partial _ _ -> error "Bug: parseDToK Partial unreachable"
489+
490+ -- XXX Maybe we can use two separate continuations instead of using
491+ -- Just/Nothing cases here. That may help in avoiding the parseContJust
492+ -- function call.
493+ {-# INLINE parseCont #-}
494+ parseCont cnt pst (Chunk arr) = parseContChunk cnt 0 pst arr
495+ parseCont cnt pst (Single x) = parseContSingle cnt 0 pst x
496+ parseCont cnt pst None = parseContNothing cnt pst
497+
498+-- | Convert a raw byte 'Parser' to a chunked parser.
499+--
500+-- /Pre-release/
501+--
502+{-# INLINE_LATE fromParser #-}
503+fromParser :: (MonadIO m, Unbox a) => ParserD.Parser a m b -> ParserK a m b
504+fromParser (ParserD.Parser step initial extract) =
505+ MkParser $ parseDToK step initial extract
506+
507+-------------------------------------------------------------------------------
508+-- Convert CPS style 'Parser' to direct style 'D.Parser'
509+-------------------------------------------------------------------------------
510+
511+-- | A continuation to extract the result when a CPS parser is done.
512+{-# INLINE parserDone #-}
513+parserDone :: Monad m => ParseResult b -> Int -> Input a -> m (Step a m b)
514+parserDone (Success n b) _ None = return $ Done n b
515+parserDone (Failure n e) _ None = return $ Error n e
516+parserDone _ _ _ = error "Bug: toParser: called with input"
517+
518+-- | Convert a CPS style 'ParserK' to a direct style 'ParserD.Parser'.
519+--
520+-- /Pre-release/
521+--
522+{-# INLINE_LATE toParser #-}
523+toParser :: Monad m => Parser a m b -> ParserD.Parser a m b
524+toParser parser = ParserD.Parser step initial extract
525+
526+ where
527+
528+ initial = pure (ParserD.IPartial (\x -> runParser parser 0 0 x parserDone))
529+
530+ step cont a = do
531+ r <- cont (Single a)
532+ return $ case r of
533+ Done n b -> ParserD.Done n b
534+ Error _ e -> ParserD.Error e
535+ Partial n cont1 -> ParserD.Partial n cont1
536+ Continue n cont1 -> ParserD.Continue n cont1
537+
538+ extract cont = do
539+ r <- cont None
540+ case r of
541+ Done n b -> return $ ParserD.Done n b
542+ Error _ e -> return $ ParserD.Error e
543+ Partial _ cont1 -> extract cont1
544+ Continue n cont1 -> return $ ParserD.Continue n cont1
545+
546+#ifndef DISABLE_FUSION
547+{-# RULES "fromParser/toParser fusion" [2]
548+ forall s. toParser (fromParser s) = s #-}
549+{-# RULES "toParser/fromParser fusion" [2]
550+ forall s. fromParser (toParser s) = s #-}
551+#endif
core/src/Streamly/Internal/Data/Producer/Source.hs+10−8
@@ -41,7 +41,7 @@ import Streamly.Internal.Data.Producer.Type (Producer(..))
4141import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
4242
4343import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
44−import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
44+-- import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
4545
4646import Prelude hiding (read)
4747
@@ -109,14 +109,14 @@ producer (Producer step1 inject1 extract1) = Producer step inject extract
109109{-# ANN type List NoSpecConstr #-}
110110newtype List a = List {getList :: [a]}
111111
112−{-# INLINE_NORMAL parseD #-}
113−parseD
112+{-# INLINE_NORMAL parse #-}
113+parse
114114 :: Monad m =>
115115 ParserD.Parser a m b
116116 -> Producer m (Source s a) a
117117 -> Source s a
118118 -> m (Either ParseError b, Source s a)
119−parseD
119+parse
120120 (ParserD.Parser pstep initial extract)
121121 (Producer ustep uinject uextract)
122122 seed = do
@@ -241,17 +241,19 @@ parseD
241241 Error err ->
242242 return (Left (ParseError err), source Nothing)
243243
244+{-
244245-- | Parse a buffered source using a parser, returning the parsed value and the
245246-- remaining source.
246247--
247248-- /Pre-release/
248−{-# INLINE [3] parse #-}
249−parse :: Monad m =>
249+{-# INLINE [3] parseK #-}
250+parseK :: Monad m =>
250251 ParserK.Parser a m b
251252 -> Producer m (Source s a) a
252253 -> Source s a
253254 -> m (Either ParseError b, Source s a)
254−parse = parseD . ParserD.fromParserK
255+parseK = parse . ParserK.toParser
256+-}
255257
256258-------------------------------------------------------------------------------
257259-- Nested parsing
@@ -271,7 +273,7 @@ parseManyD parser reader = Producer step return return
271273 if isEmpty src
272274 then return Stop
273275 else do
274− (b, s1) <- parseD parser reader src
276+ (b, s1) <- parse parser reader src
275277 case b of
276278 Right b1 -> return $ Yield (Right b1) s1
277279 Left _ -> return Stop
core/src/Streamly/Internal/Data/Stream/StreamK.hs+151
@@ -119,6 +119,8 @@ module Streamly.Internal.Data.Stream.StreamK
119119 , foldConcat
120120 , parseBreak
121121 , parse
122+ , parseKBreakChunks
123+ , parseKChunks
122124
123125 -- ** Specialized Folds
124126 , drain
@@ -219,18 +221,24 @@ module Streamly.Internal.Data.Stream.StreamK
219221 )
220222where
221223
224+#include "ArrayMacros.h"
222225#include "inline.hs"
223226#include "assert.hs"
224227
225228import Control.Monad (void, join)
229+import Data.Proxy (Proxy(..))
226230import GHC.Types (SPEC(..))
231+import Streamly.Internal.Data.Array.Type (Array(..))
227232import Streamly.Internal.Data.Fold.Type (Fold(..))
228233import Streamly.Internal.Data.Producer.Type (Producer(..))
229234import Streamly.Internal.Data.SVar.Type (adaptState, defState)
235+import Streamly.Internal.Data.Unboxed (sizeOf, Unbox)
230236
237+import qualified Streamly.Internal.Data.Array.Type as Array
231238import qualified Streamly.Internal.Data.Fold.Type as FL
232239import qualified Streamly.Internal.Data.Parser as Parser
233240import qualified Streamly.Internal.Data.Parser.ParserD.Type as PR
241+import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
234242import qualified Streamly.Internal.Data.Stream.StreamD as Stream
235243import qualified Prelude
236244
@@ -1233,11 +1241,154 @@ parseBreak :: Monad m =>
12331241 Parser.Parser a m b -> Stream m a -> m (Either ParseError b, Stream m a)
12341242parseBreak = parseBreakD
12351243
1244+-- Using ParserD or ParserK on StreamK may not make much difference. We should
1245+-- perhaps use only chunked parsing on StreamK. We can always convert a stream
1246+-- to chunks before parsing. Or just have a ParserK element parser for StreamK
1247+-- and convert ParserD to ParserK for element parsing using StreamK.
12361248{-# INLINE parse #-}
12371249parse :: Monad m =>
12381250 Parser.Parser a m b -> Stream m a -> m (Either ParseError b)
12391251parse f = fmap fst . parseBreak f
12401252
1253+-------------------------------------------------------------------------------
1254+-- Chunked parsing using ParserK
1255+-------------------------------------------------------------------------------
1256+
1257+-- The backracking buffer consists of arrays in the most-recent-first order. We
1258+-- want to take a total of n array elements from this buffer. Note: when we
1259+-- have to take an array partially, we must take the last part of the array.
1260+{-# INLINE backTrack #-}
1261+backTrack :: forall m a. Unbox a =>
1262+ Int
1263+ -> [Array a]
1264+ -> StreamK m (Array a)
1265+ -> (StreamK m (Array a), [Array a])
1266+backTrack = go
1267+
1268+ where
1269+
1270+ go _ [] stream = (stream, [])
1271+ go n xs stream | n <= 0 = (stream, xs)
1272+ go n (x:xs) stream =
1273+ let len = Array.length x
1274+ in if n > len
1275+ then go (n - len) xs (cons x stream)
1276+ else if n == len
1277+ then (cons x stream, xs)
1278+ else let !(Array contents start end) = x
1279+ !start1 = end - (n * SIZE_OF(a))
1280+ arr1 = Array contents start1 end
1281+ arr2 = Array contents start start1
1282+ in (cons arr1 stream, arr2:xs)
1283+
1284+-- | A continuation to extract the result when a CPS parser is done.
1285+{-# INLINE parserDone #-}
1286+parserDone :: Applicative m =>
1287+ ParserK.ParseResult b -> Int -> ParserK.Input a -> m (ParserK.Step a m b)
1288+parserDone (ParserK.Success n b) _ _ = pure $ ParserK.Done n b
1289+parserDone (ParserK.Failure n e) _ _ = pure $ ParserK.Error n e
1290+
1291+-- | Run a 'ParserK' over a chunked 'StreamK' and return the rest of the Stream.
1292+{-# INLINE_NORMAL parseKBreakChunks #-}
1293+parseKBreakChunks
1294+ :: (Monad m, Unbox a)
1295+ => ParserK.Parser a m b
1296+ -> StreamK m (Array a)
1297+ -> m (Either ParseError b, StreamK m (Array a))
1298+parseKBreakChunks parser input = do
1299+ let parserk = \arr -> ParserK.runParser parser 0 0 arr parserDone
1300+ in go [] parserk input
1301+
1302+ where
1303+
1304+ {-# INLINE goStop #-}
1305+ goStop backBuf parserk = do
1306+ pRes <- parserk ParserK.None
1307+ case pRes of
1308+ -- If we stop in an alternative, it will try calling the next
1309+ -- parser, the next parser may call initial returning Partial and
1310+ -- then immediately we have to call extract on it.
1311+ ParserK.Partial 0 cont1 ->
1312+ go [] cont1 nil
1313+ ParserK.Partial n cont1 -> do
1314+ let n1 = negate n
1315+ assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1316+ let (s1, backBuf1) = backTrack n1 backBuf nil
1317+ in go backBuf1 cont1 s1
1318+ ParserK.Continue 0 cont1 ->
1319+ go backBuf cont1 nil
1320+ ParserK.Continue n cont1 -> do
1321+ let n1 = negate n
1322+ assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1323+ let (s1, backBuf1) = backTrack n1 backBuf nil
1324+ in go backBuf1 cont1 s1
1325+ ParserK.Done 0 b ->
1326+ return (Right b, nil)
1327+ ParserK.Done n b -> do
1328+ let n1 = negate n
1329+ assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1330+ let (s1, _) = backTrack n1 backBuf nil
1331+ in return (Right b, s1)
1332+ ParserK.Error _ err -> return (Left (ParseError err), nil)
1333+
1334+ seekErr n len =
1335+ error $ "parseBreak: Partial: forward seek not implemented n = "
1336+ ++ show n ++ " len = " ++ show len
1337+
1338+ yieldk backBuf parserk arr stream = do
1339+ pRes <- parserk (ParserK.Chunk arr)
1340+ let len = Array.length arr
1341+ case pRes of
1342+ ParserK.Partial n cont1 ->
1343+ case compare n len of
1344+ EQ -> go [] cont1 stream
1345+ LT -> do
1346+ if n >= 0
1347+ then yieldk [] cont1 arr stream
1348+ else do
1349+ let n1 = negate n
1350+ bufLen = sum (Prelude.map Array.length backBuf)
1351+ s = cons arr stream
1352+ assertM(n1 >= 0 && n1 <= bufLen)
1353+ let (s1, _) = backTrack n1 backBuf s
1354+ go [] cont1 s1
1355+ GT -> seekErr n len
1356+ ParserK.Continue n cont1 ->
1357+ case compare n len of
1358+ EQ -> go (arr:backBuf) cont1 stream
1359+ LT -> do
1360+ if n >= 0
1361+ then yieldk backBuf cont1 arr stream
1362+ else do
1363+ let n1 = negate n
1364+ bufLen = sum (Prelude.map Array.length backBuf)
1365+ s = cons arr stream
1366+ assertM(n1 >= 0 && n1 <= bufLen)
1367+ let (s1, backBuf1) = backTrack n1 backBuf s
1368+ go backBuf1 cont1 s1
1369+ GT -> seekErr n len
1370+ ParserK.Done n b -> do
1371+ let n1 = len - n
1372+ assertM(n1 <= sum (Prelude.map Array.length (arr:backBuf)))
1373+ let (s1, _) = backTrack n1 (arr:backBuf) stream
1374+ in return (Right b, s1)
1375+ ParserK.Error _ err -> return (Left (ParseError err), nil)
1376+
1377+ go backBuf parserk stream = do
1378+ let stop = goStop backBuf parserk
1379+ single a = yieldk backBuf parserk a nil
1380+ in foldStream
1381+ defState (yieldk backBuf parserk) single stop stream
1382+
1383+{-# INLINE parseKChunks #-}
1384+parseKChunks :: (Monad m, Unbox a) =>
1385+ ParserK.Parser a m b -> Stream m (Array a) -> m (Either ParseError b)
1386+parseKChunks f = fmap fst . parseKBreakChunks f
1387+
1388+-------------------------------------------------------------------------------
1389+-- Sorting
1390+-------------------------------------------------------------------------------
1391+
12411392-- | Sort the input stream using a supplied comparison function.
12421393--
12431394-- Sorting can be achieved by simply:
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+1−1
@@ -382,7 +382,7 @@ parseD p = D.parseD p . toStreamD
382382-- /Internal/
383383{-# INLINE parseK #-}
384384parseK :: Monad m => PRK.Parser a m b -> SerialT m a -> m (Either PRD.ParseError b)
385−parseK p = parse (PRD.fromParserK p)
385+parseK p = parse (PRK.toParser p)
386386
387387-- | Parse a stream using the supplied 'Parser'.
388388--