packages feed

derive-storable (empty) → 0.1.0.0

raw patch · 10 files changed

+1562/−0 lines, 10 filesdep +QuickCheckdep +basedep +generic-storablesetup-changed

Dependencies added: QuickCheck, base, generic-storable, hspec

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2016 Mateusz Kloczko++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ derive-storable.cabal view
@@ -0,0 +1,83 @@+-- Initial derive-storable.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name:                derive-storable++-- The package version.  See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary:      +-+------- breaking API changes+--                   | | +----- non-breaking API additions+--                   | | | +--- code changes with no API change+version:             0.1.0.0++-- A short (one-line) description of the package.+synopsis: Deriving Storable instances using generics.           ++-- A longer description of the package.+-- description:         ++-- The license under which the package is released.+license:             MIT++-- The file containing the license text.+license-file:        LICENSE++-- The package author(s).+author:              Mateusz Kloczko++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer:          mateusz.p.kloczko@gmail.com++-- A copyright notice.+-- copyright:           ++category:            FFI++build-type:          Simple++-- Extra files to be distributed with the package, such as examples or a +-- README.+-- extra-source-files:  ++-- Constraint on the version of Cabal needed to build this package.+cabal-version:       >=1.10+++library+  -- Modules exported by the library.+  exposed-modules:     Foreign.Storable.Generic, Foreign.Storable.Generic.Tools+                     , Foreign.Storable.Generic.Internal, Foreign.Storable.Generic.Instances       +  +  -- LANGUAGE extensions used by modules in this package.+  -- other-extensions:    +  +  -- Other library packages from which modules are imported.+  build-depends:       base >=4.8 && <4.10+  +  -- Directories containing source files.+  hs-source-dirs:      src+  +  -- Base language which the package is written in.+  default-language:    Haskell2010+ ++test-suite c_alignment+  type:                exitcode-stdio-1.0+  +  hs-source-dirs:      src, test/Basic, test/Basic/cbits+  c-sources:           test/Basic/cbits/TestCases.c +  main-is:             MemoryCSpec.hs+  build-depends:       base >= 4.8 && <4.10, hspec == 2.2.* ,QuickCheck == 2.8.*, generic-storable+  +  default-language:    Haskell2010++test-suite spec+  type:                exitcode-stdio-1.0+  hs-source-dirs:      src/ test/Spec test/Basic test/GenericRep/+  Main-is:             Spec.hs+  build-depends:       base >= 4.8 && < 4.10, generic-storable, hspec == 2.2.*, QuickCheck == 2.8.*++  default-language:    Haskell2010
+ src/Foreign/Storable/Generic.hs view
@@ -0,0 +1,42 @@+{-|+Module      : Foreign.Storable.Generic+Copyright   : (c) Mateusz Kłoczko, 2016+License     : MIT+Maintainer  : mateusz.p.kloczko@gmail.com+Stability   : experimental+Portability : portable++++-}++{-#LANGUAGE FlexibleInstances #-}+{-#LANGUAGE FlexibleContexts #-}+{-#LANGUAGE TypeOperators #-}+{-#LANGUAGE ScopedTypeVariables #-}+{-#LANGUAGE UndecidableInstances #-}+++module Foreign.Storable.Generic (GStorable (..), Storable(..)) where++++import Foreign.Storable (Storable(..))++import Foreign.Storable.Generic.Internal (GStorable (..))+import Foreign.Storable.Generic.Instances+++------Association to Storable class-------++instance {-# OVERLAPS #-} (GStorable a) => (Storable a) where+    {-# INLINE sizeOf #-}+    sizeOf      = gsizeOf+    {-# INLINE alignment #-}+    alignment   = galignment+    {-# INLINE peekByteOff #-}+    peekByteOff = gpeekByteOff+    {-# INLINE pokeByteOff #-}+    pokeByteOff = gpokeByteOff++
+ src/Foreign/Storable/Generic/Instances.hs view
@@ -0,0 +1,105 @@+{-|+Module      : Foreign.Storable.Generic.Instances+Copyright   : (c) Mateusz Kłoczko, 2016+License     : MIT+Maintainer  : mateusz.p.kloczko@gmail.com+Stability   : experimental+Portability : portable+++-}++{-# LANGUAGE CPP #-}+module Foreign.Storable.Generic.Instances () where++import Data.Int+import Data.Word+import Foreign.C.Types+import Foreign.Ptr+import Foreign.StablePtr+import Foreign.Storable+import Foreign.Storable.Generic.Internal+import GHC.Fingerprint.Type+import System.Posix.Types+import Data.Ratio (Ratio)++#define MakeGStorable(Type)     \+instance GStorable Type where   \+    {-#INLINE gsizeOf #-}       \+;   gsizeOf      = sizeOf       \+;   {-#INLINE galignment #-}    \+;   galignment   = alignment    \+;   {-#INLINE gpeekByteOff #-}  \+;   gpeekByteOff = peekByteOff  \+;   {-#INLINE gpokeByteOff #-}  \+;   gpokeByteOff = pokeByteOff  \++-- Haskell primitives+MakeGStorable(Bool)+MakeGStorable(Char)+MakeGStorable(Double)+MakeGStorable(Float)++MakeGStorable(Int)+MakeGStorable(Int8)+MakeGStorable(Int16)+MakeGStorable(Int32)+MakeGStorable(Int64)++MakeGStorable(Word)+MakeGStorable(Word8)+MakeGStorable(Word16)+MakeGStorable(Word32)+MakeGStorable(Word64)++MakeGStorable (Fingerprint)++-- C primitives+MakeGStorable (CUIntMax)+MakeGStorable (CIntMax)+MakeGStorable (CSUSeconds)+MakeGStorable (CUSeconds)+MakeGStorable (CTime)+MakeGStorable (CClock)+MakeGStorable (CSigAtomic)+MakeGStorable (CPtrdiff)+MakeGStorable (CDouble)+MakeGStorable (CFloat)+MakeGStorable (CULLong)+MakeGStorable (CLLong)+MakeGStorable (CULong)+MakeGStorable (CLong)+MakeGStorable (CUInt)+MakeGStorable (CInt)+MakeGStorable (CUShort)+MakeGStorable (CShort)+MakeGStorable (CUChar)+MakeGStorable (CSChar)+MakeGStorable (CChar)++-- Ptr+MakeGStorable (IntPtr)+MakeGStorable (WordPtr)++MakeGStorable ((StablePtr a))+MakeGStorable ((Ptr a)) +MakeGStorable ((FunPtr a))++-- Posix+MakeGStorable (Fd)+MakeGStorable (CRLim)+MakeGStorable (CTcflag)+MakeGStorable (CSpeed)+MakeGStorable (CCc)+MakeGStorable (CUid)+MakeGStorable (CNlink)+MakeGStorable (CGid)+MakeGStorable (CSsize)+MakeGStorable (CPid)+MakeGStorable (COff)+MakeGStorable (CMode)+MakeGStorable (CIno)+MakeGStorable (CDev)+ ++
+ src/Foreign/Storable/Generic/Internal.hs view
@@ -0,0 +1,219 @@+{-|+Module      : Foreign.Storable.Generic.Internal+Copyright   : (c) Mateusz Kłoczko, 2016+License     : MIT+Maintainer  : mateusz.p.kloczko@gmail.com+Stability   : experimental+Portability : portable+++-}++{-#LANGUAGE FlexibleInstances #-}+{-#LANGUAGE FlexibleContexts #-}+{-#LANGUAGE DefaultSignatures #-}+{-#LANGUAGE TypeOperators #-}+{-#LANGUAGE ScopedTypeVariables #-}+{-#LANGUAGE UndecidableInstances #-}++module Foreign.Storable.Generic.Internal (+     GStorable'(..),+     GStorable (..),+     internalSizeOf,+     internalAlignment,+     internalPeekByteOff,+     internalPokeByteOff,+     internalOffsets+  ) where++import GHC.Generics+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal.Alloc+import Foreign.C.Types++import Data.Int++import Debug.Trace++import Foreign.Storable.Generic.Tools++import GHC.Exts++-- Defining the generics ---++class GStorable' f where+    -- | Read the element at a given offset. Additional information about the offests +    -- of the subfields are needed.+    gpeekByteOff' :: [Int]    -- ^ List of fields' offsets for the type/struct. +                  -> Int      -- ^ The index. Used to obtain the correct offset+                  -> Ptr b    -- ^ The pointer to the type/struct.+                  -> Int      -- ^ Global offset.+                  -> IO (f a) -- ^ The result, wrapped in GHC.Generic metadata.+    -- | Write the element at a given offset. Additional information about the offests +    -- of the subfields are needed.+    gpokeByteOff' :: [Int]  -- ^ List of fields' offsets for the type/struct.+                  -> Int    -- ^ The index. Used to obtain the correct offset.+                  -> Ptr b  -- ^ The pointer to the type/struct.+                  -> Int    -- ^ Global offset.+                  -> (f a)  -- ^ The element to write, wrapped in GHC.Generic metadata.+                  -> IO ()++    -- | Calculates the number of type's/struct's fields.+    gnumberOf' :: f a -- ^ GHC.Generic information about a given type/struct.+               -> Int -- ^ Size.++    -- | Calculates the sizes of type's/struct's fields.+    glistSizeOf' :: f a    -- ^ GHC.Generic information about a given type/struct. +                 -> [Size] -- ^ List of sizes.++    -- | Calculates the alignments of type's/struct's fields.+    glistAlignment' :: f a         -- ^ GHC.Generic information about a given type/struct.+                    -> [Alignment] -- ^ List of alignments.+++instance (GStorable' f) => GStorable' (M1 i t f) where+    -- Wrap the peeked value in metadata.+    {-# INLINE gpeekByteOff' #-}+    gpeekByteOff' offsets ix ptr offset = M1 <$> gpeekByteOff' offsets ix ptr offset+    -- Discard the metadata and go further.+    {-# INLINE gpokeByteOff' #-}+    gpokeByteOff' offsets ix ptr offset (M1 x) = gpokeByteOff' offsets ix ptr offset x +    ++    gnumberOf' (M1 v) = gnumberOf' v+    glistSizeOf' _ = glistSizeOf' (undefined :: f p)+    glistAlignment' _ = glistAlignment' (undefined :: f p)++instance (GStorable' f, GStorable' g) => GStorable' (f :*: g) where+    -- Tree-like traversal for reading the type.+    {-# INLINE gpeekByteOff' #-}+    gpeekByteOff' offsets ix ptr offset = (:*:) <$> peeker new_ix <*>  peeker ix+        where new_ix =  ix - n2                                        -- The new index for the left part of the tree.+              n2 = gnumberOf' (undefined :: g a)                       -- Number of elements for the right part of the tree+              peeker n_ix = gpeekByteOff' offsets n_ix ptr offset      -- gpeekByteOff' wrapped to peek into subtrees.+    -- Tree like traversal for writing the type.+    {-# INLINE gpokeByteOff' #-}+    gpokeByteOff' offsets ix ptr offset (x :*: y) = peeker new_ix x >> peeker ix y+        where new_ix = ix - n2                                 +              n2 = gnumberOf' (undefined :: g a)               -- Number of elements for the right part of the tree.+              peeker n_ix z = gpokeByteOff' offsets n_ix ptr offset z  -- gpokeByteOff' wrapped to peek into the subtree+++++    gnumberOf' _ = gnumberOf' (undefined :: f a) + gnumberOf' (undefined :: g a)+    -- Concatenate the lists. +    glistSizeOf' _ = glistSizeOf' (undefined :: f a) ++ glistSizeOf' (undefined :: g a)+    -- Concatenate the lists.+    glistAlignment' _ = glistAlignment' (undefined :: f a) ++ glistAlignment' (undefined :: g a)++instance (GStorable a) => GStorable' (K1 i a) where+    {-# INLINE gpeekByteOff' #-}+    gpeekByteOff' offsets ix ptr offset = K1 <$> gpeekByteOff ptr (off1 + offset)+        where off1 = inline (offsets !! ix)+    {-# INLINE gpokeByteOff' #-}+    gpokeByteOff' offsets ix ptr offset (K1 x) = gpokeByteOff ptr (off1 + offset) x+        where off1 = inline (offsets !! ix) +++    -- When we use the contructor, just return one.+    gnumberOf' _ = 1+    -- When the constructor is used, return the size of +    -- the constructed type in a list.+    glistSizeOf' _ = [gsizeOf (undefined :: a)]+    -- When the constructor is used, return the alignment of +    -- the constructed type in a list.+    glistAlignment' _ = [galignment (undefined :: a)]  +++-- These functions were moved outside GStorable type class.+-- They take generic representations as input.++{-# INLINE internalSizeOf #-}+-- | Calculates the size of generic data-type.+internalSizeOf :: forall f p. (GStorable' f)+               => f p  -- ^ Generic representation +               -> Int  -- ^ Resulting size+internalSizeOf _  = calcSize $ zip sizes aligns+    where sizes  = glistSizeOf'    (undefined :: f p)+          aligns = glistAlignment' (undefined :: f p)++{-# INLINE internalAlignment #-}+-- | Calculates the alignment of generic data-type.+internalAlignment :: forall f p. (GStorable' f) +                  => f p       -- ^ Generic representation+                  -> Alignment -- ^ Resulting alignment+internalAlignment  _  = calcAlignment aligns+    where aligns = glistAlignment' (undefined :: f p)++{-# INLINE internalPeekByteOff #-}+-- | View the variable under a pointer, with offset.+internalPeekByteOff :: forall f p b. (GStorable' f) +                    => Ptr b    -- ^ Pointer to peek +                    -> Offset   -- ^ Offset +                    -> IO (f p) -- ^ Resulting generic representation+internalPeekByteOff ptr off  = gpeekByteOff' offsets ix ptr off+    where offsets = internalOffsets (undefined :: f p)+          ix      = gnumberOf' (undefined :: f p) - 1++{-# INLINE internalPokeByteOff #-}+-- | Write the variable under the pointer, with offset.+internalPokeByteOff :: forall f p b. (GStorable' f) +                    => Ptr b  -- ^ Pointer to write to+                    -> Offset -- ^ Offset +                    -> f p    -- ^ Written generic representation +                    -> IO () +internalPokeByteOff ptr off rep = gpokeByteOff' offsets ix ptr off rep+    where offsets = internalOffsets (undefined :: f p)+          ix      = gnumberOf' (undefined :: f p) - 1++{-# INLINE internalOffsets #-}+-- | Obtain the list of offsets+internalOffsets :: forall f p. (GStorable' f)+                => f p      -- Generic representation+                -> [Offset] -- List of offsets+internalOffsets _ = calcOffsets $ zip sizes aligns+    where sizes = glistSizeOf'    (undefined :: f p)+          aligns= glistAlignment' (undefined :: f p)++-- | The class uses the default Generic based implementations to +-- provide Storable instances for types made from primitive types.+-- Does not work on Algebraic Data Types with more than one constructor.+class GStorable a where+    -- | Calculate the size of the type.+    {-# INLINE gsizeOf #-}+    gsizeOf :: a   -- ^ Element of a given type. Can be undefined.+            -> Int -- ^ Size.+    default gsizeOf :: (Generic a, GStorable' (Rep a))+                    => a -> Int+    gsizeOf _ = internalSizeOf (undefined :: Rep a p) +    +    -- | Calculate the alignment of the type.+    {-# INLINE galignment #-}+    galignment :: a   -- ^ Element of a given type. Can be undefined  +               -> Int -- ^ Alignment.+    default galignment :: (Generic a, GStorable' (Rep a))+                         => a -> Int+    galignment _ = internalAlignment (undefined :: Rep a p) ++    -- | Read the variable from a given pointer.+    gpeekByteOff :: Ptr b -- ^ Pointer to the variable+                 -> Int   -- ^ Offset+                 -> IO a  -- ^ Returned variable.+    default gpeekByteOff :: (Generic a, GStorable' (Rep a))+                         => Ptr b -> Int -> IO a+    {-# INLINE gpeekByteOff #-}+    gpeekByteOff ptr offset = to <$> internalPeekByteOff ptr offset++    -- | Write the variable to a pointer. +    gpokeByteOff :: Ptr b -- ^ Pointer to the variable. +                 -> Int   -- ^ Offset.+                 -> a     -- ^ The variable+                 -> IO ()+    default gpokeByteOff :: (Generic a, GStorable' (Rep a))+                         => Ptr b -> Int -> a -> IO ()+    {-# INLINE gpokeByteOff #-}+    gpokeByteOff ptr offset x = internalPokeByteOff ptr offset (from x)++
+ src/Foreign/Storable/Generic/Tools.hs view
@@ -0,0 +1,106 @@+{-|+Module      : Foreign.Storable.Generic.Tools+Copyright   : (c) Mateusz Kłoczko, 2016+License     : MIT+Maintainer  : mateusz.p.kloczko@gmail.com+Stability   : experimental+Portability : portable+++-}+++{-#LANGUAGE FlexibleInstances #-}+{-#LANGUAGE FlexibleContexts #-}+{-#LANGUAGE TypeOperators #-}+{-#LANGUAGE ScopedTypeVariables #-}+{-#LANGUAGE UndecidableInstances #-}++module Foreign.Storable.Generic.Tools (+    Size,+    Alignment,+    Offset,+    Filling(..),+    calcOffsets,+    calcSize,+    calcAlignment,+    getFilling+) where++import Data.List+++-- | The datatype representing the memory layout of a given struct.+data Filling = Size Int | Padding Int deriving(Show, Eq)++-- | Checks whether the size or padding are zero.+not_zero :: Filling -> Bool+not_zero (Size    0) = False+not_zero (Padding 0) = False+not_zero _           = True+++type Size      = Int+type Alignment = Int+type Offset    = Int++++-- | Get the memory layout of a given type/struct. Used mostly as debug information.+getFilling :: [(Size,Alignment)] -- ^ List of sizes and aligments of the type's/struct's fields. [(Int,Int)]+           -> [Filling]          -- ^ List representing the memory layout. [Filling]+getFilling size_align = reverse $ filter not_zero $ getFilling' (ordered ++ [(gl_size,0)]) 0 0 []+    where offsets = calcOffsets size_align  :: [Offset]+          sizes   = map fst size_align      :: [Size]+          ordered = sortBy (\(o1,_) (o2,_) -> compare o1 o2) $ -- Needs to be sorted in case the fields are rearranged. +                        zip offsets sizes   :: [(Offset,Size)] +          gl_size  = calcSize size_align    :: Offset   -- This variable is used as offset++getFilling' :: [(Offset, Size)] -- ^ List of struct's fields' offsets and sizes  +            -> Size             -- ^ Size of the previous element+            -> Offset           -- ^ Offest of the previous element+            -> [Filling]        -- ^ Accumulator: List of filling+            -> [Filling]        -- ^ Returned list of fillings.+getFilling' []           _ _ acc = acc+getFilling' ((o2,s2):rest) s1 o1 acc = getFilling' rest s2 o2 (Size s2 : Padding ((o2-o1) - s1) : acc )++{-# NOINLINE calcOffsets #-}+-- | Calculates the memory offset of type's/struct's fields.+calcOffsets :: [(Size, Alignment)]  -- ^ List of sizes and aligments of the type's/struct's fields. [(Int,Int)]+            -> [Offset]             -- ^ List representing the offests of the type's/struct's fields. [Int]+calcOffsets []         = []+calcOffsets size_align = reverse $ fst $ calcOffsets' size_align 0 []++++{-# NOINLINE calcOffsets' #-}+calcOffsets' :: [(Size, Alignment)] -- ^ List of struct's fields' sizes and alignments+             -> Int                 -- ^ The intermediate variable between the current and previous iteration.+             -> [Offset]            -- ^ Accumulator+             -> ([Offset], Int)     -- ^ List of offsets and the last intermediate value.+calcOffsets' []           inter acc = (acc, inter)  +calcOffsets' ((s,a):rest) inter acc = calcOffsets' rest (last_off + s) (last_off: acc)+    where p = (a - inter) `mod` a -- Padding+          last_off = inter + p    :: Offset+++{-# NOINLINE calcSize #-}+-- | Calculates the size of the type/struct.+calcSize :: [(Size, Alignment)] -- ^ List of sizes and aligments of the type's/struct's fields. [(Int,Int)].+         -> Size                -- ^ The returned size. Int+calcSize size_align = inter + ((glob_align - inter) `mod` glob_align)+    where glob_align = calcAlignment $ map snd size_align+          inter      = snd $ calcOffsets' size_align 0 []++{-# NOINLINE calcAlignment #-}+-- | Calculate the alignment of a struct.+calcAlignment :: [Alignment] -- ^ List of struct's fields' alignments.+              -> Alignment   -- ^ The resulting alignment.+calcAlignment aligns = calcAlignment' aligns 1+++calcAlignment' :: [Alignment] -- ^ List of alignments+               -> Alignment   -- ^ Accumulator+               -> Alignment   -- ^ The resulting alignment.+calcAlignment' []          glob = glob+calcAlignment' (al:aligns) glob = calcAlignment' aligns (max glob al)
+ test/Basic/MemoryCSpec.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts#-}+module Main where+++-- Tested module.+import TestCases++-- Test libraries+import Test.Hspec+import Test.QuickCheck++-- Helpers+import Foreign.Marshal.Array+import Foreign.Storable+++same_alignment a = getAlignment a `shouldReturn` alignment a+same_size a = getSize a `shouldReturn` sizeOf a+same_offsets a = do+    let offsets = goffsets a+    ptr <- mallocArray $ length offsets+    pokeArray ptr offsets+    checkOffsets a ptr `shouldReturn` True++same_fields a = do+    ptr1 <- newStorable a+    ptr2 <- new a+    checkFields ptr1 ptr2 `shouldReturn` True+main = hspec $ do+    describe "Test for same size" $ do+        it "C1" $ property $ (same_size      :: C1 -> Expectation)+        it "C2" $ property $ (same_size      :: C2 -> Expectation)+        it "C3" $ property $ (same_size      :: C3 -> Expectation)+        it "C4" $ property $ (same_size      :: C4 -> Expectation)+        it "C5" $ property $ (same_size      :: C5 -> Expectation)+        it "C6" $ property $ (same_size      :: C6 -> Expectation)+        it "C7" $ property $ (same_size      :: C7 -> Expectation)+        it "C8" $ property $ (same_size      :: C8 -> Expectation)+        it "C9" $ property $ (same_size      :: C9 -> Expectation)+        it "C10" $ property $ (same_size      :: C10 -> Expectation)+        it "C11" $ property $ (same_size      :: C11 -> Expectation)+        it "C12" $ property $ (same_size      :: C12 -> Expectation)+        it "C13" $ property $ (same_size      :: C13 -> Expectation)+        it "C14" $ property $ (same_size      :: C14 -> Expectation)+        it "C15" $ property $ (same_size      :: C15 -> Expectation)+        it "C16" $ property $ (same_size      :: C16 -> Expectation)+        it "C17" $ property $ (same_size      :: C17 -> Expectation)+        it "C18" $ property $ (same_size      :: C18 -> Expectation)+        it "C19" $ property $ (same_size      :: C19 -> Expectation)+        it "C20" $ property $ (same_size      :: C20 -> Expectation)+    describe "Test for same alignment" $ do+        it "C1" $ property $ (same_alignment :: C1 -> Expectation)+        it "C2" $ property $ (same_alignment :: C2 -> Expectation)+        it "C3" $ property $ (same_alignment :: C3 -> Expectation)+        it "C4" $ property $ (same_alignment :: C4 -> Expectation)+        it "C5" $ property $ (same_alignment :: C5 -> Expectation)+        it "C6" $ property $ (same_alignment :: C6 -> Expectation)+        it "C7" $ property $ (same_alignment :: C7 -> Expectation)+        it "C8" $ property $ (same_alignment :: C8 -> Expectation)+        it "C9" $ property $ (same_alignment :: C9 -> Expectation)+        it "C10" $ property $ (same_alignment :: C10 -> Expectation)+        it "C11" $ property $ (same_alignment :: C11 -> Expectation)+        it "C12" $ property $ (same_alignment :: C12 -> Expectation)+        it "C13" $ property $ (same_alignment :: C13 -> Expectation)+        it "C14" $ property $ (same_alignment :: C14 -> Expectation)+        it "C15" $ property $ (same_alignment :: C15 -> Expectation)+        it "C16" $ property $ (same_alignment :: C16 -> Expectation)+        it "C17" $ property $ (same_alignment :: C17 -> Expectation)+        it "C18" $ property $ (same_alignment :: C18 -> Expectation)+        it "C19" $ property $ (same_alignment :: C19 -> Expectation)+        it "C20" $ property $ (same_alignment :: C20 -> Expectation)+    describe "Test for same offsets" $ do+        it "C1" $ property $ (same_offsets   :: C1 -> Expectation)+        it "C2" $ property $ (same_offsets   :: C2 -> Expectation)+        it "C3" $ property $ (same_offsets   :: C3 -> Expectation)+        it "C4" $ property $ (same_offsets   :: C4 -> Expectation)+        it "C5" $ property $ (same_offsets   :: C5 -> Expectation)+        it "C6" $ property $ (same_offsets   :: C6 -> Expectation)+        it "C7" $ property $ (same_offsets   :: C7 -> Expectation)+        it "C8" $ property $ (same_offsets   :: C8 -> Expectation)+        it "C9" $ property $ (same_offsets   :: C9 -> Expectation)+        it "C10" $ property $ (same_offsets   :: C10 -> Expectation)+        it "C11" $ property $ (same_offsets   :: C11 -> Expectation)+        it "C12" $ property $ (same_offsets   :: C12 -> Expectation)+        it "C13" $ property $ (same_offsets   :: C13 -> Expectation)+        it "C14" $ property $ (same_offsets   :: C14 -> Expectation)+        it "C15" $ property $ (same_offsets   :: C15 -> Expectation)+        it "C16" $ property $ (same_offsets   :: C16 -> Expectation)+        it "C17" $ property $ (same_offsets   :: C17 -> Expectation)+        it "C18" $ property $ (same_offsets   :: C18 -> Expectation)+        it "C19" $ property $ (same_offsets   :: C19 -> Expectation)+        it "C20" $ property $ (same_offsets   :: C20 -> Expectation)+    describe "Test for same fields" $ do+        it "C1" $ property $ (same_fields    :: C1 -> Expectation)+        it "C2" $ property $ (same_fields    :: C2 -> Expectation)+        it "C3" $ property $ (same_fields    :: C3 -> Expectation)+        it "C4" $ property $ (same_fields    :: C4 -> Expectation)+        it "C5" $ property $ (same_fields    :: C5 -> Expectation)+        it "C6" $ property $ (same_fields    :: C6 -> Expectation)+        it "C7" $ property $ (same_fields    :: C7 -> Expectation)+        it "C8" $ property $ (same_fields    :: C8 -> Expectation)+        it "C9" $ property $ (same_fields    :: C9 -> Expectation)+        it "C10" $ property $ (same_fields    :: C10 -> Expectation)+        it "C11" $ property $ (same_fields    :: C11 -> Expectation)+        it "C12" $ property $ (same_fields    :: C12 -> Expectation)+        it "C13" $ property $ (same_fields    :: C13 -> Expectation)+        it "C14" $ property $ (same_fields    :: C14 -> Expectation)+        it "C15" $ property $ (same_fields    :: C15 -> Expectation)+        it "C16" $ property $ (same_fields    :: C16 -> Expectation)+        it "C17" $ property $ (same_fields    :: C17 -> Expectation)+        it "C18" $ property $ (same_fields    :: C18 -> Expectation)+        it "C19" $ property $ (same_fields    :: C19 -> Expectation)+        it "C20" $ property $ (same_fields    :: C20 -> Expectation)
+ test/Basic/cbits/TestCases.c view
@@ -0,0 +1,870 @@+#include <stddef.h>+#include <stdio.h>+#include <stdalign.h>+#include <stdlib.h>+#include "HsFFI.h"+typedef struct C1{+    HsInt32 a;+    HsInt32 b;+} C1;++C1 * newC1(HsInt32 a, HsInt32 b){+    C1 * ret = (C1*) malloc(sizeof(C1));+    ret->a = a;+    ret->b = b;+    return ret;+}++void pokeC1(C1* val, HsInt32 a, HsInt32 b){+    val->a = a;+    val->b = b;+}++int checkOffsetsC1(HsInt16 *offs){+    int a = offsetof(C1, a) == offs[0];+    int b = offsetof(C1, b) == offs[1];+    return a && b;+}++int checkFieldsC1(C1* s1, C1* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    return a && b;+}++HsInt16 getSizeC1() {+    return sizeof(C1);+}++HsInt16 getAlignmentC1() {+    return alignof(C1);+}++typedef struct C2{+    HsInt32 a;+    HsInt16 b;+    HsInt8 c;+} C2;++C2 * newC2(HsInt32 a, HsInt16 b, HsInt8 c){+    C2 * ret = (C2*) malloc(sizeof(C2));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC2(C2* val, HsInt32 a, HsInt16 b, HsInt8 c){+    val->a = a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC2(HsInt16 *offs){+    int a = offsetof(C2, a) == offs[0];+    int b = offsetof(C2, b) == offs[1];+    int c = offsetof(C2, c) == offs[2];+    return a && b && c;+}++int checkFieldsC2(C2* s1, C2* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC2() {+    return sizeof(C2);+}++HsInt16 getAlignmentC2() {+    return alignof(C2);+}++typedef struct C3{+    HsInt32 a;+    HsInt8 b;+    HsInt16 c;+} C3;++C3 * newC3(HsInt32 a, HsInt8 b, HsInt16 c){+    C3 * ret = (C3*) malloc(sizeof(C3));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC3(C3* val, HsInt32 a, HsInt8 b, HsInt16 c){+    val->a = a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC3(HsInt16 *offs){+    int a = offsetof(C3, a) == offs[0];+    int b = offsetof(C3, b) == offs[1];+    int c = offsetof(C3, c) == offs[2];+    return a && b && c;+}++int checkFieldsC3(C3* s1, C3* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC3() {+    return sizeof(C3);+}++HsInt16 getAlignmentC3() {+    return alignof(C3);+}++typedef struct C4{+    HsInt32 a;+    HsInt8 b;+    HsInt8 c;+} C4;++C4 * newC4(HsInt32 a, HsInt8 b, HsInt8 c){+    C4 * ret = (C4*) malloc(sizeof(C4));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC4(C4* val, HsInt32 a, HsInt8 b, HsInt8 c){+    val->a = a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC4(HsInt16 *offs){+    int a = offsetof(C4, a) == offs[0];+    int b = offsetof(C4, b) == offs[1];+    int c = offsetof(C4, c) == offs[2];+    return a && b && c;+}++int checkFieldsC4(C4* s1, C4* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC4() {+    return sizeof(C4);+}++HsInt16 getAlignmentC4() {+    return alignof(C4);+}++typedef struct C5{+    HsInt32 a;+    HsInt16 b;+    HsInt8 c;+    HsInt8 d;+    HsInt8 e;+} C5;++C5 * newC5(HsInt32 a, HsInt16 b, HsInt8 c, HsInt8 d, HsInt8 e){+    C5 * ret = (C5*) malloc(sizeof(C5));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    ret->d = d;+    ret->e = e;+    return ret;+}++void pokeC5(C5* val, HsInt32 a, HsInt16 b, HsInt8 c, HsInt8 d, HsInt8 e){+    val->a = a;+    val->b = b;+    val->c = c;+    val->d = d;+    val->e = e;+}++int checkOffsetsC5(HsInt16 *offs){+    int a = offsetof(C5, a) == offs[0];+    int b = offsetof(C5, b) == offs[1];+    int c = offsetof(C5, c) == offs[2];+    int d = offsetof(C5, d) == offs[3];+    int e = offsetof(C5, e) == offs[4];+    return a && b && c && d && e;+}++int checkFieldsC5(C5* s1, C5* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    int d = s1->d == s2->d;+    int e = s1->e == s2->e;+    return a && b && c && d && e;+}++HsInt16 getSizeC5() {+    return sizeof(C5);+}++HsInt16 getAlignmentC5() {+    return alignof(C5);+}++typedef struct C6{+    HsInt64 a;+    HsInt8 b;+    HsInt64 c;+} C6;++C6 * newC6(HsInt64 a, HsInt8 b, HsInt64 c){+    C6 * ret = (C6*) malloc(sizeof(C6));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC6(C6* val, HsInt64 a, HsInt8 b, HsInt64 c){+    val->a = a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC6(HsInt16 *offs){+    int a = offsetof(C6, a) == offs[0];+    int b = offsetof(C6, b) == offs[1];+    int c = offsetof(C6, c) == offs[2];+    return a && b && c;+}++int checkFieldsC6(C6* s1, C6* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC6() {+    return sizeof(C6);+}++HsInt16 getAlignmentC6() {+    return alignof(C6);+}++typedef struct C7{+    C1 a;+    HsInt32 b;+} C7;++C7 * newC7(C1* a, HsInt32 b){+    C7 * ret = (C7*) malloc(sizeof(C7));+    ret->a = *a;+    ret->b = b;+    return ret;+}++void pokeC7(C7* val, C1* a, HsInt32 b){+    val->a = *a;+    val->b = b;+}++int checkOffsetsC7(HsInt16 *offs){+    int a = offsetof(C7, a) == offs[0];+    int b = offsetof(C7, b) == offs[1];+    return a && b;+}++int checkFieldsC7(C7* s1, C7* s2){+    int a = checkFieldsC1(&(s1->a),&(s2->a));+    int b = s1->b == s2->b;+    return a && b;+}++HsInt16 getSizeC7() {+    return sizeof(C7);+}++HsInt16 getAlignmentC7() {+    return alignof(C7);+}++typedef struct C8{+    C2 a;+    HsInt8 b;+    C4 c;+} C8;++C8 * newC8(C2* a, HsInt8 b, C4* c){+    C8 * ret = (C8*) malloc(sizeof(C8));+    ret->a = *a;+    ret->b = b;+    ret->c = *c;+    return ret;+}++void pokeC8(C8* val, C2* a, HsInt8 b, C4* c){+    val->a = *a;+    val->b = b;+    val->c = *c;+}++int checkOffsetsC8(HsInt16 *offs){+    int a = offsetof(C8, a) == offs[0];+    int b = offsetof(C8, b) == offs[1];+    int c = offsetof(C8, c) == offs[2];+    return a && b && c;+}++int checkFieldsC8(C8* s1, C8* s2){+    int a = checkFieldsC2(&(s1->a),&(s2->a));+    int b = s1->b == s2->b;+    int c = checkFieldsC4(&(s1->c),&(s2->c));+    return a && b && c;+}++HsInt16 getSizeC8() {+    return sizeof(C8);+}++HsInt16 getAlignmentC8() {+    return alignof(C8);+}++typedef struct C9{+    C5 a;+    HsInt8 b;+    HsInt8 c;+    HsInt8 d;+} C9;++C9 * newC9(C5* a, HsInt8 b, HsInt8 c, HsInt8 d){+    C9 * ret = (C9*) malloc(sizeof(C9));+    ret->a = *a;+    ret->b = b;+    ret->c = c;+    ret->d = d;+    return ret;+}++void pokeC9(C9* val, C5* a, HsInt8 b, HsInt8 c, HsInt8 d){+    val->a = *a;+    val->b = b;+    val->c = c;+    val->d = d;+}++int checkOffsetsC9(HsInt16 *offs){+    int a = offsetof(C9, a) == offs[0];+    int b = offsetof(C9, b) == offs[1];+    int c = offsetof(C9, c) == offs[2];+    int d = offsetof(C9, d) == offs[3];+    return a && b && c && d;+}++int checkFieldsC9(C9* s1, C9* s2){+    int a = checkFieldsC5(&(s1->a),&(s2->a));+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    int d = s1->d == s2->d;+    return a && b && c && d;+}++HsInt16 getSizeC9() {+    return sizeof(C9);+}++HsInt16 getAlignmentC9() {+    return alignof(C9);+}++typedef struct C10{+    C8 a;+    HsInt64 b;+    C1 c;+} C10;++C10 * newC10(C8* a, HsInt64 b, C1* c){+    C10 * ret = (C10*) malloc(sizeof(C10));+    ret->a = *a;+    ret->b = b;+    ret->c = *c;+    return ret;+}++void pokeC10(C10* val, C8* a, HsInt64 b, C1* c){+    val->a = *a;+    val->b = b;+    val->c = *c;+}++int checkOffsetsC10(HsInt16 *offs){+    int a = offsetof(C10, a) == offs[0];+    int b = offsetof(C10, b) == offs[1];+    int c = offsetof(C10, c) == offs[2];+    return a && b && c;+}++int checkFieldsC10(C10* s1, C10* s2){+    int a = checkFieldsC8(&(s1->a),&(s2->a));+    int b = s1->b == s2->b;+    int c = checkFieldsC1(&(s1->c),&(s2->c));+    return a && b && c;+}++HsInt16 getSizeC10() {+    return sizeof(C10);+}++HsInt16 getAlignmentC10() {+    return alignof(C10);+}++typedef struct C11{+    C10 a;+    C10 b;+} C11;++C11 * newC11(C10* a, C10* b){+    C11 * ret = (C11*) malloc(sizeof(C11));+    ret->a = *a;+    ret->b = *b;+    return ret;+}++void pokeC11(C11* val, C10* a, C10* b){+    val->a = *a;+    val->b = *b;+}++int checkOffsetsC11(HsInt16 *offs){+    int a = offsetof(C11, a) == offs[0];+    int b = offsetof(C11, b) == offs[1];+    return a && b;+}++int checkFieldsC11(C11* s1, C11* s2){+    int a = checkFieldsC10(&(s1->a),&(s2->a));+    int b = checkFieldsC10(&(s1->b),&(s2->b));+    return a && b;+}++HsInt16 getSizeC11() {+    return sizeof(C11);+}++HsInt16 getAlignmentC11() {+    return alignof(C11);+}++typedef struct C12{+    HsInt64 a;+    HsInt64 b;+    HsInt64 c;+    HsInt64 d;+} C12;++C12 * newC12(HsInt64 a, HsInt64 b, HsInt64 c, HsInt64 d){+    C12 * ret = (C12*) malloc(sizeof(C12));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    ret->d = d;+    return ret;+}++void pokeC12(C12* val, HsInt64 a, HsInt64 b, HsInt64 c, HsInt64 d){+    val->a = a;+    val->b = b;+    val->c = c;+    val->d = d;+}++int checkOffsetsC12(HsInt16 *offs){+    int a = offsetof(C12, a) == offs[0];+    int b = offsetof(C12, b) == offs[1];+    int c = offsetof(C12, c) == offs[2];+    int d = offsetof(C12, d) == offs[3];+    return a && b && c && d;+}++int checkFieldsC12(C12* s1, C12* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    int d = s1->d == s2->d;+    return a && b && c && d;+}++HsInt16 getSizeC12() {+    return sizeof(C12);+}++HsInt16 getAlignmentC12() {+    return alignof(C12);+}++typedef struct C13{+    C12 a;+    C12 b;+    C12 c;+    C12 d;+} C13;++C13 * newC13(C12* a, C12* b, C12* c, C12* d){+    C13 * ret = (C13*) malloc(sizeof(C13));+    ret->a = *a;+    ret->b = *b;+    ret->c = *c;+    ret->d = *d;+    return ret;+}++void pokeC13(C13* val, C12* a, C12* b, C12* c, C12* d){+    val->a = *a;+    val->b = *b;+    val->c = *c;+    val->d = *d;+}++int checkOffsetsC13(HsInt16 *offs){+    int a = offsetof(C13, a) == offs[0];+    int b = offsetof(C13, b) == offs[1];+    int c = offsetof(C13, c) == offs[2];+    int d = offsetof(C13, d) == offs[3];+    return a && b && c && d;+}++int checkFieldsC13(C13* s1, C13* s2){+    int a = checkFieldsC12(&(s1->a),&(s2->a));+    int b = checkFieldsC12(&(s1->b),&(s2->b));+    int c = checkFieldsC12(&(s1->c),&(s2->c));+    int d = checkFieldsC12(&(s1->d),&(s2->d));+    return a && b && c && d;+}++HsInt16 getSizeC13() {+    return sizeof(C13);+}++HsInt16 getAlignmentC13() {+    return alignof(C13);+}++typedef struct C14{+    C13 a;+    C13 b;+    C13 c;+    C13 d;+    HsInt8 e;+} C14;++C14 * newC14(C13* a, C13* b, C13* c, C13* d, HsInt8 e){+    C14 * ret = (C14*) malloc(sizeof(C14));+    ret->a = *a;+    ret->b = *b;+    ret->c = *c;+    ret->d = *d;+    ret->e = e;+    return ret;+}++void pokeC14(C14* val, C13* a, C13* b, C13* c, C13* d, HsInt8 e){+    val->a = *a;+    val->b = *b;+    val->c = *c;+    val->d = *d;+    val->e = e;+}++int checkOffsetsC14(HsInt16 *offs){+    int a = offsetof(C14, a) == offs[0];+    int b = offsetof(C14, b) == offs[1];+    int c = offsetof(C14, c) == offs[2];+    int d = offsetof(C14, d) == offs[3];+    int e = offsetof(C14, e) == offs[4];+    return a && b && c && d && e;+}++int checkFieldsC14(C14* s1, C14* s2){+    int a = checkFieldsC13(&(s1->a),&(s2->a));+    int b = checkFieldsC13(&(s1->b),&(s2->b));+    int c = checkFieldsC13(&(s1->c),&(s2->c));+    int d = checkFieldsC13(&(s1->d),&(s2->d));+    int e = s1->e == s2->e;+    return a && b && c && d && e;+}++HsInt16 getSizeC14() {+    return sizeof(C14);+}++HsInt16 getAlignmentC14() {+    return alignof(C14);+}++typedef struct C15{+    C12 a;+    C14 b;+} C15;++C15 * newC15(C12* a, C14* b){+    C15 * ret = (C15*) malloc(sizeof(C15));+    ret->a = *a;+    ret->b = *b;+    return ret;+}++void pokeC15(C15* val, C12* a, C14* b){+    val->a = *a;+    val->b = *b;+}++int checkOffsetsC15(HsInt16 *offs){+    int a = offsetof(C15, a) == offs[0];+    int b = offsetof(C15, b) == offs[1];+    return a && b;+}++int checkFieldsC15(C15* s1, C15* s2){+    int a = checkFieldsC12(&(s1->a),&(s2->a));+    int b = checkFieldsC14(&(s1->b),&(s2->b));+    return a && b;+}++HsInt16 getSizeC15() {+    return sizeof(C15);+}++HsInt16 getAlignmentC15() {+    return alignof(C15);+}++typedef struct C16{+    C10 a;+    C15 b;+    C7 c;+} C16;++C16 * newC16(C10* a, C15* b, C7* c){+    C16 * ret = (C16*) malloc(sizeof(C16));+    ret->a = *a;+    ret->b = *b;+    ret->c = *c;+    return ret;+}++void pokeC16(C16* val, C10* a, C15* b, C7* c){+    val->a = *a;+    val->b = *b;+    val->c = *c;+}++int checkOffsetsC16(HsInt16 *offs){+    int a = offsetof(C16, a) == offs[0];+    int b = offsetof(C16, b) == offs[1];+    int c = offsetof(C16, c) == offs[2];+    return a && b && c;+}++int checkFieldsC16(C16* s1, C16* s2){+    int a = checkFieldsC10(&(s1->a),&(s2->a));+    int b = checkFieldsC15(&(s1->b),&(s2->b));+    int c = checkFieldsC7(&(s1->c),&(s2->c));+    return a && b && c;+}++HsInt16 getSizeC16() {+    return sizeof(C16);+}++HsInt16 getAlignmentC16() {+    return alignof(C16);+}++typedef struct C17{+    HsFloat a;+    HsDouble b;+    HsFloat c;+} C17;++C17 * newC17(HsFloat a, HsDouble b, HsFloat c){+    C17 * ret = (C17*) malloc(sizeof(C17));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC17(C17* val, HsFloat a, HsDouble b, HsFloat c){+    val->a = a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC17(HsInt16 *offs){+    int a = offsetof(C17, a) == offs[0];+    int b = offsetof(C17, b) == offs[1];+    int c = offsetof(C17, c) == offs[2];+    return a && b && c;+}++int checkFieldsC17(C17* s1, C17* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC17() {+    return sizeof(C17);+}++HsInt16 getAlignmentC17() {+    return alignof(C17);+}++typedef struct C18{+    HsFloat a;+    HsFloat b;+    HsDouble c;+    HsFloat d;+} C18;++C18 * newC18(HsFloat a, HsFloat b, HsDouble c, HsFloat d){+    C18 * ret = (C18*) malloc(sizeof(C18));+    ret->a = a;+    ret->b = b;+    ret->c = c;+    ret->d = d;+    return ret;+}++void pokeC18(C18* val, HsFloat a, HsFloat b, HsDouble c, HsFloat d){+    val->a = a;+    val->b = b;+    val->c = c;+    val->d = d;+}++int checkOffsetsC18(HsInt16 *offs){+    int a = offsetof(C18, a) == offs[0];+    int b = offsetof(C18, b) == offs[1];+    int c = offsetof(C18, c) == offs[2];+    int d = offsetof(C18, d) == offs[3];+    return a && b && c && d;+}++int checkFieldsC18(C18* s1, C18* s2){+    int a = s1->a == s2->a;+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    int d = s1->d == s2->d;+    return a && b && c && d;+}++HsInt16 getSizeC18() {+    return sizeof(C18);+}++HsInt16 getAlignmentC18() {+    return alignof(C18);+}++typedef struct C19{+    C17 a;+    HsFloat b;+    HsDouble c;+} C19;++C19 * newC19(C17* a, HsFloat b, HsDouble c){+    C19 * ret = (C19*) malloc(sizeof(C19));+    ret->a = *a;+    ret->b = b;+    ret->c = c;+    return ret;+}++void pokeC19(C19* val, C17* a, HsFloat b, HsDouble c){+    val->a = *a;+    val->b = b;+    val->c = c;+}++int checkOffsetsC19(HsInt16 *offs){+    int a = offsetof(C19, a) == offs[0];+    int b = offsetof(C19, b) == offs[1];+    int c = offsetof(C19, c) == offs[2];+    return a && b && c;+}++int checkFieldsC19(C19* s1, C19* s2){+    int a = checkFieldsC17(&(s1->a),&(s2->a));+    int b = s1->b == s2->b;+    int c = s1->c == s2->c;+    return a && b && c;+}++HsInt16 getSizeC19() {+    return sizeof(C19);+}++HsInt16 getAlignmentC19() {+    return alignof(C19);+}++typedef struct C20{+    HsDouble a;+    C18 b;+    HsDouble c;+    C19 d;+} C20;++C20 * newC20(HsDouble a, C18* b, HsDouble c, C19* d){+    C20 * ret = (C20*) malloc(sizeof(C20));+    ret->a = a;+    ret->b = *b;+    ret->c = c;+    ret->d = *d;+    return ret;+}++void pokeC20(C20* val, HsDouble a, C18* b, HsDouble c, C19* d){+    val->a = a;+    val->b = *b;+    val->c = c;+    val->d = *d;+}++int checkOffsetsC20(HsInt16 *offs){+    int a = offsetof(C20, a) == offs[0];+    int b = offsetof(C20, b) == offs[1];+    int c = offsetof(C20, c) == offs[2];+    int d = offsetof(C20, d) == offs[3];+    return a && b && c && d;+}++int checkFieldsC20(C20* s1, C20* s2){+    int a = s1->a == s2->a;+    int b = checkFieldsC18(&(s1->b),&(s2->b));+    int c = s1->c == s2->c;+    int d = checkFieldsC19(&(s1->d),&(s2->d));+    return a && b && c && d;+}++HsInt16 getSizeC20() {+    return sizeof(C20);+}++HsInt16 getAlignmentC20() {+    return alignof(C20);+}+
+ test/Spec/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}