{-# LANGUAGE CPP #-} #if __GLASGOW_HASKELL__ >= 704 {-# LANGUAGE Unsafe #-} #endif module Hails.IterIO.Conversions ( iterIOtoIterLIO , ioIterRtoLIO , onumIOtoOnumLIO , inumIOtoInumLIO ) where import qualified Data.ByteString.Lazy.Char8 as L import Data.IORef import Data.IterIO import LIO.DCLabel import LIO.TCB import Control.Monad import Control.Monad.Trans type L = L.ByteString -- | Lift the underlying monad of an 'Iter' from 'IO' to 'LIO'. iterIOtoIterLIO :: (LabelState l p s, ChunkData t) => Iter t IO a -> Iter t (LIO l p s) a iterIOtoIterLIO = adaptIterM rtioTCB -- | Lift the underlying monad of an 'IterR' from 'IO' to 'LIO'. ioIterRtoLIO :: (LabelState l p s, ChunkData t) => IterR t IO a -> IterR t (LIO l p s) a ioIterRtoLIO (Done a (Chunk b c)) = Done a (Chunk b c) ioIterRtoLIO (IterM m) = IterM $ fmap ioIterRtoLIO $ rtioTCB m ioIterRtoLIO (IterF next) = IterF $ iterIOtoIterLIO next ioIterRtoLIO (Fail itf ma mb) = Fail itf ma mb ioIterRtoLIO (IterC (CtlArg carg f c)) = let g = \cres -> iterIOtoIterLIO $ f cres in IterC (CtlArg carg g c) -- | Lift the underlying monad of an 'Inum' from 'IO' to 'LIO'. onumIOtoOnumLIO :: LabelState l p s => Onum L IO L -> Onum L (LIO l p s) a onumIOtoOnumLIO inO = mkInum $ iterIOtoIterLIO (inO .| dataI) -- | Lift the underlying monad of the Iter and IterR result type. inumResIOtoIO :: (LabelState l p s, ChunkData tIn, ChunkData tOut) => Iter tIn IO (IterR tOut IO a) -> Iter tIn (LIO l p s) (IterR tOut (LIO l p s) a) inumResIOtoIO iIn = liftM ioIterRtoLIO $ iterIOtoIterLIO iIn -- | Run an LIO computation. iterLIOtoIterIO :: (LabelState l p s, ChunkData t) => Iter t (LIO l p s) a -> LIOstate l p s -> Iter t IO (a, LIOstate l p s) iterLIOtoIterIO iter0 s0 = adaptIter (\a -> (a, s0)) adapt iter0 where adapt m = lift (runLIO m s0) >>= uncurry iterLIOtoIterIO -- iterLIOtoIterIO lio = runStateTLI (adaptIterM peelLIO lio) -- where peelLIO (LIO x) = x inumIOtoInumLIO :: (ChunkData tIn, ChunkData tOut) => Inum tIn tOut IO a -> LIOstate DCLabel TCBPriv () -> Inum tIn tOut DC a inumIOtoInumLIO io12 s0 = \dc1 -> do -- Create ref that will be used to store the final state after -- running dc1 ref <- lift $ ioTCB $ newIORef s0 -- run dc1 let io1 = do (x, s1) <- iterLIOtoIterIO dc1 s0 {- Iter tOut IO (a, LIOstate) -} -- save end state liftIO $ writeIORef ref s1 return x -- apply io1 to the inum io2 = io12 io1 {- Iter tIn IO (IterR tOut IO a) -} -- change the monad from IO to DC res <- inumResIOtoIO io2 {- Iter tIn DC (IterR tOut DC a) -} -- set the end label to the end of that running dc1 lift $ do s1 <- ioTCB $ readIORef ref putTCB s1 return res