{-# LANGUAGE FlexibleContexts, TypeOperators #-}
module Test.IOSpec.IORef
(
IORefS
, IORef
, newIORef
, readIORef
, writeIORef
, modifyIORef
)
where
import Data.Dynamic
import Data.Maybe (fromJust)
import Test.IOSpec.Types
import Test.IOSpec.VirtualMachine
data IORefS a =
NewIORef Data (Loc -> a)
| ReadIORef Loc (Data -> a)
| WriteIORef Loc Data a
instance Functor IORefS where
fmap f (NewIORef d io) = NewIORef d (f . io)
fmap f (ReadIORef l io) = ReadIORef l (f . io)
fmap f (WriteIORef l d io) = WriteIORef l d (f io)
newtype IORef a = IORef Loc
newIORef :: (Typeable a, IORefS :<: f) => a -> IOSpec f (IORef a)
newIORef d = inject $ NewIORef (toDyn d) (return . IORef)
readIORef :: (Typeable a, IORefS :<:f ) => IORef a -> IOSpec f a
readIORef (IORef l) = inject $ ReadIORef l (return . fromJust . fromDynamic)
writeIORef :: (Typeable a, IORefS :<: f) => IORef a -> a -> IOSpec f ()
writeIORef (IORef l) d = inject $ WriteIORef l (toDyn d) (return ())
modifyIORef :: (Typeable a, IORefS :<: f)
=> IORef a -> (a -> a) -> IOSpec f ()
modifyIORef ref f = readIORef ref >>= \x -> writeIORef ref (f x)
instance Executable IORefS where
step (NewIORef d t) = do loc <- alloc
updateHeap loc d
return (Step (t loc))
step (ReadIORef l t) = do lookupHeap l >>= \(Just d) -> do
return (Step (t d))
step (WriteIORef l d t) = do updateHeap l d
return (Step t)