module Hint.Configuration (
setGhcOption, setGhcOptions,
defaultConf, fromConf, onConf,
get, set, Option, OptionVal(..),
languageExtensions, availableExtensions, glasgowExtensions, Extension(..),
installedModulesInScope,
setUseLanguageExtensions,
setInstalledModsAreInScopeQualified,
searchPath
) where
import Control.Monad.Error
import Data.Char
import Data.List ( intersect, intercalate )
import qualified Hint.GHC as GHC
import qualified Hint.Compat as Compat
import Hint.Base
import Hint.Util ( partition )
import Hint.Extension
setGhcOptions :: MonadInterpreter m => [String] -> m ()
setGhcOptions opts =
do old_flags <- runGhc GHC.getSessionDynFlags
(new_flags,not_parsed) <- runGhc2 Compat.parseDynamicFlags old_flags opts
when (not . null $ not_parsed) $
throwError $ UnknownError (concat ["flag: '", unwords opts,
"' not recognized"])
runGhc1 GHC.setSessionDynFlags new_flags
return ()
setGhcOption :: MonadInterpreter m => String -> m ()
setGhcOption opt = setGhcOptions [opt]
defaultConf :: InterpreterConfiguration
defaultConf = Conf {
language_exts = [],
all_mods_in_scope = False,
search_path = ["."]
}
data Option m a = Option{_set :: MonadInterpreter m => a -> m (),
_get :: MonadInterpreter m => m a}
data OptionVal m = forall a . (Option m a) := a
set :: MonadInterpreter m => [OptionVal m] -> m ()
set = mapM_ $ \(opt := val) -> _set opt val
get :: MonadInterpreter m => Option m a -> m a
get = _get
languageExtensions :: MonadInterpreter m => Option m [Extension]
languageExtensions = Option setter getter
where setter es = do setGhcOptions $ map (mkFlag False) availableExtensions
setGhcOptions $ map (mkFlag True) es
onConf $ \c -> c{language_exts = es}
getter = fromConf language_exts
mkFlag b (UnknownExtension o) = "-X" ++ concat ["No"|not b] ++ o
mkFlag b o
| ('N':'o':c:_) <- show o,
isUpper c = if b
then "-X" ++ show o
else "-X" ++ (drop 2 $ show o)
| otherwise = "-X" ++ concat ["No"|not b] ++ show o
availableExtensions :: [Extension]
availableExtensions = asExtensionList GHC.supportedLanguages
asExtensionList :: [String] -> [Extension]
asExtensionList exts = map read knownPos ++
map read (map ("No" ++) knownNegs) ++
map UnknownExtension unknown
where (knownPos, unknownPos) = partition isKnown exts
(knownNegs,unknown) = partition (isKnown . ("No" ++)) unknownPos
isKnown e = e `elem` map show knownExtensions
glasgowExtensions :: [Extension]
glasgowExtensions = intersect availableExtensions exts610
where exts610 = asExtensionList ["ForeignFunctionInterface",
"UnliftedFFITypes",
"GADTs",
"ImplicitParams",
"ScopedTypeVariables",
"UnboxedTuples",
"TypeSynonymInstances",
"StandaloneDeriving",
"DeriveDataTypeable",
"FlexibleContexts",
"FlexibleInstances",
"ConstrainedClassMethods",
"MultiParamTypeClasses",
"FunctionalDependencies",
"MagicHash",
"PolymorphicComponents",
"ExistentialQuantification",
"UnicodeSyntax",
"PostfixOperators",
"PatternGuards",
"LiberalTypeSynonyms",
"RankNTypes",
"ImpredicativeTypes",
"TypeOperators",
"RecursiveDo",
"ParallelListComp",
"EmptyDataDecls",
"KindSignatures",
"GeneralizedNewtypeDeriving",
"TypeFamilies" ]
installedModulesInScope :: MonadInterpreter m => Option m Bool
installedModulesInScope = Option setter getter
where getter = fromConf all_mods_in_scope
setter b = do onConf $ \c -> c{all_mods_in_scope = b}
when ( ghcVersion >= 610 ) $
setGhcOption $ "-f" ++
concat ["no-" | not b] ++
"implicit-import-qualified"
searchPath :: MonadInterpreter m => Option m [FilePath]
searchPath = Option setter getter
where getter = fromConf search_path
setter p = do onConf $ \c -> c{search_path = p}
setGhcOption $ "-i"
setGhcOption $ "-i" ++ intercalate ":" p
fromConf :: MonadInterpreter m => (InterpreterConfiguration -> a) -> m a
fromConf f = fromState (f . configuration)
onConf :: MonadInterpreter m
=> (InterpreterConfiguration -> InterpreterConfiguration)
-> m ()
onConf f = onState $ \st -> st{configuration = f (configuration st)}
setUseLanguageExtensions :: MonadInterpreter m => Bool -> m ()
setUseLanguageExtensions False = set [languageExtensions := []]
setUseLanguageExtensions True = set [languageExtensions := exts]
where exts = ExtendedDefaultRules : glasgowExtensions
setInstalledModsAreInScopeQualified :: MonadInterpreter m => Bool -> m ()
setInstalledModsAreInScopeQualified b = set [installedModulesInScope := b]