packages feed

ats-storable 0.2.1.0 → 0.3.0.0

raw patch · 5 files changed

+181/−52 lines, 5 filesdep +ats-storabledep +hspecdep +microlensdep ~basedep ~composition-preludebuild-type:Customsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: ats-storable, hspec, microlens, microlens-th

Dependency ranges changed: base, composition-prelude

API changes (from Hackage documentation)

- Foreign.Storable.ATS: class Indexed a
- Foreign.Storable.ATS: index :: (Indexed a, Data a) => a -> Word8
- Foreign.Storable.ATS: instance (GHC.Generics.Generic a, Foreign.Storable.ATS.Storable' (GHC.Generics.Rep a), Data.Data.Data a) => Foreign.Storable.Storable a
- Foreign.Storable.ATS: instance Foreign.Storable.Storable a => Foreign.Storable.ATS.Indexed a
+ Foreign.Storable.ATS: instance (Foreign.Storable.ATS.Recurse' a, Foreign.Storable.ATS.Recurse' b) => Foreign.Storable.ATS.Recurse' (a GHC.Generics.:*: b)
+ Foreign.Storable.ATS: instance (Foreign.Storable.ATS.Recurse' a, Foreign.Storable.ATS.Recurse' b) => Foreign.Storable.ATS.Recurse' (a GHC.Generics.:+: b)
+ Foreign.Storable.ATS: instance (GHC.Generics.Generic a, Foreign.Storable.ATS.Recurse' (GHC.Generics.Rep a)) => Foreign.Storable.ATS.Recurse a
+ Foreign.Storable.ATS: instance (GHC.Generics.Generic a, Foreign.Storable.ATS.Storable' (GHC.Generics.Rep a), Data.Data.Data a, Foreign.Storable.ATS.Recurse a) => Foreign.Storable.Storable a
+ Foreign.Storable.ATS: instance Foreign.Storable.ATS.Recurse' (GHC.Generics.K1 i a)
+ Foreign.Storable.ATS: instance Foreign.Storable.ATS.Recurse' GHC.Generics.U1
+ Foreign.Storable.ATS: instance Foreign.Storable.ATS.Recurse' GHC.Generics.V1
+ Foreign.Storable.ATS: instance Foreign.Storable.ATS.Recurse' a => Foreign.Storable.ATS.Recurse' (GHC.Generics.M1 i c a)

Files

− README.md
@@ -1,8 +0,0 @@-# ats-storable--Resuscitation of-[generic-storable](hackage.haskell.org/package/generic-storable) altered to-work with ATS' algebraic data types.--For documentation of how to use the ATS side of things, consult the-[documentation](http://ats-lang.sourceforge.net/DOCUMENT/INT2PROGINATS/HTML/x2179.html).
Setup.hs view
@@ -1,2 +1,5 @@-import Distribution.Simple-main = defaultMain+import           Distribution.ATS+import           Distribution.Simple++main = defaultMainWithHooks $+    atsUserHooks [ atsPrelude [0,3,9] ]
ats-storable.cabal view
@@ -1,5 +1,5 @@ name:                ats-storable-version:             0.2.1.0+version:             0.3.0.0 synopsis:            Marshal ATS types into Haskell description:         Facilities for sharing types between ATS and Haskell homepage:            https://github.com//ats-generic#readme@@ -9,8 +9,7 @@ maintainer:          vamchale@gmail.com copyright:           Copyright: (c) 2018 Vanessa McHale category:            ATS, Generics-build-type:          Simple-extra-doc-files:     README.md+build-type:          Custom cabal-version:       1.18  Flag development {@@ -19,19 +18,48 @@   default: False } +Flag with-atsdeps {+  Description: Download ATS dependencies (for running the test suite)+  default: False+}++custom-setup+  setup-depends:   base+                 , ats-setup >= 0.4.0.0+                 , Cabal+ library   hs-source-dirs:      src   exposed-modules:     Foreign.Storable.ATS-  build-depends:       base >= 4.9 && < 5+  build-depends:       base >= 4.10 && < 5                      , composition-prelude                      , text                      , bytestring+                     , microlens+                     , microlens-th   default-language:    Haskell2010   if flag(development)     ghc-options:       -Werror   if impl(ghc >= 8.0)     ghc-options:       -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat    ghc-options:         -Wall++test-suite ats-storable-test+  -- c-sources:           cbits/types.c+  -- include-dirs:        ats-deps/prelude/ATS2-Postiats-include-0.3.9+  --                    , ats-deps/prelude/ATS2-Postiats-include-0.3.9/ccomp/runtime+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       base+                     , ats-storable+                     , hspec+  if flag(development)+    ghc-options: -Werror+  if impl(ghc >= 8.0)+    ghc-options:       -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat +  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall+  default-language:    Haskell2010  source-repository head   type:     darcs
src/Foreign/Storable/ATS.hs view
@@ -13,10 +13,17 @@ {-# LANGUAGE TypeOperators           #-} {-# LANGUAGE UndecidableInstances    #-} +-- | You'll probably want to use this module to simply derive an 'ATSStorable' instance. To do so:+--+-- > {-# LANGUAGE DeriveGeneric      #-}+-- > {-# LANGUAGE DeriveDataTypeable #-}+-- > {-# LANGUAGE DeriveAnyClass     #-}+-- >+-- > data MyType a = MyType a+-- >     deriving (Generic, Data, ATSStorable) module Foreign.Storable.ATS     ( ATSStorable (..)     , AsCString (..)-    , Indexed (..)     ) where  import           Control.Composition@@ -54,21 +61,27 @@ instance AsCString BSL.ByteString where     toCString = flip BS.useAsCString pure . BSL.toStrict +data ATSTypeConfig = ATSTypeConfig { _i         :: Word8 -- ^ Index of the particular constructor+                                   , n          :: Word8 -- ^ Number of constructors for the type+                                   , _recursive :: Bool -- ^ Whether or not the type is self-recursive+                                   , _special   :: Bool -- ^ Flag to be set when the type has exactly one self-recursive type.+                                   }+ class Storable' f where      sizeOf' :: f a -> Int      alignment' :: f a -> Int -    peek' :: Word8 -> Ptr (f a) -> IO (f a)+    peek' :: ATSTypeConfig -> Ptr (f a) -> IO (f a) -    poke' :: Word8 -> Ptr (f a) -> f a -> IO ()+    poke' :: ATSTypeConfig -> Ptr (f a) -> f a -> IO () -    pokeByteOff' :: Ptr (f a) -> Int -> f a -> IO ()-    pokeByteOff' = poke' 0 .* plusPtr+    pokeByteOff' :: ATSTypeConfig -> Ptr (f a) -> Int -> f a -> IO ()+    pokeByteOff' cfg = poke' cfg .* plusPtr -    peekByteOff' :: Ptr (f a) -> Int -> IO (f a)-    peekByteOff' = peek' 0 .* plusPtr+    peekByteOff' :: ATSTypeConfig -> Ptr (f a) -> Int -> IO (f a)+    peekByteOff' cfg = peek' cfg .* plusPtr  instance Storable' U1 where     sizeOf' = pure 0@@ -85,23 +98,27 @@ instance (Storable' a, Storable' b) => Storable' (a :*: b) where     sizeOf' _ = sizeOf' (undefined :: a x) + sizeOf' (undefined :: b x)     alignment' _ = gcd (alignment' (undefined :: a x)) (alignment' (undefined :: b x))-    peek' n ptr = do-        a <- peek' n (castPtr ptr)-        (a :*:) <$> peekByteOff' (castPtr ptr) (sizeOf' a)-    poke' n ptr (a :*: b) = mconcat-        [ poke' n (castPtr ptr) a-        , pokeByteOff' (castPtr ptr) (sizeOf' a) b ]+    peek' cfg ptr = do+        a <- peek' cfg (castPtr ptr)+        (a :*:) <$> peekByteOff' cfg (castPtr ptr) (sizeOf' a)+    poke' cfg ptr (a :*: b) = mconcat+        [ poke' cfg (castPtr ptr) a+        , pokeByteOff' cfg (castPtr ptr) (sizeOf' a) b ] -asIndex :: (Data a) => a -> Int-asIndex x = subtract 1 . length $ takeWhile (/= ix) cs+numConstructors :: (Data a) => a -> Int+numConstructors x = subtract 1 . length $ takeWhile (/= ix) cs     where ix = toConstr x           cs = dataTypeConstrs (dataTypeOf x) -sumHelper :: Storable' f => Word8 -> Ptr a -> f b -> IO ()-sumHelper n ptr val = do-    bptr <- mallocBytes (sizeOf' val)-    poke' n bptr val-    C.poke (castPtr ptr) bptr+sumHelper :: Storable' f => ATSTypeConfig+                         -> Ptr a -- ^ Pointer we want to write our value at+                         -> f b -- ^ Value to be written+                         -> IO ()+sumHelper cfg@(ATSTypeConfig _ _ _ True) ptr val = do+    bytesPtr <- mallocBytes (sizeOf' val)+    poke' cfg bytesPtr val+    C.poke (castPtr ptr) bytesPtr+sumHelper _ _ _ = undefined  ptrSize :: Int ptrSize = C.sizeOf (undefined :: (Ptr Word8))@@ -109,14 +126,24 @@ instance (Storable' a, Storable' b) => Storable' (a :+: b) where     sizeOf' _ = 1 + ptrSize     alignment' _ = 1++    peek' cfg@(ATSTypeConfig _ _ _ True) ptr = do+        i' <- C.peek (castPtr ptr) :: IO Word8+        bool+            (R1 <$> (peek' cfg (castPtr ptr) :: IO (b x)))+            (L1 <$> (peek' cfg (castPtr ptr) :: IO (a x)))+            (i' /= 0)     peek' _ _ = undefined-    poke' n ptr (L1 val) = mconcat-        [ C.poke (castPtr ptr) n-        , sumHelper n ptr val ]-    poke' n ptr (R1 val) = mconcat-        [ C.poke (castPtr ptr) n-        , sumHelper n ptr val ] +    poke' cfg@(ATSTypeConfig _ _ _ True) ptr (L1 val) = mconcat+        [ C.poke (castPtr ptr) (n cfg)+        , sumHelper cfg ptr val ]+    poke' cfg@(ATSTypeConfig _ _ _ True) ptr (R1 val) = mconcat+        [ C.poke (castPtr ptr) (n cfg)+        , sumHelper cfg ptr val ]++    poke' _ _ _ = undefined+ instance (C.Storable a) => Storable' (K1 i a) where     sizeOf' _ = C.sizeOf (undefined :: a)     alignment' _ = C.alignment (undefined :: a)@@ -126,29 +153,76 @@ instance (Storable' a) => Storable' (M1 i c a) where     sizeOf' _ = sizeOf' (undefined :: a x)     alignment' _ = alignment' (undefined :: a x)-    peek' n ptr = pure M1 <*> peek' n (castPtr ptr)-    poke' n ptr (M1 val) = poke' n (castPtr ptr) val+    peek' cfg ptr = pure M1 <*> peek' cfg (castPtr ptr)+    poke' cfg ptr (M1 val) = poke' cfg (castPtr ptr) val -instance C.Storable a => Indexed a where-    index :: a -> Word8-    index = pure 1+index' :: Data a => a -> Word8+index' = fromIntegral . constrIndex . toConstr -class Indexed a where-    index :: a -> Word8-    default index :: Data a => a -> Word8-    index = fromIntegral . asIndex+count' :: Data a => a -> Word8+count' = fromIntegral . numConstructors -instance (Generic a, Storable' (Rep a), Data a) => C.Storable a where+atsCfg' :: (Recurse a, Data a) => a -> ATSTypeConfig+atsCfg' a = ATSTypeConfig (index' a) (count' a) (selfRecursive a) (isSpecial a)++instance (Generic a, Storable' (Rep a), Data a, Recurse a) => C.Storable a where     sizeOf _ = (sizeOf' . from) (undefined :: a)     alignment = C.sizeOf-    poke ptr x = poke' (index x) (castPtr ptr) (from x)-    peek = fmap to . peek' undefined . castPtr+    poke ptr x = poke' (atsCfg' x) (castPtr ptr) (from x)+    peek = fmap to . peek' (atsCfg' (undefined :: a)) . castPtr +class Recurse' f where++    selfRecursive' :: f a -> Bool+    isSpecial' :: f a -> Bool++instance Recurse' V1 where+    selfRecursive' = undefined+    isSpecial' = undefined++instance Recurse' U1 where+    selfRecursive' = pure False+    isSpecial' = pure False++instance (Recurse' a, Recurse' b) => Recurse' (a :+: b) where++    selfRecursive' _ = selfRecursive' (undefined :: a x) || selfRecursive' (undefined :: b x)+    isSpecial' _ = selfRecursive' (undefined :: a x) /= selfRecursive' (undefined :: b x)++instance (Recurse' a, Recurse' b) => Recurse' (a :*: b) where++    selfRecursive' _ = selfRecursive' (undefined :: a x) || selfRecursive' (undefined :: b x)+    isSpecial' _ = selfRecursive' (undefined :: a x) || selfRecursive' (undefined :: b x)++instance Recurse' a => Recurse' (M1 i c a) where++    selfRecursive' (M1 val) = selfRecursive' val+    isSpecial' (M1 val) = isSpecial' val++instance Recurse' (K1 i a) where++    selfRecursive' = pure True+    isSpecial' = pure True++class Recurse a where++    selfRecursive :: a -> Bool++    isSpecial :: a -> Bool++instance (Generic a, Recurse' (Rep a)) => Recurse a where++    selfRecursive = selfRecursive' . from++    isSpecial = isSpecial' . from+ class ATSStorable a where +    -- | Read a value at a pointer.     readPtr :: C.Storable a => Ptr a -> IO a     readPtr = C.peek +    -- Write a value to a pointer.     writePtr :: C.Storable a => a -> IO (Ptr a)     writePtr val = do         ptr <- mallocBytes (C.sizeOf val)
+ test/Spec.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE DeriveAnyClass           #-}+{-# LANGUAGE DeriveDataTypeable       #-}+{-# LANGUAGE DeriveFunctor            #-}+{-# LANGUAGE DeriveGeneric            #-}+{-# LANGUAGE ForeignFunctionInterface #-}++import           Data.Data            (Data)+import           Foreign.C.Types+import           Foreign.Ptr+import           Foreign.Storable.ATS+import           GHC.Generics         (Generic)+import           Test.Hspec++foreign import ccall unsafe something :: Ptr (Option Product)++data Option a = Some a+              | None+              deriving (Show, Eq, Generic, Functor, Data, ATSStorable)++data Pair a b = Pair { _first :: a, _second :: b }+    deriving (Show, Eq, Generic, Data, ATSStorable)++type Product = Pair CInt CInt++somethingVal :: IO (Option Product)+somethingVal = readPtr something++main :: IO ()+main = hspec $+    describe "readPtr" $+        parallel $ it "should work on a combined sum/product type" $+            somethingVal >>= (`shouldBe` (Some (Pair 1 6)))