{-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Generate random inputs to Ivory-generated C code. -- -- Example usage: -- @ -- [ivory| -- struct foo -- { foo_a :: Stored IFloat -- ; foo_b :: Stored Uint8 -- } -- |] -- -- -- Function we want to generate inputs for. -- func :: Def ('[Uint8 -- , Ref s (Array 3 (Stored Uint8)) -- , Ref s (Struct "foo") -- ] :-> ()) -- func = proc "func" $ \u arr str -> body $ -- arrayMap $ \ix -> do -- a <- deref (arr ! ix) -- b <- deref (str ~> foo_b) -- store (arr ! ix) (a + b + u) -- -- type DriverDef = Def ('[] :-> ()) -- -- -- Driver function. Takes lists of the arguments we'll pass to the function -- -- test. -- driver :: [Uint8] -- -> [Init (Array 3 (Stored Uint8))] -- -> [Init (Struct "foo")] -- -> DriverDef -- driver as0 as1 as2 = proc "main" $ body $ do -- mapM_ oneCall (zip3 as0 as1 as2) -- -- where -- oneCall (a0, a1, a2) = do -- a1' <- local a1 -- a2' <- local a2 -- call_ func a0 a1' a2' -- -- -- Generate the random values to pass. -- runTest :: IvoryGen DriverDef -- runTest = do -- args0 <- samples num A.arbitrary -- args1 <- samples num A.arbitrary -- aFoos <- samples num foo_a -- bFoos <- samples num foo_b -- return $ driver args0 args1 (zipWith foo aFoos bFoos) -- where -- foo a b = istruct [ a, b ] -- num = 10 -- -- -- Compile! -- runTests :: IO () -- runTests = do -- d <- runIO runTest -- runCompiler [cmodule d] initialOpts { includeDir = "test" -- , srcDir = "test" -- , constFold = True -- } -- where -- cmodule d = package "qc" $ do -- incl d -- incl func -- @ module Ivory.QuickCheck ( module Ivory.QuickCheck.Monad , module Ivory.QuickCheck.Arbitrary , Samples(..) ) where import qualified Test.QuickCheck.Arbitrary as A import qualified Test.QuickCheck.Gen as G import Ivory.QuickCheck.Arbitrary import Ivory.QuickCheck.Monad import Ivory.Language import GHC.TypeLits -------------------------------------------------------------------------------- type Size = Int class Samples gen res where samples :: Size -> gen -> IvoryGen [res] instance A.Arbitrary a => Samples (G.Gen a) a where samples = mkSamples instance (A.Arbitrary a, SingI len, IvoryInit a, IvoryType a) => Samples (G.Gen a) (Init (Array len (Stored a))) where samples i gen = mkSamples i mkArr where mkArr = do let sz = fromSing (sing :: Sing len) arr <- G.vectorOf (fromInteger sz) gen return $ iarray (map ival arr) instance (A.Arbitrary a, IvoryInit a) => Samples (Label sym (Stored a)) (InitStruct sym) where samples i label = mkSamples i (sampleStoredLabel label) --------------------------------------------------------------------------------