@@ -13,7 +13,12 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
1313 -- * Transformation
1414 transform
1515
16− -- ** By folding (scans)
16+ -- ** By folding
17+ , foldrS
18+ , foldrT
19+ , foldlS
20+ , foldlT
21+
1722 , scanlM'
1823 , scanlMAfter'
1924 , scanl'
@@ -40,6 +45,10 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
4045 , postscanOnce
4146 , scanOnce
4247
48+ -- * Reordering
49+ , reverse
50+ , reverse'
51+
4352 -- * Filtering
4453 , filter
4554 , filterM
@@ -60,6 +69,13 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
6069 , rollingMap
6170 , rollingMapM
6271
72+ -- ** Special Maps
73+ , tap
74+ , tapOffsetEvery
75+ , tapAsync
76+ , tapRate
77+ , pollCounts
78+
6379 -- * Inserting
6480 , intersperseM
6581 , intersperseM_
@@ -82,6 +98,10 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
8298 , zipWith
8399 , zipWithM
84100
101+ -- * Parsers
102+ , parseMany
103+ , parseIterate
104+
85105 -- * Merging
86106 , mergeBy
87107 , mergeByM
@@ -89,25 +109,58 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
89109 -- * Concurrent Application
90110 , mkParallel
91111 , mkParallelD
112+
113+ -- ** Conversions
114+ -- | Transform a stream into another type.
115+ , hoist
116+ , generally
117+
118+ , liftInner
119+ , runReaderT
120+ , evalStateT
121+ , runStateT
92122 )
93123where
94124
95−import Control.Monad (void)
125+import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
126+import Control.Exception (assert, AsyncException)
127+import Control.Monad (void, when)
128+import Control.Monad.Catch (MonadCatch, MonadThrow, throwM)
96129import Control.Monad.IO.Class (MonadIO(..))
130+import Control.Monad.Trans.Class (MonadTrans(lift))
131+import Control.Monad.Trans.Reader (ReaderT)
132+import Control.Monad.Trans.State.Strict (StateT)
97133import Data.Functor.Identity (Identity(..))
134+import Data.IORef (newIORef, mkWeakIORef)
98135import Data.Maybe (fromJust, isJust)
99−import Streamly.Internal.Data.Time.Units
100− (TimeUnit64, toRelTime64, diffAbsTime64)
136+import Foreign.Storable (Storable(..))
137+import Fusion.Plugin.Types (Fuse(..))
138+import GHC.Types (SPEC(..))
139+import qualified Control.Monad.Catch as MC
140+import qualified Control.Monad.Trans.Reader as Reader
141+import qualified Control.Monad.Trans.State.Strict as State
142+
143+import Streamly.Internal.Data.Fold.Types (Fold(..))
144+import Streamly.Internal.Data.Parser (ParseError(..))
101145import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
146+import Streamly.Internal.Data.Stream.SVar (fromConsumer, pushToFold)
102147import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
148+import Streamly.Internal.Data.Time.Units
149+ (TimeUnit64, toRelTime64, diffAbsTime64)
103150
104−import qualified Streamly.Internal.Data.Pipe.Types as Pipe
151+import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
105152import qualified Streamly.Internal.Data.Fold as FL
153+import qualified Streamly.Internal.Data.IORef.Prim as Prim
154+import qualified Streamly.Internal.Data.Parser as PR
155+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
156+import qualified Streamly.Internal.Data.Pipe.Types as Pipe
106157import qualified Streamly.Internal.Data.Stream.StreamK as K
107158
159+import qualified Prelude
108160import Prelude hiding
109− ( drop, dropWhile, filter, map, mapM
161+ ( drop, dropWhile, filter, map, mapM, reverse
110162 , scanl, scanl1, sequence, take, takeWhile, zipWith)
163+
111164import Streamly.Internal.Data.Stream.StreamD.Type
112165import Streamly.Internal.Data.SVar
113166
@@ -142,9 +195,47 @@ transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
142195 Pipe.Continue pst' -> return $ Skip (pst', st)
143196
144197------------------------------------------------------------------------------
145−-- Transformation by Folding (Scans)
198+-- Transformation by Folding
146199------------------------------------------------------------------------------
147200
201+------------------------------------------------------------------------------
202+-- Left Folds
203+------------------------------------------------------------------------------
204+
205+{-# INLINE_NORMAL foldlT #-}
206+foldlT :: (Monad m, Monad (s m), MonadTrans s)
207+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
208+foldlT fstep begin (Stream step state) = go SPEC begin state
209+ where
210+ go !_ acc st = do
211+ r <- lift $ step defState st
212+ case r of
213+ Yield x s -> go SPEC (fstep acc x) s
214+ Skip s -> go SPEC acc s
215+ Stop -> acc
216+
217+-- Note, this is going to have horrible performance, because of the nature of
218+-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
219+-- likely be practically unusable.
220+{-# INLINE_NORMAL foldlS #-}
221+foldlS :: Monad m
222+ => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
223+foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
224+ where
225+ step' gst (Left (st, acc)) = do
226+ r <- step (adaptState gst) st
227+ return $ case r of
228+ Yield x s -> Skip (Left (s, fstep acc x))
229+ Skip s -> Skip (Left (s, acc))
230+ Stop -> Skip (Right acc)
231+
232+ step' gst (Right (Stream stp stt)) = do
233+ r <- stp (adaptState gst) stt
234+ return $ case r of
235+ Yield x s -> Yield x (Right (Stream stp s))
236+ Skip s -> Skip (Right (Stream stp s))
237+ Stop -> Stop
238+
148239------------------------------------------------------------------------------
149240-- Prescans
150241------------------------------------------------------------------------------
@@ -456,6 +547,68 @@ rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
456547rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
457548rollingMap f = rollingMapM (\x y -> return $ f x y)
458549
550+------------------------------------------------------------------------------
551+-- Reordering
552+------------------------------------------------------------------------------
553+
554+-- We can implement reverse as:
555+--
556+-- > reverse = foldlS (flip cons) nil
557+--
558+-- However, this implementation is unusable because of the horrible performance
559+-- of cons. So we just convert it to a list first and then stream from the
560+-- list.
561+--
562+-- XXX Maybe we can use an Array instead of a list here?
563+{-# INLINE_NORMAL reverse #-}
564+reverse :: Monad m => Stream m a -> Stream m a
565+reverse m = Stream step Nothing
566+ where
567+ {-# INLINE_LATE step #-}
568+ step _ Nothing = do
569+ xs <- foldl' (flip (:)) [] m
570+ return $ Skip (Just xs)
571+ step _ (Just (x:xs)) = return $ Yield x (Just xs)
572+ step _ (Just []) = return Stop
573+
574+-- Much faster reverse for Storables
575+{-# INLINE_NORMAL reverse' #-}
576+reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
577+{-
578+-- This commented implementation copies the whole stream into one single array
579+-- and then streams from that array, this is 3-4x faster than the chunked code
580+-- that follows. Though this could be problematic due to unbounded large
581+-- allocations. We need to figure out why the chunked code is slower and if we
582+-- can optimize the chunked code to work as fast as this one. It may be a
583+-- fusion issue?
584+import Foreign.ForeignPtr (touchForeignPtr)
585+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
586+import Foreign.Ptr (Ptr, plusPtr)
587+reverse' m = Stream step Nothing
588+ where
589+ {-# INLINE_LATE step #-}
590+ step _ Nothing = do
591+ arr <- A.fromStreamD m
592+ let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
593+ return $ Skip $ Just (aStart arr, p)
594+
595+ step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
596+
597+ step _ (Just (start, p)) = do
598+ let !x = A.unsafeInlineIO $ do
599+ r <- peek p
600+ touchForeignPtr start
601+ return r
602+ next = p `plusPtr` negate (sizeOf (undefined :: a))
603+ return $ Yield x (Just (start, next))
604+-}
605+reverse' m =
606+ A.flattenArraysRev
607+ $ fromStreamK
608+ $ K.reverse
609+ $ toStreamK
610+ $ A.fromStreamDArraysOf A.defaultChunkSize m
611+
459612-------------------------------------------------------------------------------
460613-- Filtering
461614-------------------------------------------------------------------------------
@@ -572,6 +725,237 @@ sequence (Stream step state) = Stream step' state
572725 Skip s -> return $ Skip s
573726 Stop -> return Stop
574727
728+------------------------------------------------------------------------------
729+-- Tapping/Distributing
730+------------------------------------------------------------------------------
731+
732+data TapState fs st a
733+ = TapInit | Tapping !fs st | TapDone st
734+
735+-- XXX Multiple yield points
736+{-# INLINE tap #-}
737+tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
738+tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
739+
740+ where
741+
742+ step' _ TapInit = do
743+ r <- initial
744+ return $ Skip (Tapping r state)
745+ step' gst (Tapping acc st) = do
746+ r <- step gst st
747+ case r of
748+ -- XXX Abstract Yield?
749+ Yield x s -> do
750+ res <- fstep acc x
751+ return
752+ $ Yield x
753+ $ case res of
754+ FL.Partial fs -> Tapping fs s
755+ FL.Done _ -> TapDone s
756+ Skip s -> return $ Skip (Tapping acc s)
757+ Stop -> do
758+ void $ extract acc
759+ return Stop
760+ step' gst (TapDone st) = do
761+ r <- step gst st
762+ return
763+ $ case r of
764+ Yield x s -> Yield x (TapDone s)
765+ Skip s -> Skip (TapDone s)
766+ Stop -> Stop
767+
768+data TapOffState fs s a
769+ = TapOffInit
770+ | TapOffTapping !fs s Int
771+ | TapOffDone s
772+
773+-- XXX Multiple yield points
774+{-# INLINE_NORMAL tapOffsetEvery #-}
775+tapOffsetEvery :: Monad m
776+ => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
777+tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
778+ Stream step' TapOffInit
779+
780+ where
781+
782+ {-# INLINE_LATE step' #-}
783+ step' _ TapOffInit = do
784+ r <- initial
785+ return $ Skip $ TapOffTapping r state (offset `mod` n)
786+ step' gst (TapOffTapping acc st count) = do
787+ r <- step gst st
788+ case r of
789+ Yield x s -> do
790+ next <-
791+ if count <= 0
792+ then do
793+ res <- fstep acc x
794+ return
795+ $ case res of
796+ FL.Partial sres ->
797+ TapOffTapping sres s (n - 1)
798+ FL.Done _ -> TapOffDone s
799+ else return $ TapOffTapping acc s (count - 1)
800+ return $ Yield x next
801+ Skip s -> return $ Skip (TapOffTapping acc s count)
802+ Stop -> do
803+ void $ extract acc
804+ return Stop
805+ step' gst (TapOffDone st) = do
806+ r <- step gst st
807+ return
808+ $ case r of
809+ Yield x s -> Yield x (TapOffDone s)
810+ Skip s -> Skip (TapOffDone s)
811+ Stop -> Stop
812+
813+{-# INLINE_NORMAL pollCounts #-}
814+pollCounts
815+ :: MonadAsync m
816+ => (a -> Bool)
817+ -> (Stream m Int -> Stream m Int)
818+ -> Fold m Int b
819+ -> Stream m a
820+ -> Stream m a
821+pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
822+ where
823+
824+ {-# INLINE_LATE step' #-}
825+ step' _ Nothing = do
826+ -- As long as we are using an "Int" for counts lockfree reads from
827+ -- Var should work correctly on both 32-bit and 64-bit machines.
828+ -- However, an Int on a 32-bit machine may overflow quickly.
829+ countVar <- liftIO $ Prim.newIORef (0 :: Int)
830+ tid <- forkManaged
831+ $ void $ foldOnce fld
832+ $ transf $ fromPrimIORef countVar
833+ return $ Skip (Just (countVar, tid, state))
834+
835+ step' gst (Just (countVar, tid, st)) = do
836+ r <- step gst st
837+ case r of
838+ Yield x s -> do
839+ when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
840+ return $ Yield x (Just (countVar, tid, s))
841+ Skip s -> return $ Skip (Just (countVar, tid, s))
842+ Stop -> do
843+ liftIO $ killThread tid
844+ return Stop
845+
846+{-# INLINE_NORMAL tapRate #-}
847+tapRate ::
848+ (MonadAsync m, MonadCatch m)
849+ => Double
850+ -> (Int -> m b)
851+ -> Stream m a
852+ -> Stream m a
853+tapRate samplingRate action (Stream step state) = Stream step' Nothing
854+ where
855+ {-# NOINLINE loop #-}
856+ loop countVar prev = do
857+ i <-
858+ MC.catch
859+ (do liftIO $ threadDelay (round $ samplingRate * 1000000)
860+ i <- liftIO $ Prim.readIORef countVar
861+ let !diff = i - prev
862+ void $ action diff
863+ return i)
864+ (\(e :: AsyncException) -> do
865+ i <- liftIO $ Prim.readIORef countVar
866+ let !diff = i - prev
867+ void $ action diff
868+ throwM (MC.toException e))
869+ loop countVar i
870+
871+ {-# INLINE_LATE step' #-}
872+ step' _ Nothing = do
873+ countVar <- liftIO $ Prim.newIORef 0
874+ tid <- fork $ loop countVar 0
875+ ref <- liftIO $ newIORef ()
876+ _ <- liftIO $ mkWeakIORef ref (killThread tid)
877+ return $ Skip (Just (countVar, tid, state, ref))
878+
879+ step' gst (Just (countVar, tid, st, ref)) = do
880+ r <- step gst st
881+ case r of
882+ Yield x s -> do
883+ liftIO $ Prim.modifyIORef' countVar (+ 1)
884+ return $ Yield x (Just (countVar, tid, s, ref))
885+ Skip s -> return $ Skip (Just (countVar, tid, s, ref))
886+ Stop -> do
887+ liftIO $ killThread tid
888+ return Stop
889+
890+-------------------------------------------------------------------------------
891+-- Concurrent tap
892+-------------------------------------------------------------------------------
893+
894+-- | Create an SVar with a fold consumer that will fold any elements sent to it
895+-- using the supplied fold function.
896+{-# INLINE newFoldSVar #-}
897+newFoldSVar :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a)
898+newFoldSVar stt f = do
899+ -- Buffer size for the SVar is derived from the current state
900+ sv <- newParallelVar StopAny (adaptState stt)
901+ -- Add the producer thread-id to the SVar.
902+ liftIO myThreadId >>= modifyThread sv
903+ void $ doFork (work sv) (svarMrun sv) (handleFoldException sv)
904+ return sv
905+
906+ where
907+
908+ {-# NOINLINE work #-}
909+ work sv = void $ foldOnce f $ fromProducer sv
910+
911+{-# INLINE_NORMAL tapAsync #-}
912+tapAsync :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a
913+tapAsync f (Stream step1 state1) = Stream step TapInit
914+ where
915+
916+ drainFold svr = do
917+ -- In general, a Stop event would come equipped with the result
918+ -- of the fold. It is not used here but it would be useful in
919+ -- applicative and distribute.
920+ done <- fromConsumer svr
921+ when (not done) $ do
922+ liftIO $ withDiagMVar svr "teeToSVar: waiting to drain"
923+ $ takeMVar (outputDoorBellFromConsumer svr)
924+ drainFold svr
925+
926+ stopFold svr = do
927+ liftIO $ sendStop svr Nothing
928+ -- drain/wait until a stop event arrives from the fold.
929+ drainFold svr
930+
931+ {-# INLINE_LATE step #-}
932+ step gst TapInit = do
933+ sv <- newFoldSVar gst f
934+ return $ Skip (Tapping sv state1)
935+
936+ step gst (Tapping sv st) = do
937+ r <- step1 gst st
938+ case r of
939+ Yield a s -> do
940+ done <- pushToFold sv a
941+ if done
942+ then do
943+ -- XXX we do not need to wait synchronously here
944+ stopFold sv
945+ return $ Yield a (TapDone s)
946+ else return $ Yield a (Tapping sv s)
947+ Skip s -> return $ Skip (Tapping sv s)
948+ Stop -> do
949+ stopFold sv
950+ return $ Stop
951+
952+ step gst (TapDone st) = do
953+ r <- step1 gst st
954+ return $ case r of
955+ Yield a s -> Yield a (TapDone s)
956+ Skip s -> Skip (TapDone s)
957+ Stop -> Stop
958+
575959------------------------------------------------------------------------------
576960-- Inserting
577961------------------------------------------------------------------------------
@@ -812,6 +1196,227 @@ zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
8121196zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
8131197zipWith f = zipWithM (\a b -> return (f a b))
8141198
1199+------------------------------------------------------------------------------
1200+-- Repeated parsing
1201+------------------------------------------------------------------------------
1202+
1203+{-# ANN type ParseChunksState Fuse #-}
1204+data ParseChunksState x inpBuf st pst =
1205+ ParseChunksInit inpBuf st
1206+ | ParseChunksInitLeftOver inpBuf
1207+ | ParseChunksStream st inpBuf !pst
1208+ | ParseChunksBuf inpBuf st inpBuf !pst
1209+ | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1210+
1211+{-# INLINE_NORMAL parseMany #-}
1212+parseMany
1213+ :: MonadThrow m
1214+ => PRD.Parser m a b
1215+ -> Stream m a
1216+ -> Stream m b
1217+parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1218+ Stream stepOuter (ParseChunksInit [] state)
1219+
1220+ where
1221+
1222+ {-# INLINE_LATE stepOuter #-}
1223+ -- Buffer is empty, get the first element from the stream, initialize the
1224+ -- fold and then go to stream processing loop.
1225+ stepOuter gst (ParseChunksInit [] st) = do
1226+ r <- step (adaptState gst) st
1227+ case r of
1228+ Yield x s -> initial >>= return . Skip . ParseChunksBuf [x] s []
1229+ Skip s -> return $ Skip $ ParseChunksInit [] s
1230+ Stop -> return Stop
1231+
1232+ -- Buffer is not empty, go to buffered processing loop
1233+ stepOuter _ (ParseChunksInit src st) = do
1234+ initial >>= return . Skip . ParseChunksBuf src st []
1235+
1236+ -- XXX we just discard any leftover input at the end
1237+ stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1238+
1239+ -- Buffer is empty, process elements from the stream
1240+ stepOuter gst (ParseChunksStream st buf pst) = do
1241+ r <- step (adaptState gst) st
1242+ case r of
1243+ Yield x s -> do
1244+ pRes <- pstep pst x
1245+ case pRes of
1246+ PR.Partial 0 pst1 ->
1247+ return $ Skip $ ParseChunksStream s [] pst1
1248+ PR.Partial n pst1 -> do
1249+ assert (n <= length (x:buf)) (return ())
1250+ let src0 = Prelude.take n (x:buf)
1251+ src = Prelude.reverse src0
1252+ return $ Skip $ ParseChunksBuf src s [] pst1
1253+ PR.Continue 0 pst1 ->
1254+ return $ Skip $ ParseChunksStream s (x:buf) pst1
1255+ PR.Continue n pst1 -> do
1256+ assert (n <= length (x:buf)) (return ())
1257+ let (src0, buf1) = splitAt n (x:buf)
1258+ src = Prelude.reverse src0
1259+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1260+ PR.Done 0 b -> do
1261+ return $ Skip $
1262+ ParseChunksYield b (ParseChunksInit [] s)
1263+ PR.Done n b -> do
1264+ assert (n <= length (x:buf)) (return ())
1265+ let src = Prelude.reverse (Prelude.take n (x:buf))
1266+ return $ Skip $
1267+ ParseChunksYield b (ParseChunksInit src s)
1268+ PR.Error err -> throwM $ ParseError err
1269+ Skip s -> return $ Skip $ ParseChunksStream s buf pst
1270+ Stop -> do
1271+ b <- extract pst
1272+ let src = Prelude.reverse buf
1273+ return $ Skip $
1274+ ParseChunksYield b (ParseChunksInitLeftOver src)
1275+
1276+ -- go back to stream processing mode
1277+ stepOuter _ (ParseChunksBuf [] s buf pst) =
1278+ return $ Skip $ ParseChunksStream s buf pst
1279+
1280+ -- buffered processing loop
1281+ stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1282+ pRes <- pstep pst x
1283+ case pRes of
1284+ PR.Partial 0 pst1 ->
1285+ return $ Skip $ ParseChunksBuf xs s [] pst1
1286+ PR.Partial n pst1 -> do
1287+ assert (n <= length (x:buf)) (return ())
1288+ let src0 = Prelude.take n (x:buf)
1289+ src = Prelude.reverse src0 ++ xs
1290+ return $ Skip $ ParseChunksBuf src s [] pst1
1291+ PR.Continue 0 pst1 ->
1292+ return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1293+ PR.Continue n pst1 -> do
1294+ assert (n <= length (x:buf)) (return ())
1295+ let (src0, buf1) = splitAt n (x:buf)
1296+ src = Prelude.reverse src0 ++ xs
1297+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1298+ PR.Done 0 b ->
1299+ return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1300+ PR.Done n b -> do
1301+ assert (n <= length (x:buf)) (return ())
1302+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1303+ return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1304+ PR.Error err -> throwM $ ParseError err
1305+
1306+ stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1307+
1308+{-# ANN type ConcatParseState Fuse #-}
1309+data ConcatParseState x inpBuf st p =
1310+ ConcatParseInit inpBuf st p
1311+ | ConcatParseInitLeftOver inpBuf
1312+ | ConcatParseStream st inpBuf p
1313+ | ConcatParseBuf inpBuf st inpBuf p
1314+ | ConcatParseYield x (ConcatParseState x inpBuf st p)
1315+
1316+{-# INLINE_NORMAL parseIterate #-}
1317+parseIterate
1318+ :: MonadThrow m
1319+ => (b -> PRD.Parser m a b)
1320+ -> b
1321+ -> Stream m a
1322+ -> Stream m b
1323+parseIterate func seed (Stream step state) =
1324+ Stream stepOuter (ConcatParseInit [] state (func seed))
1325+
1326+ where
1327+
1328+ {-# INLINE_LATE stepOuter #-}
1329+ -- Buffer is empty, go to stream processing loop
1330+ stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1331+ initial >>= \r -> return $ Skip $ ConcatParseStream st []
1332+ (PRD.Parser pstep (return r) extract)
1333+
1334+ -- Buffer is not empty, go to buffered processing loop
1335+ stepOuter _ (ConcatParseInit src st
1336+ (PRD.Parser pstep initial extract)) = do
1337+ initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1338+ (PRD.Parser pstep (return r) extract)
1339+
1340+ -- XXX we just discard any leftover input at the end
1341+ stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1342+
1343+ -- Buffer is empty process elements from the stream
1344+ stepOuter gst (ConcatParseStream st buf
1345+ p@(PRD.Parser pstep initial extract)) = do
1346+ r <- step (adaptState gst) st
1347+ case r of
1348+ Yield x s -> do
1349+ pst <- initial
1350+ pRes <- pstep pst x
1351+ case pRes of
1352+ PR.Partial 0 pst1 ->
1353+ return $ Skip $ ConcatParseStream s []
1354+ (PRD.Parser pstep (return pst1) extract)
1355+ PR.Partial n pst1 -> do
1356+ assert (n <= length (x:buf)) (return ())
1357+ let src0 = Prelude.take n (x:buf)
1358+ src = Prelude.reverse src0
1359+ return $ Skip $ ConcatParseBuf src s []
1360+ (PRD.Parser pstep (return pst1) extract)
1361+ -- PR.Continue 0 pst1 ->
1362+ -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1363+ PR.Continue n pst1 -> do
1364+ assert (n <= length (x:buf)) (return ())
1365+ let (src0, buf1) = splitAt n (x:buf)
1366+ src = Prelude.reverse src0
1367+ return $ Skip $ ConcatParseBuf src s buf1
1368+ (PRD.Parser pstep (return pst1) extract)
1369+ -- XXX Specialize for Stop 0 common case?
1370+ PR.Done n b -> do
1371+ assert (n <= length (x:buf)) (return ())
1372+ let src = Prelude.reverse (Prelude.take n (x:buf))
1373+ return $ Skip $
1374+ ConcatParseYield b (ConcatParseInit src s (func b))
1375+ PR.Error err -> throwM $ ParseError err
1376+ Skip s -> return $ Skip $ ConcatParseStream s buf p
1377+ Stop -> do
1378+ pst <- initial
1379+ b <- extract pst
1380+ let src = Prelude.reverse buf
1381+ return $ Skip $
1382+ ConcatParseYield b (ConcatParseInitLeftOver src)
1383+
1384+ -- go back to stream processing mode
1385+ stepOuter _ (ConcatParseBuf [] s buf p) =
1386+ return $ Skip $ ConcatParseStream s buf p
1387+
1388+ -- buffered processing loop
1389+ stepOuter _ (ConcatParseBuf (x:xs) s buf
1390+ (PRD.Parser pstep initial extract)) = do
1391+ pst <- initial
1392+ pRes <- pstep pst x
1393+ case pRes of
1394+ PR.Partial 0 pst1 ->
1395+ return $ Skip $ ConcatParseBuf xs s []
1396+ (PRD.Parser pstep (return pst1) extract)
1397+ PR.Partial n pst1 -> do
1398+ assert (n <= length (x:buf)) (return ())
1399+ let src0 = Prelude.take n (x:buf)
1400+ src = Prelude.reverse src0 ++ xs
1401+ return $ Skip $ ConcatParseBuf src s []
1402+ (PRD.Parser pstep (return pst1) extract)
1403+ -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1404+ PR.Continue n pst1 -> do
1405+ assert (n <= length (x:buf)) (return ())
1406+ let (src0, buf1) = splitAt n (x:buf)
1407+ src = Prelude.reverse src0 ++ xs
1408+ return $ Skip $ ConcatParseBuf src s buf1
1409+ (PRD.Parser pstep (return pst1) extract)
1410+ -- XXX Specialize for Stop 0 common case?
1411+ PR.Done n b -> do
1412+ assert (n <= length (x:buf)) (return ())
1413+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1414+ return $ Skip $ ConcatParseYield b
1415+ (ConcatParseInit src s (func b))
1416+ PR.Error err -> throwM $ ParseError err
1417+
1418+ stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1419+
8151420------------------------------------------------------------------------------
8161421-- Merging
8171422------------------------------------------------------------------------------
@@ -982,3 +1587,75 @@ dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
9821587 Yield x s -> Yield x (DropByTimeYield s)
9831588 Skip s -> Skip (DropByTimeYield s)
9841589 Stop -> Stop
1590+
1591+-------------------------------------------------------------------------------
1592+-- Hoisting the inner monad
1593+-------------------------------------------------------------------------------
1594+
1595+{-# INLINE_NORMAL hoist #-}
1596+hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
1597+hoist f (Stream step state) = (Stream step' state)
1598+ where
1599+ {-# INLINE_LATE step' #-}
1600+ step' gst st = do
1601+ r <- f $ step (adaptState gst) st
1602+ return $ case r of
1603+ Yield x s -> Yield x s
1604+ Skip s -> Skip s
1605+ Stop -> Stop
1606+
1607+{-# INLINE generally #-}
1608+generally :: Monad m => Stream Identity a -> Stream m a
1609+generally = hoist (return . runIdentity)
1610+
1611+{-# INLINE_NORMAL liftInner #-}
1612+liftInner :: (Monad m, MonadTrans t, Monad (t m))
1613+ => Stream m a -> Stream (t m) a
1614+liftInner (Stream step state) = Stream step' state
1615+ where
1616+ {-# INLINE_LATE step' #-}
1617+ step' gst st = do
1618+ r <- lift $ step (adaptState gst) st
1619+ return $ case r of
1620+ Yield x s -> Yield x s
1621+ Skip s -> Skip s
1622+ Stop -> Stop
1623+
1624+{-# INLINE_NORMAL runReaderT #-}
1625+runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
1626+runReaderT env (Stream step state) = Stream step' (state, env)
1627+ where
1628+ {-# INLINE_LATE step' #-}
1629+ step' gst (st, action) = do
1630+ sv <- action
1631+ r <- Reader.runReaderT (step (adaptState gst) st) sv
1632+ return $ case r of
1633+ Yield x s -> Yield x (s, return sv)
1634+ Skip s -> Skip (s, return sv)
1635+ Stop -> Stop
1636+
1637+{-# INLINE_NORMAL evalStateT #-}
1638+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
1639+evalStateT initial (Stream step state) = Stream step' (state, initial)
1640+ where
1641+ {-# INLINE_LATE step' #-}
1642+ step' gst (st, action) = do
1643+ sv <- action
1644+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
1645+ return $ case r of
1646+ Yield x s -> Yield x (s, return sv')
1647+ Skip s -> Skip (s, return sv')
1648+ Stop -> Stop
1649+
1650+{-# INLINE_NORMAL runStateT #-}
1651+runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
1652+runStateT initial (Stream step state) = Stream step' (state, initial)
1653+ where
1654+ {-# INLINE_LATE step' #-}
1655+ step' gst (st, action) = do
1656+ sv <- action
1657+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
1658+ return $ case r of
1659+ Yield x s -> Yield (sv', x) (s, return sv')
1660+ Skip s -> Skip (s, return sv')
1661+ Stop -> Stop