{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module LiveCoding.GHCi where
import Control.Concurrent
import Control.Exception (Exception (displayException, toException), SomeException, try)
import Control.Monad (join, void, (>=>))
import Data.Data
import Data.Function ((&))
import Control.Monad.Trans.State.Strict
import Foreign.Store
import LiveCoding.LiveProgram
import LiveCoding.RuntimeIO.Launch
proxyFromLiveProgram :: LiveProgram m -> Proxy m
proxyFromLiveProgram :: forall (m :: * -> *). LiveProgram m -> Proxy m
proxyFromLiveProgram LiveProgram m
_ = forall {k} (t :: k). Proxy t
Proxy
data NoStore = NoStore
deriving (Int -> NoStore -> ShowS
[NoStore] -> ShowS
NoStore -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NoStore] -> ShowS
$cshowList :: [NoStore] -> ShowS
show :: NoStore -> String
$cshow :: NoStore -> String
showsPrec :: Int -> NoStore -> ShowS
$cshowsPrec :: Int -> NoStore -> ShowS
Show)
instance Exception NoStore
possiblyLaunchedProgram ::
Launchable m =>
Proxy m ->
IO (Either SomeException (LaunchedProgram m))
possiblyLaunchedProgram :: forall (m :: * -> *).
Launchable m =>
Proxy m -> IO (Either SomeException (LaunchedProgram m))
possiblyLaunchedProgram Proxy m
_ = do
Maybe (Store (LaunchedProgram m))
storeMaybe <- forall a. Word32 -> IO (Maybe (Store a))
lookupStore Word32
0
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall e a. Exception e => IO a -> IO (Either e a)
try forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall a. Store a -> IO a
readStore forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall e. Exception e => e -> SomeException
toException NoStore
NoStore) forall a b. b -> Either a b
Right Maybe (Store (LaunchedProgram m))
storeMaybe
sync :: Launchable m => LiveProgram m -> IO ()
sync :: forall (m :: * -> *). Launchable m => LiveProgram m -> IO ()
sync LiveProgram m
program = do
Either SomeException (LaunchedProgram m)
launchedProgramPossibly <- forall (m :: * -> *).
Launchable m =>
Proxy m -> IO (Either SomeException (LaunchedProgram m))
possiblyLaunchedProgram forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). LiveProgram m -> Proxy m
proxyFromLiveProgram LiveProgram m
program
case Either SomeException (LaunchedProgram m)
launchedProgramPossibly of
Left (SomeException
e :: SomeException) -> do
String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ forall e. Exception e => e -> String
displayException SomeException
e
forall (m :: * -> *). Launchable m => LiveProgram m -> IO ()
launchAndSave LiveProgram m
program
Right LaunchedProgram m
launchedProgram -> do
String -> IO ()
putStrLn String
"update"
forall (m :: * -> *).
Launchable m =>
LaunchedProgram m -> LiveProgram m -> IO ()
update LaunchedProgram m
launchedProgram LiveProgram m
program
launchAndSave :: Launchable m => LiveProgram m -> IO ()
launchAndSave :: forall (m :: * -> *). Launchable m => LiveProgram m -> IO ()
launchAndSave = forall (m :: * -> *).
Launchable m =>
LiveProgram m -> IO (LaunchedProgram m)
launch forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall (m :: * -> *). Launchable m => LaunchedProgram m -> IO ()
save
save :: Launchable m => LaunchedProgram m -> IO ()
save :: forall (m :: * -> *). Launchable m => LaunchedProgram m -> IO ()
save = forall a. Store a -> a -> IO ()
writeStore forall a b. (a -> b) -> a -> b
$ forall a. Word32 -> Store a
Store Word32
0
stopStored ::
Launchable m =>
Proxy m ->
IO ()
stopStored :: forall (m :: * -> *). Launchable m => Proxy m -> IO ()
stopStored Proxy m
proxy = do
Either SomeException (LaunchedProgram m)
launchedProgramPossibly <- forall (m :: * -> *).
Launchable m =>
Proxy m -> IO (Either SomeException (LaunchedProgram m))
possiblyLaunchedProgram Proxy m
proxy
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> IO ()
putStrLn forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Exception e => e -> String
displayException) forall (m :: * -> *). Launchable m => LaunchedProgram m -> IO ()
stop Either SomeException (LaunchedProgram m)
launchedProgramPossibly
liveinit :: p -> m String
liveinit p
_ =
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
[String] -> String
unlines
[ String
"programVar <- newMVar liveProgram"
, String
"threadId <- myThreadId"
, String
"save LaunchedProgram { .. }"
]
livestep :: p -> m String
livestep p
_ = forall (m :: * -> *) a. Monad m => a -> m a
return String
"stepLaunchedProgram launchedProgram"
livelaunch :: p -> m String
livelaunch p
_ = forall (m :: * -> *) a. Monad m => a -> m a
return String
"sync liveProgram"
livereload :: p -> m String
livereload p
_ =
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
[String] -> String
unlines
[ String
":reload"
, String
"sync liveProgram"
]
livestop :: p -> m String
livestop p
_ = forall (m :: * -> *) a. Monad m => a -> m a
return String
"stopStored $ proxyFromLiveProgram liveProgram"