{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RecordWildCards #-}
module LiveCoding.RuntimeIO.Launch where
import Control.Concurrent
import Control.Monad
import Control.Monad.Trans.State.Strict
import LiveCoding.Debugger
import LiveCoding.Handle
import LiveCoding.LiveProgram
import LiveCoding.LiveProgram.HotCodeSwap
import LiveCoding.Cell.Monad.Trans
import Data.Data (Typeable)
class Monad m => Launchable m where
runIO :: LiveProgram m -> LiveProgram IO
instance Launchable IO where
runIO = id
instance Launchable (StateT (HandlingState IO) IO) where
runIO = runHandlingState
data LaunchedProgram (m :: * -> *) = LaunchedProgram
{ programVar :: MVar (LiveProgram IO)
, threadId :: ThreadId
}
launch
:: Launchable m
=> LiveProgram m
-> IO (LaunchedProgram m)
launch liveProg = do
programVar <- newMVar $ runIO liveProg
threadId <- forkIO $ background programVar
return LaunchedProgram { .. }
update
:: Launchable m
=> LaunchedProgram m
-> LiveProgram m
-> IO ()
update LaunchedProgram { .. } newProg = do
oldProg <- takeMVar programVar
putMVar programVar $ hotCodeSwap (runIO newProg) oldProg
stop
:: Launchable m
=> LaunchedProgram m
-> IO ()
stop launchedProgram@LaunchedProgram { .. } = do
update launchedProgram mempty
stepLaunchedProgram launchedProgram
killThread threadId
launchWithDebugger
:: (Monad m, Launchable m)
=> LiveProgram m
-> Debugger m
-> IO (LaunchedProgram m)
launchWithDebugger liveProg debugger = launch $ liveProg `withDebugger` debugger
background :: MVar (LiveProgram IO) -> IO ()
background var = forever $ do
liveProg <- takeMVar var
liveProg' <- stepProgram liveProg
putMVar var liveProg'
stepProgram :: Monad m => LiveProgram m -> m (LiveProgram m)
stepProgram LiveProgram {..} = do
liveState' <- liveStep liveState
return LiveProgram { liveState = liveState', .. }
stepLaunchedProgram
:: (Monad m, Launchable m)
=> LaunchedProgram m
-> IO ()
stepLaunchedProgram LaunchedProgram { .. } = modifyMVar_ programVar stepProgram