{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
module Clash.GHCi.Common
( checkImportDirs
, checkMonoLocalBinds
, checkMonoLocalBindsMod
, checkClashDynamic
) where
import Clash.Driver.Types (ClashOpts (..))
import qualified DynFlags
#if MIN_VERSION_base(4,11,0)
import qualified EnumSet as GHC (member)
#else
import qualified Data.IntSet as IntSet
#endif
import qualified GHC (DynFlags, ModSummary (..), Module (..),
extensionFlags, moduleNameString)
import qualified GHC.LanguageExtensions as LangExt (Extension (..))
import Panic (GhcException (..), throwGhcException)
import Control.Monad (forM_, unless, when)
import System.Directory (doesDirectoryExist)
import System.IO (hPutStrLn, stderr)
checkMonoLocalBindsMod :: GHC.ModSummary -> IO ()
checkMonoLocalBindsMod :: ModSummary -> IO ()
checkMonoLocalBindsMod x :: ModSummary
x =
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (DynFlags -> Bool
active (DynFlags -> Bool)
-> (ModSummary -> DynFlags) -> ModSummary -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModSummary -> DynFlags
GHC.ms_hspp_opts (ModSummary -> Bool) -> ModSummary -> Bool
forall a b. (a -> b) -> a -> b
$ ModSummary
x) (Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ ModSummary -> String
msg ModSummary
x)
where
msg :: ModSummary -> String
msg = String -> String
messageWith (String -> String)
-> (ModSummary -> String) -> ModSummary -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleName -> String
GHC.moduleNameString (ModuleName -> String)
-> (ModSummary -> ModuleName) -> ModSummary -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Module -> ModuleName
GHC.moduleName (Module -> ModuleName)
-> (ModSummary -> Module) -> ModSummary -> ModuleName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModSummary -> Module
GHC.ms_mod
checkMonoLocalBinds :: GHC.DynFlags -> IO ()
checkMonoLocalBinds :: DynFlags -> IO ()
checkMonoLocalBinds dflags :: DynFlags
dflags =
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
unless (DynFlags -> Bool
active DynFlags
dflags) (Handle -> String -> IO ()
hPutStrLn Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> String
messageWith "")
messageWith :: String -> String
messageWith :: String -> String
messageWith srcModule :: String
srcModule
| String
srcModule String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== [] = String
msgStem String -> String -> String
forall a. [a] -> [a] -> [a]
++ "."
| Bool
otherwise = String
msgStem String -> String -> String
forall a. [a] -> [a] -> [a]
++ " in module: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
srcModule
where
msgStem :: String
msgStem = "Warning: Extension MonoLocalBinds disabled. This might lead to unexpected logic duplication"
active :: GHC.DynFlags -> Bool
#if MIN_VERSION_base(4,11,0)
active :: DynFlags -> Bool
active = Extension -> EnumSet Extension -> Bool
forall a. Enum a => a -> EnumSet a -> Bool
GHC.member Extension
LangExt.MonoLocalBinds (EnumSet Extension -> Bool)
-> (DynFlags -> EnumSet Extension) -> DynFlags -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> EnumSet Extension
GHC.extensionFlags
#else
active = member LangExt.MonoLocalBinds . GHC.extensionFlags
member :: Enum a => a -> IntSet.IntSet -> Bool
member = IntSet.member . fromEnum
#endif
checkImportDirs :: Foldable t => ClashOpts -> t FilePath -> IO ()
checkImportDirs :: ClashOpts -> t String -> IO ()
checkImportDirs opts :: ClashOpts
opts idirs :: t String
idirs = Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
when (ClashOpts -> Bool
opt_checkIDir ClashOpts
opts) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
t String -> (String -> IO ()) -> IO ()
forall (t :: Type -> Type) (m :: Type -> Type) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ t String
idirs ((String -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \dir :: String
dir -> do
String -> IO Bool
doesDirectoryExist String
dir IO Bool -> (Bool -> IO ()) -> IO ()
forall (m :: Type -> Type) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
False -> GhcException -> IO ()
forall a. GhcException -> a
throwGhcException (String -> GhcException
CmdLineError (String -> GhcException) -> String -> GhcException
forall a b. (a -> b) -> a -> b
$ "Missing directory: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dir)
_ -> () -> IO ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ()
checkClashDynamic :: GHC.DynFlags -> IO ()
checkClashDynamic :: DynFlags -> IO ()
checkClashDynamic dflags :: DynFlags
dflags = do
let isStatic :: Bool
isStatic = case String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup "GHC Dynamic" (DynFlags -> [(String, String)]
DynFlags.compilerInfo DynFlags
dflags) of
Just "YES" -> Bool
False
_ -> Bool
True
Bool -> IO () -> IO ()
forall (f :: Type -> Type). Applicative f => Bool -> f () -> f ()
when Bool
isStatic
(Handle -> String -> IO ()
hPutStrLn Handle
stderr ([String] -> String
unlines
["WARNING: Clash is linked statically, which can lead to long startup times."
,"See https://gitlab.haskell.org/ghc/ghc/issues/15524"
]))