ghc-simple 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+132/−86 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Language.Haskell.GHC.Simple: class Compile a
- Language.Haskell.GHC.Simple: genericCompile :: (DynFlags -> ModSummary -> Ghc a) -> CompConfig -> [String] -> IO (CompResult a)
+ Language.Haskell.GHC.Simple: compileFold :: CompConfig b -> (a -> CompiledModule b -> IO a) -> a -> [String] -> IO (CompResult a)
+ Language.Haskell.GHC.Simple: getDynFlagsForConfig :: CompConfig a -> IO (DynFlags, [String])
+ Language.Haskell.GHC.Simple.Types: cfgGhcPipeline :: CompConfig a -> ModSummary -> Ghc a
+ Language.Haskell.GHC.Simple.Types: class Compile a
+ Language.Haskell.GHC.Simple.Types: toCode :: Compile a => ModSummary -> Ghc a
- Language.Haskell.GHC.Simple: compile :: Compile a => [String] -> IO (CompResult a)
+ Language.Haskell.GHC.Simple: compile :: Compile a => [String] -> IO (CompResult [CompiledModule a])
- Language.Haskell.GHC.Simple: compileWith :: Compile a => CompConfig -> [String] -> IO (CompResult a)
+ Language.Haskell.GHC.Simple: compileWith :: Compile a => CompConfig a -> [String] -> IO (CompResult [CompiledModule a])
- Language.Haskell.GHC.Simple.Impl: toCode :: Compile a => DynFlags -> ModSummary -> Ghc a
+ Language.Haskell.GHC.Simple.Impl: toCode :: Compile a => ModSummary -> Ghc a
- Language.Haskell.GHC.Simple.Impl: toCompiledModule :: GhcMonad m => (DynFlags -> ModSummary -> m a) -> DynFlags -> ModSummary -> m (CompiledModule a)
+ Language.Haskell.GHC.Simple.Impl: toCompiledModule :: GhcMonad m => (ModSummary -> m a) -> ModSummary -> m (CompiledModule a)
- Language.Haskell.GHC.Simple.Impl: toSimplifiedStg :: GhcMonad m => DynFlags -> ModSummary -> m [StgBinding]
+ Language.Haskell.GHC.Simple.Impl: toSimplifiedStg :: GhcMonad m => ModSummary -> m [StgBinding]
- Language.Haskell.GHC.Simple.Types: Success :: [CompiledModule a] -> [Warning] -> DynFlags -> CompResult a
+ Language.Haskell.GHC.Simple.Types: Success :: a -> [Warning] -> DynFlags -> CompResult a
- Language.Haskell.GHC.Simple.Types: cfgCustomPrimIface :: CompConfig -> Maybe (PrimOp -> PrimOpInfo, PrimOp -> Arity -> StrictSig)
+ Language.Haskell.GHC.Simple.Types: cfgCustomPrimIface :: CompConfig a -> Maybe (PrimOp -> PrimOpInfo, PrimOp -> Arity -> StrictSig)
- Language.Haskell.GHC.Simple.Types: cfgGhcFlags :: CompConfig -> [String]
+ Language.Haskell.GHC.Simple.Types: cfgGhcFlags :: CompConfig a -> [String]
- Language.Haskell.GHC.Simple.Types: cfgGhcLibDir :: CompConfig -> Maybe FilePath
+ Language.Haskell.GHC.Simple.Types: cfgGhcLibDir :: CompConfig a -> Maybe FilePath
- Language.Haskell.GHC.Simple.Types: cfgUpdateDynFlags :: CompConfig -> DynFlags -> DynFlags
+ Language.Haskell.GHC.Simple.Types: cfgUpdateDynFlags :: CompConfig a -> DynFlags -> DynFlags
- Language.Haskell.GHC.Simple.Types: cfgUseGhcErrorLogger :: CompConfig -> Bool
+ Language.Haskell.GHC.Simple.Types: cfgUseGhcErrorLogger :: CompConfig a -> Bool
- Language.Haskell.GHC.Simple.Types: cfgUseTargetsFromFlags :: CompConfig -> Bool
+ Language.Haskell.GHC.Simple.Types: cfgUseTargetsFromFlags :: CompConfig a -> Bool
- Language.Haskell.GHC.Simple.Types: compResult :: CompResult a -> [CompiledModule a]
+ Language.Haskell.GHC.Simple.Types: compResult :: CompResult a -> a
- Language.Haskell.GHC.Simple.Types: data CompConfig
+ Language.Haskell.GHC.Simple.Types: data CompConfig a
- Language.Haskell.GHC.Simple.Types: defaultConfig :: CompConfig
+ Language.Haskell.GHC.Simple.Types: defaultConfig :: Compile a => CompConfig a
Files
- ghc-simple.cabal +1/−1
- src/Language/Haskell/GHC/Simple.hs +96/−62
- src/Language/Haskell/GHC/Simple/Impl.hs +8/−13
- src/Language/Haskell/GHC/Simple/Types.hs +27/−10
ghc-simple.cabal view
@@ -1,5 +1,5 @@ name: ghc-simple-version: 0.1.1.0+version: 0.1.2.0 synopsis: Simplified interface to the GHC API. description: The GHC API is a great tool for working with Haskell code. Unfortunately, it's also fairly opaque and hard to get
src/Language/Haskell/GHC/Simple.hs view
@@ -1,10 +1,13 @@ {-# LANGUAGE CPP, PatternGuards #-} -- | Simplified interface to the GHC API. module Language.Haskell.GHC.Simple (+ -- * Entry points+ compile, compileWith, compileFold,+ -- * Configuration, input and output types module Simple.Types,- Compile, StgModule,+ getDynFlagsForConfig, -- * GHC re-exports for processing STG and Core module CoreSyn, module StgSyn, module Module,@@ -15,10 +18,7 @@ module DynFlags, module SrcLoc, ModSummary (..), ModGuts (..), PkgKey,- pkgKeyString, modulePkgKey,- - -- * Entry points- compile, compileWith, genericCompile+ pkgKeyString, modulePkgKey ) where -- GHC scaffolding@@ -31,6 +31,7 @@ import SrcLoc import Outputable import Hooks+import StaticFlags (discardStaticFlags) -- Convenience re-exports for fiddling with STG import StgSyn@@ -56,6 +57,7 @@ import Language.Haskell.GHC.Simple.PrimIface as Simple.PrimIface import Language.Haskell.GHC.Simple.Types as Simple.Types import Language.Haskell.GHC.Simple.Impl+import System.IO.Unsafe -- | Compile a list of targets and their dependencies into intermediate code. -- Uses settings from the the default 'CompConfig'.@@ -63,74 +65,54 @@ => [String] -- ^ List of compilation targets. A target can be either a module -- or a file name.- -> IO (CompResult a)+ -> IO (CompResult [CompiledModule a]) compile = compileWith defaultConfig -- | Compile a list of targets and their dependencies using a custom -- configuration. compileWith :: Compile a- => CompConfig+ => CompConfig a -- ^ GHC pipeline configuration. -> [String] -- ^ List of compilation targets. A target can be either a module -- or a file name. Targets may also be read from the specified -- 'CompConfig', if 'cfgUseTargetsFromFlags' is set.- -> IO (CompResult a)-compileWith = genericCompile toCode+ -> IO (CompResult [CompiledModule a])+compileWith cfg = compileFold (cfg {cfgGhcPipeline = toCode}) consMod [] --- | Compile a list of targets and their dependencies using a custom--- configuration and compilation function in the 'Ghc' monad. See--- "Language.Haskell.GHC.Simple.Impl" for more information about building--- custom compilation functions.-genericCompile :: (DynFlags -> ModSummary -> Ghc a)- -- ^ Compilation function.- -> CompConfig- -- ^ GHC pipeline configuration.- -> [String]- -- ^ List of compilation targets. A target can be either a module- -- or a file name. Targets may also be read from the specified- -- 'CompConfig', if 'cfgUseTargetsFromFlags' is set.- -> IO (CompResult a)-genericCompile comp cfg files = do- (flags, _staticwarns) <- parseStaticFlags $ map noLoc (cfgGhcFlags cfg)- warns <- newIORef []- runGhc (maybe (Just libdir) Just (cfgGhcLibDir cfg)) $ do+consMod :: [CompiledModule a] -> CompiledModule a -> IO [CompiledModule a]+consMod xs x = return (x:xs) - -- Parse and update dynamic flags- dfs <- getSessionDynFlags- (dfs', files2, _dynwarns) <- parseDynamicFlags dfs flags- let dfs'' = cfgUpdateDynFlags cfg $ dfs' {- log_action = logger (log_action dfs') warns- }+-- | Obtain the dynamic flags and extra targets that would be used to compile+-- anything with the given config.+getDynFlagsForConfig :: CompConfig a -> IO (DynFlags, [String])+getDynFlagsForConfig cfg = initStaticFlags `seq` do+ ws <- newIORef []+ runGhc (maybe (Just libdir) Just (cfgGhcLibDir cfg)) $ do+ setDFS cfg (discardStaticFlags (cfgGhcFlags cfg)) ws - -- Update prim interface hook name and cache if we're using a custom- -- GHC.Prim interface, setting the dynflags in the process.- case cfgCustomPrimIface cfg of- Just (nfo, strs) -> setPrimIface dfs'' nfo strs- _ -> void $ setSessionDynFlags dfs''+-- | Set and return the appropriate dynflags and extra targets for the given+-- config.+setDFS :: CompConfig a -- ^ Compilation configuration.+ -> [String] -- ^ Dynamic GHC command line flags.+ -> IORef [Warning] -- ^ IORef to use for logging warnings.+ -> Ghc (DynFlags, [String])+setDFS cfg flags warns = do+ -- Parse and update dynamic flags+ dfs <- getSessionDynFlags+ (dfs', files2, _dynwarns) <- parseDynamicFlags dfs (map noLoc flags)+ let dfs'' = cfgUpdateDynFlags cfg $ dfs' {+ log_action = logger (log_action dfs') warns+ } - -- Generate code and report results- ecode <- genCode (toCompiledModule comp) (files ++ map unLoc files2)- ws <- liftIO $ readIORef warns- case ecode of- Right (finaldfs, code) ->- return Success {- compResult = code,- compWarnings = ws,- compDynFlags = finaldfs- }- Left es ->- return Failure {- compErrors = es,- compWarnings = ws- }+ -- Update prim interface hook name and cache if we're using a custom+ -- GHC.Prim interface, setting the dynflags in the process.+ case cfgCustomPrimIface cfg of+ Just (nfo, strs) -> setPrimIface dfs'' nfo strs+ _ -> void $ setSessionDynFlags dfs''+ finaldfs <- getSessionDynFlags+ return (finaldfs, map unLoc files2) where- setPrimIface dfs nfo strs = do- void $ setSessionDynFlags dfs {- hooks = (hooks dfs) {ghcPrimIfaceHook = Just $ primIface nfo strs}- }- getSession >>= liftIO . fixPrimopTypes nfo strs- logger deflog warns dfs severity srcspan style msg | cfgUseGhcErrorLogger cfg = do logger' deflog warns dfs severity srcspan style msg@@ -153,13 +135,65 @@ logger' output _ dfs sev srcspan style msg = do output dfs sev srcspan style msg + setPrimIface dfs nfo strs = do+ void $ setSessionDynFlags dfs {+ hooks = (hooks dfs) {ghcPrimIfaceHook = Just $ primIface nfo strs}+ }+ getSession >>= liftIO . fixPrimopTypes nfo strs+++-- | Left fold over a list of compilation targets and their dependencies.+--+-- Sometimes you don't just want a huge pile of intermediate code lying+-- around; chances are you either want to dump it to file or combine it with+-- some other intermediate code, without having to keep it all in memory at+-- the same time.+compileFold :: CompConfig b+ -- ^ GHC pipeline configuration.+ -> (a -> CompiledModule b -> IO a)+ -- ^ Compilation function.+ -> a+ -- ^ Initial accumulator.+ -> [String]+ -- ^ List of compilation targets. A target can be either a module+ -- or a file name. Targets may also be read from the specified+ -- 'CompConfig', if 'cfgUseTargetsFromFlags' is set.+ -> IO (CompResult a)+compileFold cfg comp acc files = initStaticFlags `seq` do+ warns <- newIORef []+ runGhc (maybe (Just libdir) Just (cfgGhcLibDir cfg)) $ do+ (_, files2) <- setDFS cfg (discardStaticFlags (cfgGhcFlags cfg)) warns+ ecode <- genCode ghcPipeline comp acc (files ++ files2)+ ws <- liftIO $ readIORef warns+ case ecode of+ Right (finaldfs, code) ->+ return Success {+ compResult = code,+ compWarnings = ws,+ compDynFlags = finaldfs+ }+ Left es ->+ return Failure {+ compErrors = es,+ compWarnings = ws+ }+ where+ ghcPipeline = toCompiledModule $ cfgGhcPipeline cfg++{-# NOINLINE initStaticFlags #-}+-- | Use lazy evaluation to only call 'parseStaticFlags' once.+initStaticFlags :: [Located String]+initStaticFlags = unsafePerformIO $ fmap fst (parseStaticFlags [])+ -- | Map a compilation function over each 'ModSummary' in the dependency graph -- of a list of targets. genCode :: GhcMonad m- => (DynFlags -> ModSummary -> m a)+ => (ModSummary -> m a)+ -> (b -> a -> IO b)+ -> b -> [String]- -> m (Either [Error] (DynFlags, [a]))-genCode comp files = do+ -> m (Either [Error] (DynFlags, b))+genCode comp usercomp acc files = do dfs <- getSessionDynFlags merrs <- handleSourceError (maybeErrors dfs) $ do ts <- mapM (flip guessTarget Nothing) files@@ -170,7 +204,7 @@ Just errs -> return $ Left errs _ -> do mss <- depanal [] False- code <- mapM (comp dfs . noLog) mss+ code <- foldM (\a x -> comp (noLog x) >>= liftIO . usercomp a) acc mss return $ Right (dfs, code) where -- We logged everything when we did @load@, we don't want to do it twice.
src/Language/Haskell/GHC/Simple/Impl.hs view
@@ -33,20 +33,15 @@ import Control.Monad import Language.Haskell.GHC.Simple.Types --- | Any type we can generate intermediate code for.-class Compile a where- -- | Generate some sort of code (or other output) from a Haskell module.- toCode :: DynFlags -> ModSummary -> Ghc a- type StgModule = CompiledModule [StgBinding] instance Compile [StgBinding] where toCode = toSimplifiedStg instance Compile CgGuts where- toCode = const toSimplifiedCore+ toCode = toSimplifiedCore instance Compile ModGuts where- toCode = const toModGuts+ toCode = toModGuts -- | Package ID/key of a module. modulePkgKey :: Module -> PkgKey@@ -71,12 +66,11 @@ -- | Compile a 'ModSummary' into a module with metadata using a custom -- compilation function. toCompiledModule :: GhcMonad m- => (DynFlags -> ModSummary -> m a)- -> DynFlags+ => (ModSummary -> m a) -> ModSummary -> m (CompiledModule a)-toCompiledModule comp dfs ms = do- code <- comp dfs ms+toCompiledModule comp ms = do+ code <- comp ms ts <- getTargets return $ CompiledModule { modSummary = ms,@@ -101,8 +95,9 @@ -- | Compile a 'ModSummary' into a list of simplified 'StgBinding's. -- See <https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/StgSynType> -- for more information about STG and how it relates to core and Haskell.-toSimplifiedStg :: GhcMonad m => DynFlags -> ModSummary -> m [StgBinding]-toSimplifiedStg dfs ms =+toSimplifiedStg :: GhcMonad m => ModSummary -> m [StgBinding]+toSimplifiedStg ms = do+ dfs <- getSessionDynFlags toSimplifiedCore ms >>= prepare dfs ms >>= toStgBindings dfs ms -- | Compile a 'ModSummary' into a 'CgGuts', containing all information about
src/Language/Haskell/GHC/Simple/Types.hs view
@@ -1,12 +1,13 @@ -- | Config, input and output types for the simplified GHC API. module Language.Haskell.GHC.Simple.Types (- -- Configuration+ -- * GHC pipeline configuration+ Compile (..), CompConfig, defaultConfig, cfgGhcFlags, cfgUseTargetsFromFlags, cfgUpdateDynFlags, cfgGhcLibDir,- cfgUseGhcErrorLogger, cfgCustomPrimIface,+ cfgUseGhcErrorLogger, cfgCustomPrimIface, cfgGhcPipeline, - -- Results and errors+ -- * Compilation results and errors CompiledModule (..), CompResult (..), Error (..),@@ -17,9 +18,16 @@ import GHC import Language.Haskell.GHC.Simple.PrimIface -data CompConfig = CompConfig {- -- | GHC command line flags to control the Haskell to STG compilation- -- pipeline. Both static and dynamic flags may be set here.+-- | Any type we can generate intermediate code for.+class Compile a where+ -- | Generate some sort of code (or other output) from a Haskell module.+ toCode :: ModSummary -> Ghc a++-- | GHC pipeline configuration, parameterized over the intermediate code+-- produced by the pipeline.+data CompConfig a = CompConfig {+ -- | GHC command line dynamic flags to control the Haskell to STG+ -- compilation pipeline. -- For instance, passing @["-O2", "-DHELLO"]@ here is equivalent to -- passing @-O2 -DHELLO@ to the @ghc@ binary. --@@ -69,18 +77,27 @@ -- -- Default: @Nothing@ cfgCustomPrimIface :: Maybe (PrimOp -> PrimOpInfo,- PrimOp -> Arity -> StrictSig)+ PrimOp -> Arity -> StrictSig),++ -- | Use a custom GHC pipeline to generate intermediate code. Useful if+ -- the provided instances for @[StgBinding]@ etc. don't quite do what you+ -- want them to. See "Language.Haskell.GHC.Simple.Impl" for more+ -- information about custom pipelines.+ --+ -- Default: @toCode@+ cfgGhcPipeline :: ModSummary -> Ghc a } -- | Default configuration.-defaultConfig :: CompConfig+defaultConfig :: Compile a => CompConfig a defaultConfig = CompConfig { cfgGhcFlags = [], cfgUseTargetsFromFlags = True, cfgUpdateDynFlags = id, cfgUseGhcErrorLogger = False, cfgGhcLibDir = Nothing,- cfgCustomPrimIface = Nothing+ cfgCustomPrimIface = Nothing,+ cfgGhcPipeline = toCode } -- | Compiler output and metadata for a given module.@@ -141,7 +158,7 @@ data CompResult a = Success { -- | Result of the compilation.- compResult :: [CompiledModule a],+ compResult :: a, -- | Warnings that occurred during compilation. compWarnings :: [Warning],