{-# LANGUAGE CPP, DeriveFunctor, RankNTypes #-}
{-# OPTIONS_GHC -funbox-strict-fields #-}
module GhcMonad (
GhcMonad(..),
Ghc(..),
GhcT(..), liftGhcT,
reflectGhc, reifyGhc,
getSessionDynFlags,
liftIO,
Session(..), withSession, modifySession, withTempSession,
logWarnings, printException,
WarnErrLogger, defaultWarnErrLogger
) where
import GhcPrelude
import MonadUtils
import HscTypes
import DynFlags
import Exception
import ErrUtils
import Control.Monad
import Data.IORef
class (Functor m, MonadIO m, ExceptionMonad m, HasDynFlags m) => GhcMonad m where
getSession :: m HscEnv
setSession :: HscEnv -> m ()
withSession :: GhcMonad m => (HscEnv -> m a) -> m a
withSession :: (HscEnv -> m a) -> m a
withSession HscEnv -> m a
f = m HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession m HscEnv -> (HscEnv -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HscEnv -> m a
f
getSessionDynFlags :: GhcMonad m => m DynFlags
getSessionDynFlags :: m DynFlags
getSessionDynFlags = (HscEnv -> m DynFlags) -> m DynFlags
forall (m :: * -> *) a. GhcMonad m => (HscEnv -> m a) -> m a
withSession (DynFlags -> m DynFlags
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags -> m DynFlags)
-> (HscEnv -> DynFlags) -> HscEnv -> m DynFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HscEnv -> DynFlags
hsc_dflags)
modifySession :: GhcMonad m => (HscEnv -> HscEnv) -> m ()
modifySession :: (HscEnv -> HscEnv) -> m ()
modifySession HscEnv -> HscEnv
f = do HscEnv
h <- m HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
HscEnv -> m ()
forall (m :: * -> *). GhcMonad m => HscEnv -> m ()
setSession (HscEnv -> m ()) -> HscEnv -> m ()
forall a b. (a -> b) -> a -> b
$! HscEnv -> HscEnv
f HscEnv
h
withSavedSession :: GhcMonad m => m a -> m a
withSavedSession :: m a -> m a
withSavedSession m a
m = do
HscEnv
saved_session <- m HscEnv
forall (m :: * -> *). GhcMonad m => m HscEnv
getSession
m a
m m a -> m () -> m a
forall (m :: * -> *) a b. ExceptionMonad m => m a -> m b -> m a
`gfinally` HscEnv -> m ()
forall (m :: * -> *). GhcMonad m => HscEnv -> m ()
setSession HscEnv
saved_session
withTempSession :: GhcMonad m => (HscEnv -> HscEnv) -> m a -> m a
withTempSession :: (HscEnv -> HscEnv) -> m a -> m a
withTempSession HscEnv -> HscEnv
f m a
m =
m a -> m a
forall (m :: * -> *) a. GhcMonad m => m a -> m a
withSavedSession (m a -> m a) -> m a -> m a
forall a b. (a -> b) -> a -> b
$ (HscEnv -> HscEnv) -> m ()
forall (m :: * -> *). GhcMonad m => (HscEnv -> HscEnv) -> m ()
modifySession HscEnv -> HscEnv
f m () -> m a -> m a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m a
m
logWarnings :: GhcMonad m => WarningMessages -> m ()
logWarnings :: WarningMessages -> m ()
logWarnings WarningMessages
warns = do
DynFlags
dflags <- m DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getSessionDynFlags
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> WarningMessages -> IO ()
printOrThrowWarnings DynFlags
dflags WarningMessages
warns
newtype Ghc a = Ghc { Ghc a -> Session -> IO a
unGhc :: Session -> IO a } deriving (a -> Ghc b -> Ghc a
(a -> b) -> Ghc a -> Ghc b
(forall a b. (a -> b) -> Ghc a -> Ghc b)
-> (forall a b. a -> Ghc b -> Ghc a) -> Functor Ghc
forall a b. a -> Ghc b -> Ghc a
forall a b. (a -> b) -> Ghc a -> Ghc b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Ghc b -> Ghc a
$c<$ :: forall a b. a -> Ghc b -> Ghc a
fmap :: (a -> b) -> Ghc a -> Ghc b
$cfmap :: forall a b. (a -> b) -> Ghc a -> Ghc b
Functor)
data Session = Session !(IORef HscEnv)
instance Applicative Ghc where
pure :: a -> Ghc a
pure a
a = (Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ \Session
_ -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
Ghc (a -> b)
g <*> :: Ghc (a -> b) -> Ghc a -> Ghc b
<*> Ghc a
m = do a -> b
f <- Ghc (a -> b)
g; a
a <- Ghc a
m; b -> Ghc b
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> b
f a
a)
instance Monad Ghc where
Ghc a
m >>= :: Ghc a -> (a -> Ghc b) -> Ghc b
>>= a -> Ghc b
g = (Session -> IO b) -> Ghc b
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO b) -> Ghc b) -> (Session -> IO b) -> Ghc b
forall a b. (a -> b) -> a -> b
$ \Session
s -> do a
a <- Ghc a -> Session -> IO a
forall a. Ghc a -> Session -> IO a
unGhc Ghc a
m Session
s; Ghc b -> Session -> IO b
forall a. Ghc a -> Session -> IO a
unGhc (a -> Ghc b
g a
a) Session
s
instance MonadIO Ghc where
liftIO :: IO a -> Ghc a
liftIO IO a
ioA = (Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ \Session
_ -> IO a
ioA
instance MonadFix Ghc where
mfix :: (a -> Ghc a) -> Ghc a
mfix a -> Ghc a
f = (Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ \Session
s -> (a -> IO a) -> IO a
forall (m :: * -> *) a. MonadFix m => (a -> m a) -> m a
mfix (\a
x -> Ghc a -> Session -> IO a
forall a. Ghc a -> Session -> IO a
unGhc (a -> Ghc a
f a
x) Session
s)
instance ExceptionMonad Ghc where
gcatch :: Ghc a -> (e -> Ghc a) -> Ghc a
gcatch Ghc a
act e -> Ghc a
handle =
(Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ \Session
s -> Ghc a -> Session -> IO a
forall a. Ghc a -> Session -> IO a
unGhc Ghc a
act Session
s IO a -> (e -> IO a) -> IO a
forall (m :: * -> *) e a.
(ExceptionMonad m, Exception e) =>
m a -> (e -> m a) -> m a
`gcatch` \e
e -> Ghc a -> Session -> IO a
forall a. Ghc a -> Session -> IO a
unGhc (e -> Ghc a
handle e
e) Session
s
gmask :: ((Ghc a -> Ghc a) -> Ghc b) -> Ghc b
gmask (Ghc a -> Ghc a) -> Ghc b
f =
(Session -> IO b) -> Ghc b
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO b) -> Ghc b) -> (Session -> IO b) -> Ghc b
forall a b. (a -> b) -> a -> b
$ \Session
s -> ((IO a -> IO a) -> IO b) -> IO b
forall (m :: * -> *) a b.
ExceptionMonad m =>
((m a -> m a) -> m b) -> m b
gmask (((IO a -> IO a) -> IO b) -> IO b)
-> ((IO a -> IO a) -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \IO a -> IO a
io_restore ->
let
g_restore :: Ghc a -> Ghc a
g_restore (Ghc Session -> IO a
m) = (Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ \Session
s -> IO a -> IO a
io_restore (Session -> IO a
m Session
s)
in
Ghc b -> Session -> IO b
forall a. Ghc a -> Session -> IO a
unGhc ((Ghc a -> Ghc a) -> Ghc b
f Ghc a -> Ghc a
g_restore) Session
s
instance HasDynFlags Ghc where
getDynFlags :: Ghc DynFlags
getDynFlags = Ghc DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getSessionDynFlags
instance GhcMonad Ghc where
getSession :: Ghc HscEnv
getSession = (Session -> IO HscEnv) -> Ghc HscEnv
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO HscEnv) -> Ghc HscEnv)
-> (Session -> IO HscEnv) -> Ghc HscEnv
forall a b. (a -> b) -> a -> b
$ \(Session IORef HscEnv
r) -> IORef HscEnv -> IO HscEnv
forall a. IORef a -> IO a
readIORef IORef HscEnv
r
setSession :: HscEnv -> Ghc ()
setSession HscEnv
s' = (Session -> IO ()) -> Ghc ()
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO ()) -> Ghc ()) -> (Session -> IO ()) -> Ghc ()
forall a b. (a -> b) -> a -> b
$ \(Session IORef HscEnv
r) -> IORef HscEnv -> HscEnv -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef HscEnv
r HscEnv
s'
reflectGhc :: Ghc a -> Session -> IO a
reflectGhc :: Ghc a -> Session -> IO a
reflectGhc Ghc a
m = Ghc a -> Session -> IO a
forall a. Ghc a -> Session -> IO a
unGhc Ghc a
m
reifyGhc :: (Session -> IO a) -> Ghc a
reifyGhc :: (Session -> IO a) -> Ghc a
reifyGhc Session -> IO a
act = (Session -> IO a) -> Ghc a
forall a. (Session -> IO a) -> Ghc a
Ghc ((Session -> IO a) -> Ghc a) -> (Session -> IO a) -> Ghc a
forall a b. (a -> b) -> a -> b
$ Session -> IO a
act
newtype GhcT m a = GhcT { GhcT m a -> Session -> m a
unGhcT :: Session -> m a }
deriving (a -> GhcT m b -> GhcT m a
(a -> b) -> GhcT m a -> GhcT m b
(forall a b. (a -> b) -> GhcT m a -> GhcT m b)
-> (forall a b. a -> GhcT m b -> GhcT m a) -> Functor (GhcT m)
forall a b. a -> GhcT m b -> GhcT m a
forall a b. (a -> b) -> GhcT m a -> GhcT m b
forall (m :: * -> *) a b. Functor m => a -> GhcT m b -> GhcT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> GhcT m a -> GhcT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> GhcT m b -> GhcT m a
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> GhcT m b -> GhcT m a
fmap :: (a -> b) -> GhcT m a -> GhcT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> GhcT m a -> GhcT m b
Functor)
liftGhcT :: m a -> GhcT m a
liftGhcT :: m a -> GhcT m a
liftGhcT m a
m = (Session -> m a) -> GhcT m a
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m a) -> GhcT m a) -> (Session -> m a) -> GhcT m a
forall a b. (a -> b) -> a -> b
$ \Session
_ -> m a
m
instance Applicative m => Applicative (GhcT m) where
pure :: a -> GhcT m a
pure a
x = (Session -> m a) -> GhcT m a
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m a) -> GhcT m a) -> (Session -> m a) -> GhcT m a
forall a b. (a -> b) -> a -> b
$ \Session
_ -> a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x
GhcT m (a -> b)
g <*> :: GhcT m (a -> b) -> GhcT m a -> GhcT m b
<*> GhcT m a
m = (Session -> m b) -> GhcT m b
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m b) -> GhcT m b) -> (Session -> m b) -> GhcT m b
forall a b. (a -> b) -> a -> b
$ \Session
s -> GhcT m (a -> b) -> Session -> m (a -> b)
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT GhcT m (a -> b)
g Session
s m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GhcT m a -> Session -> m a
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT GhcT m a
m Session
s
instance Monad m => Monad (GhcT m) where
GhcT m a
m >>= :: GhcT m a -> (a -> GhcT m b) -> GhcT m b
>>= a -> GhcT m b
k = (Session -> m b) -> GhcT m b
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m b) -> GhcT m b) -> (Session -> m b) -> GhcT m b
forall a b. (a -> b) -> a -> b
$ \Session
s -> do a
a <- GhcT m a -> Session -> m a
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT GhcT m a
m Session
s; GhcT m b -> Session -> m b
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT (a -> GhcT m b
k a
a) Session
s
instance MonadIO m => MonadIO (GhcT m) where
liftIO :: IO a -> GhcT m a
liftIO IO a
ioA = (Session -> m a) -> GhcT m a
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m a) -> GhcT m a) -> (Session -> m a) -> GhcT m a
forall a b. (a -> b) -> a -> b
$ \Session
_ -> IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
ioA
instance ExceptionMonad m => ExceptionMonad (GhcT m) where
gcatch :: GhcT m a -> (e -> GhcT m a) -> GhcT m a
gcatch GhcT m a
act e -> GhcT m a
handle =
(Session -> m a) -> GhcT m a
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m a) -> GhcT m a) -> (Session -> m a) -> GhcT m a
forall a b. (a -> b) -> a -> b
$ \Session
s -> GhcT m a -> Session -> m a
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT GhcT m a
act Session
s m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(ExceptionMonad m, Exception e) =>
m a -> (e -> m a) -> m a
`gcatch` \e
e -> GhcT m a -> Session -> m a
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT (e -> GhcT m a
handle e
e) Session
s
gmask :: ((GhcT m a -> GhcT m a) -> GhcT m b) -> GhcT m b
gmask (GhcT m a -> GhcT m a) -> GhcT m b
f =
(Session -> m b) -> GhcT m b
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m b) -> GhcT m b) -> (Session -> m b) -> GhcT m b
forall a b. (a -> b) -> a -> b
$ \Session
s -> ((m a -> m a) -> m b) -> m b
forall (m :: * -> *) a b.
ExceptionMonad m =>
((m a -> m a) -> m b) -> m b
gmask (((m a -> m a) -> m b) -> m b) -> ((m a -> m a) -> m b) -> m b
forall a b. (a -> b) -> a -> b
$ \m a -> m a
io_restore ->
let
g_restore :: GhcT m a -> GhcT m a
g_restore (GhcT Session -> m a
m) = (Session -> m a) -> GhcT m a
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m a) -> GhcT m a) -> (Session -> m a) -> GhcT m a
forall a b. (a -> b) -> a -> b
$ \Session
s -> m a -> m a
io_restore (Session -> m a
m Session
s)
in
GhcT m b -> Session -> m b
forall (m :: * -> *) a. GhcT m a -> Session -> m a
unGhcT ((GhcT m a -> GhcT m a) -> GhcT m b
f GhcT m a -> GhcT m a
g_restore) Session
s
instance MonadIO m => HasDynFlags (GhcT m) where
getDynFlags :: GhcT m DynFlags
getDynFlags = (Session -> m DynFlags) -> GhcT m DynFlags
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m DynFlags) -> GhcT m DynFlags)
-> (Session -> m DynFlags) -> GhcT m DynFlags
forall a b. (a -> b) -> a -> b
$ \(Session IORef HscEnv
r) -> (HscEnv -> DynFlags) -> m HscEnv -> m DynFlags
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM HscEnv -> DynFlags
hsc_dflags (IO HscEnv -> m HscEnv
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HscEnv -> m HscEnv) -> IO HscEnv -> m HscEnv
forall a b. (a -> b) -> a -> b
$ IORef HscEnv -> IO HscEnv
forall a. IORef a -> IO a
readIORef IORef HscEnv
r)
instance ExceptionMonad m => GhcMonad (GhcT m) where
getSession :: GhcT m HscEnv
getSession = (Session -> m HscEnv) -> GhcT m HscEnv
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m HscEnv) -> GhcT m HscEnv)
-> (Session -> m HscEnv) -> GhcT m HscEnv
forall a b. (a -> b) -> a -> b
$ \(Session IORef HscEnv
r) -> IO HscEnv -> m HscEnv
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HscEnv -> m HscEnv) -> IO HscEnv -> m HscEnv
forall a b. (a -> b) -> a -> b
$ IORef HscEnv -> IO HscEnv
forall a. IORef a -> IO a
readIORef IORef HscEnv
r
setSession :: HscEnv -> GhcT m ()
setSession HscEnv
s' = (Session -> m ()) -> GhcT m ()
forall (m :: * -> *) a. (Session -> m a) -> GhcT m a
GhcT ((Session -> m ()) -> GhcT m ()) -> (Session -> m ()) -> GhcT m ()
forall a b. (a -> b) -> a -> b
$ \(Session IORef HscEnv
r) -> IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef HscEnv -> HscEnv -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef HscEnv
r HscEnv
s'
printException :: GhcMonad m => SourceError -> m ()
printException :: SourceError -> m ()
printException SourceError
err = do
DynFlags
dflags <- m DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
getSessionDynFlags
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> WarningMessages -> IO ()
printBagOfErrors DynFlags
dflags (SourceError -> WarningMessages
srcErrorMessages SourceError
err)
type WarnErrLogger = forall m. GhcMonad m => Maybe SourceError -> m ()
defaultWarnErrLogger :: WarnErrLogger
defaultWarnErrLogger :: Maybe SourceError -> m ()
defaultWarnErrLogger Maybe SourceError
Nothing = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
defaultWarnErrLogger (Just SourceError
e) = SourceError -> m ()
forall (m :: * -> *). GhcMonad m => SourceError -> m ()
printException SourceError
e