{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE UndecidableInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Test.StateMachine.Internal.Types -- Copyright : (C) 2017, ATS Advanced Telematic Systems GmbH -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Stevan Andjelkovic -- Stability : provisional -- Portability : non-portable (GHC extensions) -- -- This module exports some types that are used internally by the library. -- ----------------------------------------------------------------------------- module Test.StateMachine.Internal.Types ( Program(..) , ParallelProgram(..) , Pid(..) , Fork(..) , Internal(..) ) where import Data.List (intercalate) import Data.Typeable (Typeable) import Text.Read (readListPrec, readListPrecDefault, readPrec) import Test.StateMachine.Types (Untyped(Untyped)) import Test.StateMachine.Types.HFunctor import Test.StateMachine.Types.References ------------------------------------------------------------------------ -- | A (sequential) program is an abstract datatype representing a list -- of actions. -- -- The idea is that the user shows how to generate, shrink, execute and -- modelcheck individual actions, and then the below combinators lift -- those things to whole programs. newtype Program act = Program { unProgram :: [Internal act] } instance Eq (Internal act) => Eq (Program act) where Program acts1 == Program acts2 = acts1 == acts2 instance Monoid (Program act) where mempty = Program [] Program acts1 `mappend` Program acts2 = Program (acts1 ++ acts2) instance (Show (Untyped act), HFoldable act) => Show (Program act) where show (Program iacts) = bracket . intercalate "," . map go $ iacts where go (Internal act (Symbolic var)) = show (Untyped act) ++ " " ++ show var bracket s = "[" ++ s ++ "]" instance Read (Internal act) => Read (Program act) where readPrec = Program <$> readPrec readListPrec = readListPrecDefault ------------------------------------------------------------------------ -- | A parallel program is an abstract datatype that represents three -- sequences of actions; a sequential prefix and two parallel -- suffixes. Analogous to the sequential case, the user shows how to -- generate, shrink, execute and modelcheck individual actions, and -- then the below combinators lift those things to whole parallel -- programs. newtype ParallelProgram act = ParallelProgram { unParallelProgram :: Fork (Program act) } instance (Show (Untyped act), HFoldable act) => Show (ParallelProgram act) where show = show . unParallelProgram -- | Forks are used to represent parallel programs. data Fork a = Fork a a a deriving (Eq, Functor, Show, Ord, Read) ------------------------------------------------------------------------ -- | An internal action is an action together with the symbolic variable -- that will hold its result. data Internal (act :: (* -> *) -> * -> *) where Internal :: (Show resp, Typeable resp) => act Symbolic resp -> Symbolic resp -> Internal act ------------------------------------------------------------------------ -- | A process id. newtype Pid = Pid Int deriving (Eq, Show)