module Hint.Configuration (
setGhcOption, setGhcOptions,
defaultConf,
get, set, Option, OptionVal(..),
languageExtensions, availableExtensions, Extension(..),
installedModulesInScope,
searchPath,
configureDynFlags, parseDynamicFlags,
) where
import Control.Monad
import Control.Monad.Catch
import Data.Char
import Data.Maybe (maybe)
import Data.List (intercalate)
import qualified Hint.GHC as GHC
import Hint.Base
import Hint.Util (quote)
import Hint.Extension
setGhcOptions :: MonadInterpreter m => [String] -> m ()
setGhcOptions :: [String] -> m ()
setGhcOptions [String]
opts =
do DynFlags
old_flags <- RunGhc m DynFlags
forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
runGhc forall (n :: * -> *). (MonadIO n, MonadMask n) => GhcT n DynFlags
forall (m :: * -> *). GhcMonad m => m DynFlags
GHC.getSessionDynFlags
Logger
logger <- FromSession m Logger
forall (m :: * -> *) a. MonadInterpreter m => FromSession m a
fromSession SessionData () -> Logger
forall a. SessionData a -> Logger
ghcLogger
(DynFlags
new_flags,[String]
not_parsed) <- RunGhc m (DynFlags, [String])
forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
runGhc RunGhc m (DynFlags, [String]) -> RunGhc m (DynFlags, [String])
forall a b. (a -> b) -> a -> b
$ Logger -> DynFlags -> [String] -> GhcT n (DynFlags, [String])
forall (m :: * -> *).
GhcMonad m =>
Logger -> DynFlags -> [String] -> m (DynFlags, [String])
parseDynamicFlags Logger
logger DynFlags
old_flags [String]
opts
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
not_parsed) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
InterpreterError -> m ()
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (InterpreterError -> m ()) -> InterpreterError -> m ()
forall a b. (a -> b) -> a -> b
$ String -> InterpreterError
UnknownError
(String -> InterpreterError) -> String -> InterpreterError
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"flags: ", [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
quote [String]
not_parsed,
String
"not recognized"]
[InstalledUnitId]
_ <- RunGhc m [InstalledUnitId]
forall (m :: * -> *) a. MonadInterpreter m => RunGhc m a
runGhc RunGhc m [InstalledUnitId] -> RunGhc m [InstalledUnitId]
forall a b. (a -> b) -> a -> b
$ DynFlags -> GhcT n [InstalledUnitId]
forall (m :: * -> *). GhcMonad m => DynFlags -> m [InstalledUnitId]
GHC.setSessionDynFlags DynFlags
new_flags
() -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
setGhcOption :: MonadInterpreter m => String -> m ()
setGhcOption :: String -> m ()
setGhcOption String
opt = [String] -> m ()
forall (m :: * -> *). MonadInterpreter m => [String] -> m ()
setGhcOptions [String
opt]
defaultConf :: InterpreterConfiguration
defaultConf :: InterpreterConfiguration
defaultConf = Conf :: [String] -> [Extension] -> Bool -> InterpreterConfiguration
Conf {
languageExts :: [Extension]
languageExts = [],
allModsInScope :: Bool
allModsInScope = Bool
False,
searchFilePath :: [String]
searchFilePath = [String
"."]
}
data Option m a = Option{
Option m a -> MonadInterpreter m => a -> m ()
_set :: MonadInterpreter m => a -> m (),
Option m a -> MonadInterpreter m => m a
_get :: MonadInterpreter m => m a
}
data OptionVal m = forall a . (Option m a) := a
set :: MonadInterpreter m => [OptionVal m] -> m ()
set :: [OptionVal m] -> m ()
set = (OptionVal m -> m ()) -> [OptionVal m] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((OptionVal m -> m ()) -> [OptionVal m] -> m ())
-> (OptionVal m -> m ()) -> [OptionVal m] -> m ()
forall a b. (a -> b) -> a -> b
$ \(Option m a
opt := a
val) -> Option m a -> a -> m ()
forall (m :: * -> *) a.
Option m a -> MonadInterpreter m => a -> m ()
_set Option m a
opt a
val
get :: MonadInterpreter m => Option m a -> m a
get :: Option m a -> m a
get = \Option m a
o -> Option m a -> MonadInterpreter m => m a
forall (m :: * -> *) a. Option m a -> MonadInterpreter m => m a
_get Option m a
o
languageExtensions :: MonadInterpreter m => Option m [Extension]
languageExtensions :: Option m [Extension]
languageExtensions = (MonadInterpreter m => [Extension] -> m ())
-> (MonadInterpreter m => m [Extension]) -> Option m [Extension]
forall (m :: * -> *) a.
(MonadInterpreter m => a -> m ())
-> (MonadInterpreter m => m a) -> Option m a
Option [Extension] -> m ()
MonadInterpreter m => [Extension] -> m ()
setter m [Extension]
MonadInterpreter m => m [Extension]
getter
where setter :: [Extension] -> m ()
setter [Extension]
es = do m ()
resetExtensions
[String] -> m ()
forall (m :: * -> *). MonadInterpreter m => [String] -> m ()
setGhcOptions ([String] -> m ()) -> [String] -> m ()
forall a b. (a -> b) -> a -> b
$ (Extension -> String) -> [Extension] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> Extension -> String
extFlag Bool
True) [Extension]
es
(InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall (m :: * -> *).
MonadInterpreter m =>
(InterpreterConfiguration -> InterpreterConfiguration) -> m ()
onConf ((InterpreterConfiguration -> InterpreterConfiguration) -> m ())
-> (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall a b. (a -> b) -> a -> b
$ \InterpreterConfiguration
c -> InterpreterConfiguration
c{languageExts :: [Extension]
languageExts = [Extension]
es}
getter :: m [Extension]
getter = (InterpreterConfiguration -> [Extension]) -> m [Extension]
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterConfiguration -> a) -> m a
fromConf InterpreterConfiguration -> [Extension]
languageExts
resetExtensions :: m ()
resetExtensions = do [(Extension, Bool)]
es <- (InterpreterState -> [(Extension, Bool)]) -> m [(Extension, Bool)]
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterState -> a) -> m a
fromState InterpreterState -> [(Extension, Bool)]
defaultExts
[String] -> m ()
forall (m :: * -> *). MonadInterpreter m => [String] -> m ()
setGhcOptions ([String] -> m ()) -> [String] -> m ()
forall a b. (a -> b) -> a -> b
$ (Extension -> Bool -> String) -> (Extension, Bool) -> String
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((Bool -> Extension -> String) -> Extension -> Bool -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip Bool -> Extension -> String
extFlag) ((Extension, Bool) -> String) -> [(Extension, Bool)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Extension, Bool)]
es
extFlag :: Bool -> Extension -> String
extFlag :: Bool -> Extension -> String
extFlag = Bool -> Extension -> String
mkFlag
where mkFlag :: Bool -> Extension -> String
mkFlag Bool
b (UnknownExtension String
o) = Bool -> String -> String
strToFlag Bool
b String
o
mkFlag Bool
b Extension
o = Bool -> String -> String
strToFlag Bool
b (Extension -> String
forall a. Show a => a -> String
show Extension
o)
strToFlag :: Bool -> String -> String
strToFlag Bool
b o :: String
o@(Char
'N':Char
'o':(Char
c:String
_))
| Char -> Bool
isUpper Char
c = String
"-X" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String -> String
forall a. Int -> [a] -> [a]
drop (if Bool
b then Int
0 else Int
2) String
o
strToFlag Bool
b String
o = String
"-X" String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"No"|Bool -> Bool
not Bool
b] String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
o
installedModulesInScope :: MonadInterpreter m => Option m Bool
installedModulesInScope :: Option m Bool
installedModulesInScope = (MonadInterpreter m => Bool -> m ())
-> (MonadInterpreter m => m Bool) -> Option m Bool
forall (m :: * -> *) a.
(MonadInterpreter m => a -> m ())
-> (MonadInterpreter m => m a) -> Option m a
Option MonadInterpreter m => Bool -> m ()
forall (m :: * -> *). MonadInterpreter m => Bool -> m ()
setter m Bool
MonadInterpreter m => m Bool
getter
where getter :: m Bool
getter = (InterpreterConfiguration -> Bool) -> m Bool
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterConfiguration -> a) -> m a
fromConf InterpreterConfiguration -> Bool
allModsInScope
setter :: Bool -> m ()
setter Bool
b = do (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall (m :: * -> *).
MonadInterpreter m =>
(InterpreterConfiguration -> InterpreterConfiguration) -> m ()
onConf ((InterpreterConfiguration -> InterpreterConfiguration) -> m ())
-> (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall a b. (a -> b) -> a -> b
$ \InterpreterConfiguration
c -> InterpreterConfiguration
c{allModsInScope :: Bool
allModsInScope = Bool
b}
String -> m ()
forall (m :: * -> *). MonadInterpreter m => String -> m ()
setGhcOption (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"-f" String -> String -> String
forall a. [a] -> [a] -> [a]
++
[String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"no-" | Bool -> Bool
not Bool
b] String -> String -> String
forall a. [a] -> [a] -> [a]
++
String
"implicit-import-qualified"
searchPath :: MonadInterpreter m => Option m [FilePath]
searchPath :: Option m [String]
searchPath = (MonadInterpreter m => [String] -> m ())
-> (MonadInterpreter m => m [String]) -> Option m [String]
forall (m :: * -> *) a.
(MonadInterpreter m => a -> m ())
-> (MonadInterpreter m => m a) -> Option m a
Option MonadInterpreter m => [String] -> m ()
forall (m :: * -> *). MonadInterpreter m => [String] -> m ()
setter m [String]
MonadInterpreter m => m [String]
getter
where getter :: m [String]
getter = (InterpreterConfiguration -> [String]) -> m [String]
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterConfiguration -> a) -> m a
fromConf InterpreterConfiguration -> [String]
searchFilePath
setter :: [String] -> m ()
setter [String]
p = do (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall (m :: * -> *).
MonadInterpreter m =>
(InterpreterConfiguration -> InterpreterConfiguration) -> m ()
onConf ((InterpreterConfiguration -> InterpreterConfiguration) -> m ())
-> (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
forall a b. (a -> b) -> a -> b
$ \InterpreterConfiguration
c -> InterpreterConfiguration
c{searchFilePath :: [String]
searchFilePath = [String]
p}
String -> m ()
forall (m :: * -> *). MonadInterpreter m => String -> m ()
setGhcOption String
"-i"
String -> m ()
forall (m :: * -> *). MonadInterpreter m => String -> m ()
setGhcOption (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"-i" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
":" [String]
p
Maybe String
mfp <- (InterpreterState -> Maybe String) -> m (Maybe String)
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterState -> a) -> m a
fromState InterpreterState -> Maybe String
phantomDirectory
m () -> (String -> m ()) -> Maybe String -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
(\String
fp -> String -> m ()
forall (m :: * -> *). MonadInterpreter m => String -> m ()
setGhcOption (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"-i" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fp) Maybe String
mfp
fromConf :: MonadInterpreter m => (InterpreterConfiguration -> a) -> m a
fromConf :: (InterpreterConfiguration -> a) -> m a
fromConf InterpreterConfiguration -> a
f = (InterpreterState -> a) -> m a
forall (m :: * -> *) a.
MonadInterpreter m =>
(InterpreterState -> a) -> m a
fromState (InterpreterConfiguration -> a
f (InterpreterConfiguration -> a)
-> (InterpreterState -> InterpreterConfiguration)
-> InterpreterState
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InterpreterState -> InterpreterConfiguration
configuration)
onConf :: MonadInterpreter m
=> (InterpreterConfiguration -> InterpreterConfiguration)
-> m ()
onConf :: (InterpreterConfiguration -> InterpreterConfiguration) -> m ()
onConf InterpreterConfiguration -> InterpreterConfiguration
f = (InterpreterState -> InterpreterState) -> m ()
forall (m :: * -> *).
MonadInterpreter m =>
(InterpreterState -> InterpreterState) -> m ()
onState ((InterpreterState -> InterpreterState) -> m ())
-> (InterpreterState -> InterpreterState) -> m ()
forall a b. (a -> b) -> a -> b
$ \InterpreterState
st -> InterpreterState
st{configuration :: InterpreterConfiguration
configuration = InterpreterConfiguration -> InterpreterConfiguration
f (InterpreterState -> InterpreterConfiguration
configuration InterpreterState
st)}
configureDynFlags :: GHC.DynFlags -> GHC.DynFlags
configureDynFlags :: DynFlags -> DynFlags
configureDynFlags DynFlags
dflags =
(if Bool
GHC.dynamicGhc then Way -> DynFlags -> DynFlags
GHC.addWay Way
GHC.WayDyn else DynFlags -> DynFlags
forall a. a -> a
id)
(DynFlags -> DynFlags)
-> (DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> DynFlags
GHC.setBackendToInterpreter
(DynFlags -> DynFlags) -> DynFlags -> DynFlags
forall a b. (a -> b) -> a -> b
$
DynFlags
dflags{ghcMode :: GhcMode
GHC.ghcMode = GhcMode
GHC.CompManager,
ghcLink :: GhcLink
GHC.ghcLink = GhcLink
GHC.LinkInMemory,
verbosity :: Int
GHC.verbosity = Int
0}
parseDynamicFlags :: GHC.GhcMonad m
=> GHC.Logger -> GHC.DynFlags -> [String] -> m (GHC.DynFlags, [String])
parseDynamicFlags :: Logger -> DynFlags -> [String] -> m (DynFlags, [String])
parseDynamicFlags Logger
l DynFlags
d = ((DynFlags, [Located String], [Warn]) -> (DynFlags, [String]))
-> m (DynFlags, [Located String], [Warn]) -> m (DynFlags, [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (DynFlags, [Located String], [Warn]) -> (DynFlags, [String])
forall a a c. HasSrcSpan a => (a, [a], c) -> (a, [SrcSpanLess a])
firstTwo (m (DynFlags, [Located String], [Warn]) -> m (DynFlags, [String]))
-> ([String] -> m (DynFlags, [Located String], [Warn]))
-> [String]
-> m (DynFlags, [String])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Logger
-> DynFlags
-> [Located String]
-> m (DynFlags, [Located String], [Warn])
forall (m :: * -> *).
MonadIO m =>
Logger
-> DynFlags
-> [Located String]
-> m (DynFlags, [Located String], [Warn])
GHC.parseDynamicFlags Logger
l DynFlags
d ([Located String] -> m (DynFlags, [Located String], [Warn]))
-> ([String] -> [Located String])
-> [String]
-> m (DynFlags, [Located String], [Warn])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Located String) -> [String] -> [Located String]
forall a b. (a -> b) -> [a] -> [b]
map String -> Located String
forall a. HasSrcSpan a => SrcSpanLess a -> a
GHC.noLoc
where firstTwo :: (a, [a], c) -> (a, [SrcSpanLess a])
firstTwo (a
a,[a]
b,c
_) = (a
a, (a -> SrcSpanLess a) -> [a] -> [SrcSpanLess a]
forall a b. (a -> b) -> [a] -> [b]
map a -> SrcSpanLess a
forall a. HasSrcSpan a => a -> SrcSpanLess a
GHC.unLoc [a]
b)