{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, TypeOperators #-}
module Test.IOSpec.MVar
(
MVarS
, MVar
, newEmptyMVar
, takeMVar
, putMVar
)
where
import Data.Dynamic
import Data.Maybe (fromJust)
import Test.IOSpec.Types
import Test.IOSpec.VirtualMachine
data MVarS a =
NewEmptyMVar (Loc -> a)
| TakeMVar Loc (Data -> a)
| PutMVar Loc Data a
instance Functor MVarS where
fmap f (NewEmptyMVar io) = NewEmptyMVar (f . io)
fmap f (TakeMVar l io) = TakeMVar l (f . io)
fmap f (PutMVar l d io) = PutMVar l d (f io)
newtype MVar a = MVar Loc deriving Typeable
newEmptyMVar :: (Typeable a, MVarS :<: f) => IOSpec f (MVar a)
newEmptyMVar = inject $ NewEmptyMVar (return . MVar)
takeMVar :: (Typeable a, MVarS :<: f) => MVar a -> IOSpec f a
takeMVar (MVar l) = inject $ TakeMVar l (return . fromJust . fromDynamic)
putMVar :: (Typeable a, MVarS :<: f) => MVar a -> a -> IOSpec f ()
putMVar (MVar l) d = inject $ PutMVar l (toDyn d) (return ())
instance Executable MVarS where
step (NewEmptyMVar t) = do loc <- alloc
emptyLoc loc
return (Step (t loc))
step (TakeMVar loc t) = do var <- lookupHeap loc
case var of
Nothing -> return Block
Just x -> do
emptyLoc loc
return (Step (t x))
step (PutMVar loc d t) = do var <- lookupHeap loc
case var of
Nothing -> do
updateHeap loc d
return (Step t)
Just _ -> return Block