Skip to content

Commit 3d9f5ed

Browse files
committed
Add more levity-monomorphized variants of bind, pure, and fail
1 parent 53a3e10 commit 3d9f5ed

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/Data/Bytes/Parser.hs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ module Data.Bytes.Parser
7979

8080
-- * Repetition
8181
, replicate
82+
, listUntilEoi
8283

8384
-- * Subparsing
8485
, delimit
@@ -104,37 +105,45 @@ module Data.Bytes.Parser
104105
-- of monadic @>>=@ can be helpful. If @C#@, @I#@, etc. never
105106
-- get used in your original source code, GHC will not introduce them.
106107
, bindFromCharToLifted
108+
, bindFromCharToByteArrayIntInt
107109
, bindFromLiftedToIntPair
108110
, bindFromLiftedToInt
109111
, bindFromIntToIntPair
110112
, bindFromCharToIntPair
113+
, bindFromLiftedToByteArrayIntInt
114+
, bindFromByteArrayIntIntToLifted
111115
, bindFromMaybeCharToIntPair
112116
, bindFromMaybeCharToLifted
113117

114118
-- * Specialized Pure
115119
, pureIntPair
120+
, pureByteArrayIntInt
116121

117122
-- * Specialized Fail
118123
, failIntPair
124+
, failByteArrayIntInt
119125
) where
120126

121127
import Prelude hiding (any, fail, length, replicate, take, takeWhile)
122128

123129
import Data.Bytes.Parser.Internal (Parser (..), Result#, ST#, boxBytes, fail, unboxBytes, uneffectful, uneffectful#, uneffectfulInt#)
130+
import Data.Bytes.Parser.Internal (failByteArrayIntInt)
124131
import Data.Bytes.Parser.Types (Result (Failure, Success), Slice (Slice))
125132
import Data.Bytes.Parser.Unsafe (cursor, expose, unconsume)
126133
import Data.Bytes.Types (Bytes (..), BytesN (BytesN))
127134
import Data.Primitive (ByteArray (..))
128135
import Data.Primitive.Contiguous (Contiguous, Element)
129136
import Foreign.C.String (CString)
130137
import GHC.Exts (Char#, Int (I#), Int#, Word#, runRW#, (+#), (-#), (>=#))
138+
import GHC.Exts (ByteArray#)
131139
import GHC.ST (ST (..))
132140
import GHC.Word (Word32 (W32#), Word8)
133141

134142
import qualified Arithmetic.Nat as Nat
135143
import qualified Arithmetic.Types as Arithmetic
136144
import qualified Data.Bytes as B
137145
import qualified Data.Bytes.Parser.Internal as Internal
146+
import qualified Data.List as List
138147
import qualified Data.Primitive as PM
139148
import qualified Data.Primitive.Contiguous as C
140149
import qualified GHC.Exts as Exts
@@ -696,6 +705,17 @@ bindFromCharToLifted (Parser f) g =
696705
runParser (g y) (# arr, b, c #) s1
697706
)
698707

708+
bindFromCharToByteArrayIntInt :: Parser s e Char# -> (Char# -> Parser s e (# ByteArray#, Int#, Int# #)) -> Parser s e (# ByteArray#, Int#, Int# #)
709+
{-# INLINE bindFromCharToByteArrayIntInt #-}
710+
bindFromCharToByteArrayIntInt (Parser f) g =
711+
Parser
712+
( \x@(# arr, _, _ #) s0 -> case f x s0 of
713+
(# s1, r0 #) -> case r0 of
714+
(# e | #) -> (# s1, (# e | #) #)
715+
(# | (# y, b, c #) #) ->
716+
runParser (g y) (# arr, b, c #) s1
717+
)
718+
699719
bindFromCharToIntPair :: Parser s e Char# -> (Char# -> Parser s e (# Int#, Int# #)) -> Parser s e (# Int#, Int# #)
700720
{-# INLINE bindFromCharToIntPair #-}
701721
bindFromCharToIntPair (Parser f) g =
@@ -718,6 +738,34 @@ bindFromLiftedToInt (Parser f) g =
718738
runParser (g y) (# arr, b, c #) s1
719739
)
720740

741+
bindFromByteArrayIntIntToLifted ::
742+
Parser s e (# ByteArray#, Int#, Int# #)
743+
-> ((# ByteArray#, Int#, Int# #) -> Parser s e a)
744+
-> Parser s e a
745+
{-# INLINE bindFromByteArrayIntIntToLifted #-}
746+
bindFromByteArrayIntIntToLifted (Parser f) g =
747+
Parser
748+
( \x@(# arr, _, _ #) s0 -> case f x s0 of
749+
(# s1, r0 #) -> case r0 of
750+
(# e | #) -> (# s1, (# e | #) #)
751+
(# | (# y, b, c #) #) ->
752+
runParser (g y) (# arr, b, c #) s1
753+
)
754+
755+
bindFromLiftedToByteArrayIntInt ::
756+
Parser s e a
757+
-> (a -> Parser s e (# ByteArray#, Int#, Int# #))
758+
-> Parser s e (# ByteArray#, Int#, Int# #)
759+
{-# INLINE bindFromLiftedToByteArrayIntInt #-}
760+
bindFromLiftedToByteArrayIntInt (Parser f) g =
761+
Parser
762+
( \x@(# arr, _, _ #) s0 -> case f x s0 of
763+
(# s1, r0 #) -> case r0 of
764+
(# e | #) -> (# s1, (# e | #) #)
765+
(# | (# y, b, c #) #) ->
766+
runParser (g y) (# arr, b, c #) s1
767+
)
768+
721769
bindFromLiftedToIntPair :: Parser s e a -> (a -> Parser s e (# Int#, Int# #)) -> Parser s e (# Int#, Int# #)
722770
{-# INLINE bindFromLiftedToIntPair #-}
723771
bindFromLiftedToIntPair (Parser f) g =
@@ -776,6 +824,14 @@ pureIntPair a =
776824
Parser
777825
(\(# _, b, c #) s -> (# s, (# | (# a, b, c #) #) #))
778826

827+
pureByteArrayIntInt ::
828+
(# ByteArray#, Int#, Int# #) ->
829+
Parser s e (# ByteArray#, Int#, Int# #)
830+
{-# INLINE pureByteArrayIntInt #-}
831+
pureByteArrayIntInt a =
832+
Parser
833+
(\(# _, b, c #) s -> (# s, (# | (# a, b, c #) #) #))
834+
779835
failIntPair :: e -> Parser e s (# Int#, Int# #)
780836
{-# INLINE failIntPair #-}
781837
failIntPair e =
@@ -848,6 +904,20 @@ delimit esz eleftovers (I# n) (Parser f) =
848904
_ -> (# s0, (# esz | #) #)
849905
)
850906

907+
{- | Apply the parser repeatedly until there is no more input left
908+
to consume. Collects the results into a list.
909+
-}
910+
listUntilEoi ::
911+
Parser e s a -- ^ Parser to repeatedly apply until input is exhausted
912+
-> Parser e s [a]
913+
listUntilEoi p = go []
914+
where
915+
go !acc = isEndOfInput >>= \case
916+
True -> pure $! List.reverse acc
917+
False -> do
918+
a <- p
919+
go (a : acc)
920+
851921
{- | Replicate a parser @n@ times, writing the results into
852922
an array of length @n@. For @Array@ and @SmallArray@, this
853923
is lazy in the elements, so be sure the they result of the

src/Data/Bytes/Parser/Internal.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module Data.Bytes.Parser.Internal
2525
, unboxBytes
2626
, unboxResult
2727
, fail
28+
, failByteArrayIntInt
2829
, indexLatinCharArray
2930
, upcastUnitSuccess
3031
-- Swapping
@@ -44,6 +45,7 @@ import Data.Kind (Type)
4445
import Data.Primitive (ByteArray (ByteArray))
4546
import Data.Word (Word8)
4647
import GHC.Exts (ByteArray#, Char (C#), Int (I#), Int#, RuntimeRep, State#, TYPE)
48+
import GHC.Exts (RuntimeRep(IntRep, BoxedRep, TupleRep), Levity(Unlifted))
4749

4850
import qualified Control.Applicative
4951
import qualified Control.Monad
@@ -129,6 +131,13 @@ fail ::
129131
{-# INLINE fail #-}
130132
fail e = uneffectful $ \_ -> Failure e
131133

134+
failByteArrayIntInt :: forall e s (a :: TYPE ('TupleRep '[ 'BoxedRep 'Unlifted, 'IntRep, 'IntRep ])).
135+
-- | Error message
136+
e ->
137+
Parser e s a
138+
{-# INLINE failByteArrayIntInt #-}
139+
failByteArrayIntInt e = Parser (\_ s0 -> (# s0, (# e | #) #))
140+
132141
instance Applicative (Parser e s) where
133142
pure = pureParser
134143
(<*>) = Control.Monad.ap

0 commit comments

Comments
 (0)