module Test.StateMachine.Internal.Types
( Program(..)
, programLength
, ParallelProgram(..)
, parallelProgramLength
, parallelProgramToList
, parallelProgramFromList
, parallelProgramAsList
, flattenParallelProgram
, Pid(..)
, Internal(..)
) where
import Data.Bifunctor
(bimap)
import Data.Monoid
((<>))
import Data.Typeable
(Typeable)
import Text.Read
(Lexeme(Ident), lexP, parens, prec, readPrec, step)
import Test.StateMachine.Types
(Untyped(Untyped))
import Test.StateMachine.Types.References
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)
deriving instance Show (Untyped act) => Show (Program act)
deriving instance Read (Untyped act) => Read (Program act)
programLength :: Program act -> Int
programLength = length . unProgram
data ParallelProgram act
= ParallelProgram (Program act) [(Program act, Program act)]
deriving instance Eq (Untyped act) => Eq (ParallelProgram act)
deriving instance Show (Untyped act) => Show (ParallelProgram act)
deriving instance Read (Untyped act) => Read (ParallelProgram act)
parallelProgramLength :: ParallelProgram act -> Int
parallelProgramLength (ParallelProgram prefix suffixes) =
programLength prefix +
programLength (mconcat (parallelProgramToList suffixes))
parallelProgramFromList :: [Program act] -> [(Program act, Program act)]
parallelProgramFromList
= map (\prog -> bimap Program Program
(splitAt (programLength prog `div` 2) (unProgram prog)))
parallelProgramToList :: [(Program act, Program act)] -> [Program act]
parallelProgramToList = map (\(prog1, prog2) -> prog1 <> prog2)
parallelProgramAsList
:: ([Program act] -> [Program act])
-> [(Program act, Program act)]
-> [(Program act, Program act)]
parallelProgramAsList f = parallelProgramFromList . f . parallelProgramToList
flattenParallelProgram :: ParallelProgram act -> Program act
flattenParallelProgram (ParallelProgram prefix suffixes)
= prefix <> mconcat (parallelProgramToList suffixes)
data Internal (act :: (* -> *) -> * -> *) where
Internal :: (Show resp, Typeable resp) =>
act Symbolic resp -> Symbolic resp -> Internal act
instance Eq (Untyped act) => Eq (Internal act) where
Internal a1 _ == Internal a2 _ = Untyped a1 == Untyped a2
instance Show (Untyped act) => Show (Internal act) where
showsPrec p (Internal action v) = showParen (p > appPrec) $
showString "Internal " .
showsPrec (appPrec + 1) (Untyped action) .
showString " " .
showsPrec (appPrec + 1) v
where
appPrec = 10
instance Read (Untyped act) => Read (Internal act) where
readPrec = parens $
prec appPrec $ do
Ident "Internal" <- lexP
Untyped action <- step readPrec
v <- step readPrec
return (Internal action v)
where
appPrec = 10
newtype Pid = Pid Int
deriving (Eq, Show)