From a45bfb97b94a046a9bd83cab6b03910af83a496c Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Sat, 24 Aug 2013 19:17:33 +0200 Subject: [PATCH 1/2] Exposing lower level API using GhcMonad --- Language/Haskell/GhcMod/GHCApi.hs | 16 +++++------ Language/Haskell/GhcMod/GHCChoice.hs | 3 ++ Language/Haskell/GhcModLowLevel.hs | 41 ++++++++++++++++++++++++++++ ghc-mod.cabal | 1 + 4 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 Language/Haskell/GhcModLowLevel.hs diff --git a/Language/Haskell/GhcMod/GHCApi.hs b/Language/Haskell/GhcMod/GHCApi.hs index a96c2d6..0cd27e7 100644 --- a/Language/Haskell/GhcMod/GHCApi.hs +++ b/Language/Haskell/GhcMod/GHCApi.hs @@ -57,9 +57,9 @@ importDirs = [".","..","../..","../../..","../../../..","../../../../.."] data Build = CabalPkg | SingleFile deriving Eq -initializeFlagsWithCradle :: Options -> Cradle -> [GHCOption] -> Bool -> Ghc LogReader +initializeFlagsWithCradle :: GhcMonad m => Options -> Cradle -> [GHCOption] -> Bool -> m LogReader initializeFlagsWithCradle opt cradle ghcOptions logging - | cabal = withCabal ||> withoutCabal + | cabal = withCabal |||> withoutCabal | otherwise = withoutCabal where cabal = isJust $ cradleCabalFile cradle @@ -71,13 +71,13 @@ initializeFlagsWithCradle opt cradle ghcOptions logging ---------------------------------------------------------------- -initSession :: Build +initSession :: GhcMonad m => Build -> Options -> [GHCOption] -> [IncludeDir] -> Maybe [Package] -> Bool - -> Ghc LogReader + -> m LogReader initSession build opt cmdOpts idirs mDepPkgs logging = do dflags0 <- getSessionDynFlags (dflags1,readLog) <- setupDynamicFlags dflags0 @@ -92,7 +92,7 @@ initSession build opt cmdOpts idirs mDepPkgs logging = do ---------------------------------------------------------------- -initializeFlags :: Options -> Ghc () +initializeFlags :: GhcMonad m => Options -> m () initializeFlags opt = do dflags0 <- getSessionDynFlags dflags1 <- modifyFlagsWithOpts dflags0 $ ghcOpts opt @@ -127,7 +127,7 @@ setFastOrNot dflags Fast = dflags { , hscTarget = HscNothing } -setSlowDynFlags :: Ghc () +setSlowDynFlags :: GhcMonad m => m () setSlowDynFlags = (flip setFastOrNot Slow <$> getSessionDynFlags) >>= void . setSessionDynFlags @@ -135,14 +135,14 @@ setSlowDynFlags = (flip setFastOrNot Slow <$> getSessionDynFlags) -- "load" sets a session module graph using "depanal". -- But we have to set "-fno-code" to DynFlags before "load". -- So, this is necessary redundancy. -checkSlowAndSet :: Ghc () +checkSlowAndSet :: GhcMonad m => m () checkSlowAndSet = do fast <- canCheckFast <$> depanal [] False unless fast setSlowDynFlags ---------------------------------------------------------------- -modifyFlagsWithOpts :: DynFlags -> [String] -> Ghc DynFlags +modifyFlagsWithOpts :: GhcMonad m => DynFlags -> [String] -> m DynFlags modifyFlagsWithOpts dflags cmdOpts = tfst <$> parseDynamicFlags dflags (map noLoc cmdOpts) where diff --git a/Language/Haskell/GhcMod/GHCChoice.hs b/Language/Haskell/GhcMod/GHCChoice.hs index 0345a7e..4bad3f0 100644 --- a/Language/Haskell/GhcMod/GHCChoice.hs +++ b/Language/Haskell/GhcMod/GHCChoice.hs @@ -12,6 +12,9 @@ import GHC (||>) :: Ghc a -> Ghc a -> Ghc a x ||> y = x `gcatch` (\(_ :: IOException) -> y) +(|||>) :: GhcMonad m => m a -> m a -> m a +x |||> y = x `gcatch` (\(_ :: IOException) -> y) + ---------------------------------------------------------------- {-| Go to the next 'Ghc' monad by throwing 'AltGhcgoNext'. diff --git a/Language/Haskell/GhcModLowLevel.hs b/Language/Haskell/GhcModLowLevel.hs new file mode 100644 index 0000000..5950a1e --- /dev/null +++ b/Language/Haskell/GhcModLowLevel.hs @@ -0,0 +1,41 @@ +-- | Low level access to the ghc-mod library. + +module Language.Haskell.GhcModLowLevel ( + -- * Cradle + Cradle(..) + , findCradle + -- * GHC version + , GHCVersion + , getGHCVersion + -- * Options + , Options(..) + , OutputStyle(..) + , defaultOptions + -- * Types + , ModuleString + , Expression + -- * Converting the 'Ghc' monad to the 'IO' monad + , withGHC + , withGHCDummyFile + -- * Low level access + , LogReader + , GHCOption + , initializeFlagsWithCradle + , setTargetFile + , checkSlowAndSet + , getDynamicFlags + ) where + +import Language.Haskell.GhcMod.Browse +import Language.Haskell.GhcMod.Check +import Language.Haskell.GhcMod.Cradle +import Language.Haskell.GhcMod.Debug +import Language.Haskell.GhcMod.ErrMsg +import Language.Haskell.GhcMod.Flag +import Language.Haskell.GhcMod.GHCApi +import Language.Haskell.GhcMod.Info +import Language.Haskell.GhcMod.Lang +import Language.Haskell.GhcMod.Lint +import Language.Haskell.GhcMod.List +import Language.Haskell.GhcMod.Types +import Language.Haskell.GhcMod.CabalApi diff --git a/ghc-mod.cabal b/ghc-mod.cabal index d38cda4..f27bbd4 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -40,6 +40,7 @@ Library Default-Language: Haskell2010 GHC-Options: -Wall Exposed-Modules: Language.Haskell.GhcMod + Language.Haskell.GhcModLowLevel Other-Modules: Language.Haskell.GhcMod.Browse Language.Haskell.GhcMod.CabalApi Language.Haskell.GhcMod.Check From e487a535eb5d1cb80c4425493e5595e8f75b0404 Mon Sep 17 00:00:00 2001 From: Alan Zimmerman Date: Mon, 26 Aug 2013 18:28:21 +0200 Subject: [PATCH 2/2] Rename GhcModLowLevel to GhcMod.Internal and document exposed items. --- Language/Haskell/GhcMod/ErrMsg.hs | 1 + Language/Haskell/GhcMod/GHCApi.hs | 7 ++++- Language/Haskell/GhcMod/Internal.hs | 16 +++++++++++ Language/Haskell/GhcMod/Types.hs | 2 ++ Language/Haskell/GhcModLowLevel.hs | 41 ----------------------------- ghc-mod.cabal | 2 +- 6 files changed, 26 insertions(+), 43 deletions(-) create mode 100644 Language/Haskell/GhcMod/Internal.hs delete mode 100644 Language/Haskell/GhcModLowLevel.hs diff --git a/Language/Haskell/GhcMod/ErrMsg.hs b/Language/Haskell/GhcMod/ErrMsg.hs index cdf363a..5a2e485 100644 --- a/Language/Haskell/GhcMod/ErrMsg.hs +++ b/Language/Haskell/GhcMod/ErrMsg.hs @@ -21,6 +21,7 @@ import System.FilePath (normalise) ---------------------------------------------------------------- +-- | A means to read the log type LogReader = IO [String] ---------------------------------------------------------------- diff --git a/Language/Haskell/GhcMod/GHCApi.hs b/Language/Haskell/GhcMod/GHCApi.hs index 0cd27e7..197b131 100644 --- a/Language/Haskell/GhcMod/GHCApi.hs +++ b/Language/Haskell/GhcMod/GHCApi.hs @@ -57,6 +57,9 @@ importDirs = [".","..","../..","../../..","../../../..","../../../../.."] data Build = CabalPkg | SingleFile deriving Eq +-- | Initialize the 'DynFlags' relating to the compilation of a single +-- file or GHC session according to the 'Cradle' and 'Options' +-- provided. initializeFlagsWithCradle :: GhcMonad m => Options -> Cradle -> [GHCOption] -> Bool -> m LogReader initializeFlagsWithCradle opt cradle ghcOptions logging | cabal = withCabal |||> withoutCabal @@ -131,7 +134,7 @@ setSlowDynFlags :: GhcMonad m => m () setSlowDynFlags = (flip setFastOrNot Slow <$> getSessionDynFlags) >>= void . setSessionDynFlags --- To check TH, a session module graph is necessary. +-- | To check TH, a session module graph is necessary. -- "load" sets a session module graph using "depanal". -- But we have to set "-fno-code" to DynFlags before "load". -- So, this is necessary redundancy. @@ -150,6 +153,7 @@ modifyFlagsWithOpts dflags cmdOpts = ---------------------------------------------------------------- +-- | Set the file that GHC will load / compile setTargetFile :: (GhcMonad m) => String -> m () setTargetFile file = do target <- guessTarget file Nothing @@ -157,6 +161,7 @@ setTargetFile file = do ---------------------------------------------------------------- +-- | Return the 'DynFlags' currently in use in the GHC session getDynamicFlags :: IO DynFlags getDynamicFlags = runGhc (Just libdir) getSessionDynFlags diff --git a/Language/Haskell/GhcMod/Internal.hs b/Language/Haskell/GhcMod/Internal.hs new file mode 100644 index 0000000..b709495 --- /dev/null +++ b/Language/Haskell/GhcMod/Internal.hs @@ -0,0 +1,16 @@ +-- | Low level access to the ghc-mod library. + +module Language.Haskell.GhcMod.Internal ( + -- * Low level access + LogReader + , GHCOption + , initializeFlagsWithCradle + , setTargetFile + , checkSlowAndSet + , getDynamicFlags + ) where + +import Language.Haskell.GhcMod.ErrMsg +import Language.Haskell.GhcMod.GHCApi +import Language.Haskell.GhcMod.Types + diff --git a/Language/Haskell/GhcMod/Types.hs b/Language/Haskell/GhcMod/Types.hs index f32b769..6179f6a 100644 --- a/Language/Haskell/GhcMod/Types.hs +++ b/Language/Haskell/GhcMod/Types.hs @@ -84,7 +84,9 @@ data Cradle = Cradle { ---------------------------------------------------------------- +-- | A single GHC option, as it would appear on the command line type GHCOption = String + type IncludeDir = FilePath type Package = String diff --git a/Language/Haskell/GhcModLowLevel.hs b/Language/Haskell/GhcModLowLevel.hs deleted file mode 100644 index 5950a1e..0000000 --- a/Language/Haskell/GhcModLowLevel.hs +++ /dev/null @@ -1,41 +0,0 @@ --- | Low level access to the ghc-mod library. - -module Language.Haskell.GhcModLowLevel ( - -- * Cradle - Cradle(..) - , findCradle - -- * GHC version - , GHCVersion - , getGHCVersion - -- * Options - , Options(..) - , OutputStyle(..) - , defaultOptions - -- * Types - , ModuleString - , Expression - -- * Converting the 'Ghc' monad to the 'IO' monad - , withGHC - , withGHCDummyFile - -- * Low level access - , LogReader - , GHCOption - , initializeFlagsWithCradle - , setTargetFile - , checkSlowAndSet - , getDynamicFlags - ) where - -import Language.Haskell.GhcMod.Browse -import Language.Haskell.GhcMod.Check -import Language.Haskell.GhcMod.Cradle -import Language.Haskell.GhcMod.Debug -import Language.Haskell.GhcMod.ErrMsg -import Language.Haskell.GhcMod.Flag -import Language.Haskell.GhcMod.GHCApi -import Language.Haskell.GhcMod.Info -import Language.Haskell.GhcMod.Lang -import Language.Haskell.GhcMod.Lint -import Language.Haskell.GhcMod.List -import Language.Haskell.GhcMod.Types -import Language.Haskell.GhcMod.CabalApi diff --git a/ghc-mod.cabal b/ghc-mod.cabal index f27bbd4..f1c359e 100644 --- a/ghc-mod.cabal +++ b/ghc-mod.cabal @@ -40,7 +40,7 @@ Library Default-Language: Haskell2010 GHC-Options: -Wall Exposed-Modules: Language.Haskell.GhcMod - Language.Haskell.GhcModLowLevel + Language.Haskell.GhcMod.Internal Other-Modules: Language.Haskell.GhcMod.Browse Language.Haskell.GhcMod.CabalApi Language.Haskell.GhcMod.Check