{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
#if __GLASGOW_HASKELL__ >= 800
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
#endif
#include "inline.hs"
module Streamly.Internal.Data.Parser.Tee
(
teeWith
, teeWithFst
, teeWithMin
, shortest
, longest
)
where
import Control.Exception (assert)
import Control.Monad.Catch (MonadCatch, try)
import Prelude
hiding (any, all, takeWhile)
import Fusion.Plugin.Types (Fuse(..))
import Streamly.Internal.Data.Parser.Types (Parser(..), Step(..), ParseError)
{-# ANN type StepState Fuse #-}
data StepState s a = StepState s | StepResult a
{-# ANN type TeeState Fuse #-}
data TeeState sL sR x a b =
TeePair !([x], StepState sL a, [x], [x]) !([x], StepState sR b, [x], [x])
{-# ANN type Res Fuse #-}
data Res = Yld Int | Stp Int | Skp | Err String
{-# INLINE teeWith #-}
teeWith :: Monad m
=> (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
teeWith zf (Parser stepL initialL extractL) (Parser stepR initialR extractR) =
Parser step initial extract
where
{-# INLINE_LATE initial #-}
initial = do
sL <- initialL
sR <- initialR
return $ TeePair ([], StepState sL, [], []) ([], StepState sR, [], [])
{-# INLINE consume #-}
consume buf inp1 inp2 stp st y = do
let (x, inp11, inp21) =
case inp1 of
[] -> (y, [], [])
z : [] -> (z, reverse (x:inp2), [])
z : zs -> (z, zs, x:inp2)
r <- stp st x
let buf1 = x:buf
return (buf1, r, inp11, inp21)
{-# INLINE useStream #-}
useStream buf inp1 inp2 stp st y = do
(buf1, r, inp11, inp21) <- consume buf inp1 inp2 stp st y
case r of
Yield n s ->
let state = (Prelude.take n buf1, StepState s, inp11, inp21)
in assert (n <= length buf1) (return (state, Yld n))
Stop n b ->
let state = (Prelude.take n buf1, StepResult b, inp11, inp21)
in assert (n <= length buf1) (return (state, Stp n))
Skip n s ->
let (src0, buf2) = splitAt n buf1
src = Prelude.reverse src0
state = (buf2, StepState s, src ++ inp11, inp21)
in assert (n <= length buf1) (return (state, Skp))
Error err -> return (undefined, Err err)
{-# INLINE_LATE step #-}
step (TeePair (bufL, StepState sL, inpL1, inpL2)
(bufR, StepState sR, inpR1, inpR2)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
(r,stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
return $ case (stL,stR) of
(Yld n1, Yld n2) -> Yield (min n1 n2) next
(Yld n1, Stp n2) -> Yield (min n1 n2) next
(Stp n1, Yld n2) -> Yield (min n1 n2) next
(Stp n1, Stp n2) ->
let (_, StepResult rL, _, _) = l
(_, StepResult rR, _, _) = r
in Stop (min n1 n2) (zf rL rR)
(Err err, _) -> Error err
(_, Err err) -> Error err
_ -> Skip 0 next
step (TeePair (bufL, StepState sL, inpL1, inpL2)
r@(_, StepResult rR, _, _)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
let next = TeePair l r
return $ case stL of
Yld n -> Yield n next
Stp n ->
let (_, StepResult rL, _, _) = l
in Stop n (zf rL rR)
Skp -> Skip 0 next
Err err -> Error err
step (TeePair l@(_, StepResult rL, _, _)
(bufR, StepState sR, inpR1, inpR2)) x = do
(r, stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
return $ case stR of
Yld n -> Yield n next
Stp n ->
let (_, StepResult rR, _, _) = r
in Stop n (zf rL rR)
Skp -> Skip 0 next
Err err -> Error err
step _ _ = undefined
{-# INLINE_LATE extract #-}
extract st =
case st of
TeePair (_, StepState sL, _, _) (_, StepState sR, _, _) -> do
rL <- extractL sL
rR <- extractR sR
return $ zf rL rR
TeePair (_, StepState sL, _, _) (_, StepResult rR, _, _) -> do
rL <- extractL sL
return $ zf rL rR
TeePair (_, StepResult rL, _, _) (_, StepState sR, _, _) -> do
rR <- extractR sR
return $ zf rL rR
TeePair (_, StepResult rL, _, _) (_, StepResult rR, _, _) ->
return $ zf rL rR
{-# INLINE teeWithFst #-}
teeWithFst :: Monad m
=> (a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
teeWithFst zf (Parser stepL initialL extractL)
(Parser stepR initialR extractR) =
Parser step initial extract
where
{-# INLINE_LATE initial #-}
initial = do
sL <- initialL
sR <- initialR
return $ TeePair ([], StepState sL, [], []) ([], StepState sR, [], [])
{-# INLINE consume #-}
consume buf inp1 inp2 stp st y = do
let (x, inp11, inp21) =
case inp1 of
[] -> (y, [], [])
z : [] -> (z, reverse (x:inp2), [])
z : zs -> (z, zs, x:inp2)
r <- stp st x
let buf1 = x:buf
return (buf1, r, inp11, inp21)
{-# INLINE useStream #-}
useStream buf inp1 inp2 stp st y = do
(buf1, r, inp11, inp21) <- consume buf inp1 inp2 stp st y
case r of
Yield n s ->
let state = (Prelude.take n buf1, StepState s, inp11, inp21)
in assert (n <= length buf1) (return (state, Yld n))
Stop n b ->
let state = (Prelude.take n buf1, StepResult b, inp11, inp21)
in assert (n <= length buf1) (return (state, Stp n))
Skip n s ->
let (src0, buf2) = splitAt n buf1
src = Prelude.reverse src0
state = (buf2, StepState s, src ++ inp11, inp21)
in assert (n <= length buf1) (return (state, Skp))
Error err -> return (undefined, Err err)
{-# INLINE_LATE step #-}
step (TeePair (bufL, StepState sL, inpL1, inpL2)
(bufR, StepState sR, inpR1, inpR2)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
(r,stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
case (stL,stR) of
(Stp n1, Stp _) ->
let (_, StepResult rL, _, _) = l
(_, StepResult rR, _, _) = r
in return $ Stop n1 (zf rL rR)
(Stp n1, Yld _) ->
let (_, StepResult rL, _, _) = l
(_, StepState ssR, _, _) = r
in do
rR <- extractR ssR
return $ Stop n1 (zf rL rR)
(Yld n1, Yld n2) -> return $ Yield (min n1 n2) next
(Yld n1, Stp n2) -> return $ Yield (min n1 n2) next
(Err err, _) -> return $ Error err
(_, Err err) -> return $ Error err
_ -> return $ Skip 0 next
step (TeePair (bufL, StepState sL, inpL1, inpL2)
r@(_, StepResult rR, _, _)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
let next = TeePair l r
return $ case stL of
Yld n -> Yield n next
Stp n ->
let (_, StepResult rL, _, _) = l
in Stop n (zf rL rR)
Skp -> Skip 0 next
Err err -> Error err
step _ _ = undefined
{-# INLINE_LATE extract #-}
extract st =
case st of
TeePair (_, StepState sL, _, _) (_, StepState sR, _, _) -> do
rL <- extractL sL
rR <- extractR sR
return $ zf rL rR
TeePair (_, StepState sL, _, _) (_, StepResult rR, _, _) -> do
rL <- extractL sL
return $ zf rL rR
_ -> error "unreachable"
{-# INLINE teeWithMin #-}
teeWithMin ::
(a -> b -> c) -> Parser m x a -> Parser m x b -> Parser m x c
teeWithMin = undefined
{-# INLINE shortest #-}
shortest :: Monad m => Parser m x a -> Parser m x a -> Parser m x a
shortest (Parser stepL initialL extractL) (Parser stepR initialR _) =
Parser step initial extract
where
{-# INLINE_LATE initial #-}
initial = do
sL <- initialL
sR <- initialR
return $ TeePair ([], StepState sL, [], []) ([], StepState sR, [], [])
{-# INLINE consume #-}
consume buf inp1 inp2 stp st y = do
let (x, inp11, inp21) =
case inp1 of
[] -> (y, [], [])
z : [] -> (z, reverse (x:inp2), [])
z : zs -> (z, zs, x:inp2)
r <- stp st x
let buf1 = x:buf
return (buf1, r, inp11, inp21)
{-# INLINE useStream #-}
useStream buf inp1 inp2 stp st y = do
(buf1, r, inp11, inp21) <- consume buf inp1 inp2 stp st y
case r of
Yield n s ->
let state = (Prelude.take n buf1, StepState s, inp11, inp21)
in assert (n <= length buf1) (return (state, Yld n))
Stop n b ->
let state = (Prelude.take n buf1, StepResult b, inp11, inp21)
in assert (n <= length buf1) (return (state, Stp n))
Skip n s ->
let (src0, buf2) = splitAt n buf1
src = Prelude.reverse src0
state = (buf2, StepState s, src ++ inp11, inp21)
in assert (n <= length buf1) (return (state, Skp))
Error err -> return (undefined, Err err)
{-# INLINE_LATE step #-}
step (TeePair (bufL, StepState sL, inpL1, inpL2)
(bufR, StepState sR, inpR1, inpR2)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
(r,stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
return $ case (stL,stR) of
(Stp n1, _) ->
let (_, StepResult rL, _, _) = l
in Stop n1 rL
(_, Stp n2) ->
let (_, StepResult rR, _, _) = r
in Stop n2 rR
(Yld n1, Yld n2) -> Yield (min n1 n2) next
(Err err, _) -> Error err
(_, Err err) -> Error err
_ -> Skip 0 next
step _ _ = undefined
{-# INLINE_LATE extract #-}
extract st =
case st of
TeePair (_, StepState sL, _, _) _ -> extractL sL
_ -> error "unreachable"
{-# INLINE longest #-}
longest :: MonadCatch m => Parser m x a -> Parser m x a -> Parser m x a
longest (Parser stepL initialL extractL) (Parser stepR initialR extractR) =
Parser step initial extract
where
{-# INLINE_LATE initial #-}
initial = do
sL <- initialL
sR <- initialR
return $ TeePair ([], StepState sL, [], []) ([], StepState sR, [], [])
{-# INLINE consume #-}
consume buf inp1 inp2 stp st y = do
let (x, inp11, inp21) =
case inp1 of
[] -> (y, [], [])
z : [] -> (z, reverse (x:inp2), [])
z : zs -> (z, zs, x:inp2)
r <- stp st x
let buf1 = x:buf
return (buf1, r, inp11, inp21)
{-# INLINE useStream #-}
useStream buf inp1 inp2 stp st y = do
(buf1, r, inp11, inp21) <- consume buf inp1 inp2 stp st y
case r of
Yield n s ->
let state = (Prelude.take n buf1, StepState s, inp11, inp21)
in assert (n <= length buf1) (return (state, Yld n))
Stop n b ->
let state = (Prelude.take n buf1, StepResult b, inp11, inp21)
in assert (n <= length buf1) (return (state, Stp n))
Skip n s ->
let (src0, buf2) = splitAt n buf1
src = Prelude.reverse src0
state = (buf2, StepState s, src ++ inp11, inp21)
in assert (n <= length buf1) (return (state, Skp))
Error err -> return (undefined, Err err)
{-# INLINE_LATE step #-}
step (TeePair (bufL, StepState sL, inpL1, inpL2)
(bufR, StepState sR, inpR1, inpR2)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
(r,stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
return $ case (stL,stR) of
(Yld n1, Yld n2) -> Yield (min n1 n2) next
(Yld n1, Stp n2) -> Yield (min n1 n2) next
(Stp n1, Yld n2) -> Yield (min n1 n2) next
(Stp n1, Stp n2) ->
let (_, StepResult rL, _, _) = l
(_, StepResult rR, _, _) = r
in Stop (max n1 n2) (if n1 >= n2 then rL else rR)
(Err err, _) -> Error err
(_, Err err) -> Error err
_ -> Skip 0 next
step (TeePair (bufL, StepState sL, inpL1, inpL2)
r@(_, StepResult _, _, _)) x = do
(l,stL) <- useStream bufL inpL1 inpL2 stepL sL x
let next = TeePair l r
return $ case stL of
Yld n -> Yield n next
Stp n ->
let (_, StepResult rL, _, _) = l
in Stop n rL
Skp -> Skip 0 next
Err err -> Error err
step (TeePair l@(_, StepResult _, _, _)
(bufR, StepState sR, inpR1, inpR2)) x = do
(r, stR) <- useStream bufR inpR1 inpR2 stepR sR x
let next = TeePair l r
return $ case stR of
Yld n -> Yield n next
Stp n ->
let (_, StepResult rR, _, _) = r
in Stop n rR
Skp -> Skip 0 next
Err err -> Error err
step _ _ = undefined
{-# INLINE_LATE extract #-}
extract st =
case st of
TeePair (_, StepState sL, _, _) (_, StepState sR, _, _) -> do
r <- try $ extractL sL
case r of
Left (_ :: ParseError) -> extractR sR
Right b -> return b
TeePair (_, StepState sL, _, _) (_, StepResult rR, _, _) -> do
r <- try $ extractL sL
case r of
Left (_ :: ParseError) -> return rR
Right b -> return b
TeePair (_, StepResult rL, _, _) (_, StepState sR, _, _) -> do
r <- try $ extractR sR
case r of
Left (_ :: ParseError) -> return rL
Right b -> return b
TeePair (_, StepResult _, _, _) (_, StepResult _, _, _) ->
error "unreachable"