{-# 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)
import LiveCoding.HandlingState
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 (HandlingStateT m) where
runIO :: LiveProgram (HandlingStateT m) -> LiveProgram IO
runIO = LiveProgram m -> LiveProgram IO
forall (m :: * -> *).
Launchable m =>
LiveProgram m -> LiveProgram IO
runIO (LiveProgram m -> LiveProgram IO)
-> (LiveProgram (HandlingStateT m) -> LiveProgram m)
-> LiveProgram (HandlingStateT m)
-> LiveProgram IO
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LiveProgram (HandlingStateT 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