diff options
author | Bodigrim <andrew.lelechenko@gmail.com> | 2021-12-01 23:15:43 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-03-25 11:36:31 -0400 |
commit | 83f5841b32ef11c54ff1e24dd5b92bc3c77f6250 (patch) | |
tree | 06014aaef052ba54a384e59f093fb7295fe68bce /libraries | |
parent | 1d673aa25205084d3973a3e9c7b7cd84a8b3171c (diff) | |
download | haskell-83f5841b32ef11c54ff1e24dd5b92bc3c77f6250.tar.gz |
Add instance Lift ByteArray
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/template-haskell/Language/Haskell/TH/Syntax.hs | 58 | ||||
-rw-r--r-- | libraries/template-haskell/changelog.md | 1 |
2 files changed, 58 insertions, 1 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs index 5acf96e011..08d2ea41bf 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs @@ -3,7 +3,7 @@ RankNTypes, RoleAnnotations, ScopedTypeVariables, MagicHash, KindSignatures, PolyKinds, TypeApplications, DataKinds, GADTs, UnboxedTuples, UnboxedSums, TypeInType, TypeOperators, - Trustworthy, DeriveFunctor #-} + Trustworthy, DeriveFunctor, BangPatterns, RecordWildCards, ImplicitParams #-} {-# OPTIONS_GHC -fno-warn-inline-rule-shadowing #-} @@ -61,11 +61,22 @@ import Prelude import Foreign.ForeignPtr import Foreign.C.String import Foreign.C.Types +import GHC.Stack #if __GLASGOW_HASKELL__ >= 901 import GHC.Types ( Levity(..) ) #endif +#if __GLASGOW_HASKELL__ >= 903 +import Data.Array.Byte (ByteArray(..)) +import GHC.Exts + ( ByteArray#, unsafeFreezeByteArray#, copyAddrToByteArray#, newByteArray# + , isByteArrayPinned#, isTrue#, sizeofByteArray#, unsafeCoerce#, byteArrayContents# + , copyByteArray#, newPinnedByteArray#) +import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..)) +import GHC.ST (ST(..), runST) +#endif + ----------------------------------------------------- -- -- The Quasi class @@ -1074,6 +1085,51 @@ instance Lift Addr# where lift x = return (LitE (StringPrimL (map (fromIntegral . ord) (unpackCString# x)))) +#if __GLASGOW_HASKELL__ >= 903 + +-- | +-- @since 2.19.0.0 +instance Lift ByteArray where + liftTyped x = unsafeCodeCoerce (lift x) + lift (ByteArray b) = return + (AppE (AppE (VarE addrToByteArrayName) (LitE (IntegerL (fromIntegral len)))) + (LitE (BytesPrimL (Bytes ptr 0 (fromIntegral len))))) + where + len# = sizeofByteArray# b + len = I# len# + pb :: ByteArray# + !(ByteArray pb) + | isTrue# (isByteArrayPinned# b) = ByteArray b + | otherwise = runST $ ST $ + \s -> case newPinnedByteArray# len# s of + (# s', mb #) -> case copyByteArray# b 0# mb 0# len# s' of + s'' -> case unsafeFreezeByteArray# mb s'' of + (# s''', ret #) -> (# s''', ByteArray ret #) + ptr :: ForeignPtr Word8 + ptr = ForeignPtr (byteArrayContents# pb) (PlainPtr (unsafeCoerce# pb)) + + +-- We can't use a TH quote in this module because we're in the template-haskell +-- package, so we conconct this quite defensive solution to make the correct name +-- which will work if the package name or module name changes in future. +addrToByteArrayName :: Name +addrToByteArrayName = helper + where + helper :: HasCallStack => Name + helper = + case head (getCallStack ?callStack) of + (_, SrcLoc{..}) -> mkNameG_v srcLocPackage srcLocModule "addrToByteArray" + + +addrToByteArray :: Int -> Addr# -> ByteArray +addrToByteArray (I# len) addr = runST $ ST $ + \s -> case newByteArray# len s of + (# s', mb #) -> case copyAddrToByteArray# addr mb 0# len s' of + s'' -> case unsafeFreezeByteArray# mb s'' of + (# s''', ret #) -> (# s''', ByteArray ret #) + +#endif + instance Lift a => Lift (Maybe a) where liftTyped x = unsafeCodeCoerce (lift x) diff --git a/libraries/template-haskell/changelog.md b/libraries/template-haskell/changelog.md index 3965279f15..e3bcef509a 100644 --- a/libraries/template-haskell/changelog.md +++ b/libraries/template-haskell/changelog.md @@ -7,6 +7,7 @@ * Add support for Overloaded Record Dot. Introduces `getFieldE :: Quote m => m Exp -> String -> m Exp` and `projectionE :: Quote m => [String] -> m Exp`. + * Add `instance Lift ByteArray`. * Add `PromotedInfixT` and `PromotedUInfixT`, which are analogs to `InfixT` and `UInfixT` that ensure that if a dynamically bound name (i.e. a name |