{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RecordWildCards #-}
module LiveCoding.RuntimeIO.Launch where
import Control.Concurrent
import Control.Monad
import Data.Data
import Control.Monad.Trans.State.Strict
import Control.Monad.Trans.Except
import LiveCoding.Debugger
import LiveCoding.Handle
import LiveCoding.LiveProgram
import LiveCoding.LiveProgram.Except
import LiveCoding.LiveProgram.HotCodeSwap
import LiveCoding.Cell.Monad.Trans
import LiveCoding.Exceptions.Finite (Finite)
class Monad m => Launchable m where
runIO :: LiveProgram m -> LiveProgram IO
instance Launchable IO where
runIO :: LiveProgram IO -> LiveProgram IO
runIO = LiveProgram IO -> LiveProgram IO
forall a. a -> a
id
instance (Typeable m, Launchable m) => Launchable (StateT (HandlingState m) m) where
runIO :: LiveProgram (StateT (HandlingState m) m) -> LiveProgram IO
runIO = LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO (LiveProgram m -> LiveProgram IO)
-> (LiveProgram (StateT (HandlingState m) m) -> LiveProgram m)
-> LiveProgram (StateT (HandlingState m) m)
-> LiveProgram IO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LiveProgram (StateT (HandlingState m) m) -> LiveProgram m
forall (m :: * -> *).
(Monad m, Typeable m) =>
LiveProgram (HandlingStateT m) -> LiveProgram m
runHandlingState
instance (Data e, Finite e, Launchable m) => Launchable (ExceptT e m) where
runIO :: LiveProgram (ExceptT e m) -> LiveProgram IO
runIO LiveProgram (ExceptT e m)
liveProgram = LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO (LiveProgram m -> LiveProgram IO)
-> LiveProgram m -> LiveProgram IO
forall a b. (a -> b) -> a -> b
$ LiveProgramExcept m e -> LiveProgram m
forall e (m :: * -> *).
(Data e, Monad m) =>
LiveProgramExcept m e -> LiveProgram m
foreverCLiveProgram (LiveProgramExcept m e -> LiveProgram m)
-> LiveProgramExcept m e -> LiveProgram m
forall a b. (a -> b) -> a -> b
$ LiveProgram (ExceptT e m) -> LiveProgramExcept m e
forall e (m :: * -> *).
(Data e, Finite e, Functor m) =>
LiveProgram (ExceptT e m) -> LiveProgramExcept m e
try LiveProgram (ExceptT e m)
liveProgram
liveMain
:: Launchable m
=> LiveProgram m
-> IO ()
liveMain :: LiveProgram m -> IO ()
liveMain = LiveProgram IO -> IO ()
forall (m :: * -> *). Monad m => LiveProgram m -> m ()
foreground (LiveProgram IO -> IO ())
-> (LiveProgram m -> LiveProgram IO) -> LiveProgram m -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO
foreground :: Monad m => LiveProgram m -> m ()
foreground :: LiveProgram m -> m ()
foreground LiveProgram m
liveProgram
= LiveProgram m -> m (LiveProgram m)
forall (m :: * -> *). Monad m => LiveProgram m -> m (LiveProgram m)
stepProgram LiveProgram m
liveProgram
m (LiveProgram m) -> (LiveProgram m -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= LiveProgram m -> m ()
forall (m :: * -> *). Monad m => LiveProgram m -> m ()
foreground
data LaunchedProgram (m :: * -> *) = LaunchedProgram
{ LaunchedProgram m -> MVar (LiveProgram IO)
programVar :: MVar (LiveProgram IO)
, LaunchedProgram m -> ThreadId
threadId :: ThreadId
}
launch
:: Launchable m
=> LiveProgram m
-> IO (LaunchedProgram m)
launch :: LiveProgram m -> IO (LaunchedProgram m)
launch LiveProgram m
liveProg = do
MVar (LiveProgram IO)
programVar <- LiveProgram IO -> IO (MVar (LiveProgram IO))
forall a. a -> IO (MVar a)
newMVar (LiveProgram IO -> IO (MVar (LiveProgram IO)))
-> LiveProgram IO -> IO (MVar (LiveProgram IO))
forall a b. (a -> b) -> a -> b
$ LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO LiveProgram m
liveProg
ThreadId
threadId <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ MVar (LiveProgram IO) -> IO ()
background MVar (LiveProgram IO)
programVar
LaunchedProgram m -> IO (LaunchedProgram m)
forall (m :: * -> *) a. Monad m => a -> m a
return LaunchedProgram :: forall (m :: * -> *).
MVar (LiveProgram IO) -> ThreadId -> LaunchedProgram m
LaunchedProgram { ThreadId
MVar (LiveProgram IO)
threadId :: ThreadId
programVar :: MVar (LiveProgram IO)
threadId :: ThreadId
programVar :: MVar (LiveProgram IO)
.. }
update
:: Launchable m
=> LaunchedProgram m
-> LiveProgram m
-> IO ()
update :: LaunchedProgram m -> LiveProgram m -> IO ()
update LaunchedProgram { ThreadId
MVar (LiveProgram IO)
threadId :: ThreadId
programVar :: MVar (LiveProgram IO)
threadId :: forall (m :: * -> *). LaunchedProgram m -> ThreadId
programVar :: forall (m :: * -> *). LaunchedProgram m -> MVar (LiveProgram IO)
.. } LiveProgram m
newProg = MVar (LiveProgram IO)
-> (LiveProgram IO -> IO (LiveProgram IO)) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVarMasked_ MVar (LiveProgram IO)
programVar
((LiveProgram IO -> IO (LiveProgram IO)) -> IO ())
-> (LiveProgram IO -> IO (LiveProgram IO)) -> IO ()
forall a b. (a -> b) -> a -> b
$ LiveProgram IO -> IO (LiveProgram IO)
forall (m :: * -> *) a. Monad m => a -> m a
return (LiveProgram IO -> IO (LiveProgram IO))
-> (LiveProgram IO -> LiveProgram IO)
-> LiveProgram IO
-> IO (LiveProgram IO)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LiveProgram IO -> LiveProgram IO -> LiveProgram IO
forall (m :: * -> *).
LiveProgram m -> LiveProgram m -> LiveProgram m
hotCodeSwap (LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO LiveProgram m
newProg)
stop
:: Launchable m
=> LaunchedProgram m
-> IO ()
stop :: LaunchedProgram m -> IO ()
stop launchedProgram :: LaunchedProgram m
launchedProgram@LaunchedProgram { ThreadId
MVar (LiveProgram IO)
threadId :: ThreadId
programVar :: MVar (LiveProgram IO)
threadId :: forall (m :: * -> *). LaunchedProgram m -> ThreadId
programVar :: forall (m :: * -> *). LaunchedProgram m -> MVar (LiveProgram IO)
.. } = do
LaunchedProgram m -> LiveProgram m -> IO ()
forall (m :: * -> *).
Launchable m =>
LaunchedProgram m -> LiveProgram m -> IO ()
update LaunchedProgram m
launchedProgram LiveProgram m
forall a. Monoid a => a
mempty
LaunchedProgram m -> IO ()
forall (m :: * -> *).
(Monad m, Launchable m) =>
LaunchedProgram m -> IO ()
stepLaunchedProgram LaunchedProgram m
launchedProgram
ThreadId -> IO ()
killThread ThreadId
threadId
launchWithDebugger
:: (Monad m, Launchable m)
=> LiveProgram m
-> Debugger m
-> IO (LaunchedProgram m)
launchWithDebugger :: LiveProgram m -> Debugger m -> IO (LaunchedProgram m)
launchWithDebugger LiveProgram m
liveProg Debugger m
debugger = LiveProgram m -> IO (LaunchedProgram m)
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> IO (LaunchedProgram m)
launch (LiveProgram m -> IO (LaunchedProgram m))
-> LiveProgram m -> IO (LaunchedProgram m)
forall a b. (a -> b) -> a -> b
$ LiveProgram m
liveProg LiveProgram m -> Debugger m -> LiveProgram m
forall (m :: * -> *).
Monad m =>
LiveProgram m -> Debugger m -> LiveProgram m
`withDebugger` Debugger m
debugger
background :: MVar (LiveProgram IO) -> IO ()
background :: MVar (LiveProgram IO) -> IO ()
background MVar (LiveProgram IO)
var = IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
LiveProgram IO
liveProg <- MVar (LiveProgram IO) -> IO (LiveProgram IO)
forall a. MVar a -> IO a
takeMVar MVar (LiveProgram IO)
var
LiveProgram IO
liveProg' <- LiveProgram IO -> IO (LiveProgram IO)
forall (m :: * -> *). Monad m => LiveProgram m -> m (LiveProgram m)
stepProgram LiveProgram IO
liveProg
MVar (LiveProgram IO) -> LiveProgram IO -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (LiveProgram IO)
var LiveProgram IO
liveProg'
stepProgram :: Monad m => LiveProgram m -> m (LiveProgram m)
stepProgram :: LiveProgram m -> m (LiveProgram m)
stepProgram LiveProgram {s
s -> m s
liveStep :: ()
liveState :: ()
liveStep :: s -> m s
liveState :: s
..} = do
s
liveState' <- s -> m s
liveStep s
liveState
LiveProgram m -> m (LiveProgram m)
forall (m :: * -> *) a. Monad m => a -> m a
return LiveProgram :: forall (m :: * -> *) s. Data s => s -> (s -> m s) -> LiveProgram m
LiveProgram { liveState :: s
liveState = s
liveState', s -> m s
liveStep :: s -> m s
liveStep :: s -> m s
.. }
stepLaunchedProgram
:: (Monad m, Launchable m)
=> LaunchedProgram m
-> IO ()
stepLaunchedProgram :: LaunchedProgram m -> IO ()
stepLaunchedProgram LaunchedProgram { ThreadId
MVar (LiveProgram IO)
threadId :: ThreadId
programVar :: MVar (LiveProgram IO)
threadId :: forall (m :: * -> *). LaunchedProgram m -> ThreadId
programVar :: forall (m :: * -> *). LaunchedProgram m -> MVar (LiveProgram IO)
.. } = MVar (LiveProgram IO)
-> (LiveProgram IO -> IO (LiveProgram IO)) -> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVarMasked_ MVar (LiveProgram IO)
programVar LiveProgram IO -> IO (LiveProgram IO)
forall (m :: * -> *). Monad m => LiveProgram m -> m (LiveProgram m)
stepProgram