-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.Simple.GHC.ImplInfo
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- This module contains the data structure describing invocation
-- details for a GHC or GHC-derived compiler, such as supported flags
-- and workarounds for bugs.

module Distribution.Simple.GHC.ImplInfo (
        GhcImplInfo(..), getImplInfo,
        ghcVersionImplInfo, ghcjsVersionImplInfo
        ) where

import Prelude ()
import Distribution.Compat.Prelude

import Distribution.Simple.Compiler
import Distribution.Version

{- |
     Information about features and quirks of a GHC-based implementation.

     Compiler flavors based on GHC behave similarly enough that some of
     the support code for them is shared. Every implementation has its
     own peculiarities, that may or may not be a direct result of the
     underlying GHC version. This record keeps track of these differences.

     All shared code (i.e. everything not in the Distribution.Simple.FLAVOR
     module) should use implementation info rather than version numbers
     to test for supported features.
-}

data GhcImplInfo = GhcImplInfo
  { GhcImplInfo -> Bool
supportsHaskell2010  :: Bool -- ^ -XHaskell2010 and -XHaskell98 flags
  , GhcImplInfo -> Bool
reportsNoExt         :: Bool -- ^ --supported-languages gives Ext and NoExt
  , GhcImplInfo -> Bool
alwaysNondecIndent   :: Bool -- ^ NondecreasingIndentation is always on
  , GhcImplInfo -> Bool
flagGhciScript       :: Bool -- ^ -ghci-script flag supported
  , GhcImplInfo -> Bool
flagProfAuto         :: Bool -- ^ new style -fprof-auto* flags
  , GhcImplInfo -> Bool
flagPackageConf      :: Bool -- ^ use package-conf instead of package-db
  , GhcImplInfo -> Bool
flagDebugInfo        :: Bool -- ^ -g flag supported
  , GhcImplInfo -> Bool
supportsDebugLevels  :: Bool -- ^ supports numeric @-g@ levels
  , GhcImplInfo -> Bool
supportsPkgEnvFiles  :: Bool -- ^ picks up @.ghc.environment@ files
  , GhcImplInfo -> Bool
flagWarnMissingHomeModules :: Bool -- ^ -Wmissing-home-modules is supported
  }

getImplInfo :: Compiler -> GhcImplInfo
getImplInfo :: Compiler -> GhcImplInfo
getImplInfo Compiler
comp =
  case Compiler -> CompilerFlavor
compilerFlavor Compiler
comp of
    CompilerFlavor
GHC   -> Version -> GhcImplInfo
ghcVersionImplInfo (Compiler -> Version
compilerVersion Compiler
comp)
    CompilerFlavor
GHCJS -> case CompilerFlavor -> Compiler -> Maybe Version
compilerCompatVersion CompilerFlavor
GHC Compiler
comp of
              Just Version
ghcVer -> Version -> Version -> GhcImplInfo
ghcjsVersionImplInfo (Compiler -> Version
compilerVersion Compiler
comp) Version
ghcVer
              Maybe Version
_  -> [Char] -> GhcImplInfo
forall a. HasCallStack => [Char] -> a
error ([Char]
"Distribution.Simple.GHC.Props.getImplProps: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                           [Char]
"could not find GHC version for GHCJS compiler")
    CompilerFlavor
x     -> [Char] -> GhcImplInfo
forall a. HasCallStack => [Char] -> a
error ([Char]
"Distribution.Simple.GHC.Props.getImplProps only works" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                    [Char]
"for GHC-like compilers (GHC, GHCJS)" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++
                    [Char]
", but found " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ CompilerFlavor -> [Char]
forall a. Show a => a -> [Char]
show CompilerFlavor
x)

ghcVersionImplInfo :: Version -> GhcImplInfo
ghcVersionImplInfo :: Version -> GhcImplInfo
ghcVersionImplInfo Version
ver = GhcImplInfo :: Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> GhcImplInfo
GhcImplInfo
  { supportsHaskell2010 :: Bool
supportsHaskell2010  = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
7]
  , reportsNoExt :: Bool
reportsNoExt         = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
7]
  , alwaysNondecIndent :: Bool
alwaysNondecIndent   = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
<  [Int
7,Int
1]
  , flagGhciScript :: Bool
flagGhciScript       = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
7,Int
2]
  , flagProfAuto :: Bool
flagProfAuto         = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
7,Int
4]
  , flagPackageConf :: Bool
flagPackageConf      = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
<  [Int
7,Int
5]
  , flagDebugInfo :: Bool
flagDebugInfo        = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
7,Int
10]
  , supportsDebugLevels :: Bool
supportsDebugLevels  = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
0]
  , supportsPkgEnvFiles :: Bool
supportsPkgEnvFiles  = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
0,Int
1,Int
20160901] -- broken in 8.0.1, fixed in 8.0.2
  , flagWarnMissingHomeModules :: Bool
flagWarnMissingHomeModules = [Int]
v [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
2]
  }
  where
    v :: [Int]
v = Version -> [Int]
versionNumbers Version
ver

ghcjsVersionImplInfo :: Version  -- ^ The GHCJS version
                     -> Version  -- ^ The GHC version
                     -> GhcImplInfo
ghcjsVersionImplInfo :: Version -> Version -> GhcImplInfo
ghcjsVersionImplInfo Version
_ghcjsver Version
ghcver = GhcImplInfo :: Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> GhcImplInfo
GhcImplInfo
  { supportsHaskell2010 :: Bool
supportsHaskell2010  = Bool
True
  , reportsNoExt :: Bool
reportsNoExt         = Bool
True
  , alwaysNondecIndent :: Bool
alwaysNondecIndent   = Bool
False
  , flagGhciScript :: Bool
flagGhciScript       = Bool
True
  , flagProfAuto :: Bool
flagProfAuto         = Bool
True
  , flagPackageConf :: Bool
flagPackageConf      = Bool
False
  , flagDebugInfo :: Bool
flagDebugInfo        = Bool
False
  , supportsDebugLevels :: Bool
supportsDebugLevels  = [Int]
ghcv [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
0]
  , supportsPkgEnvFiles :: Bool
supportsPkgEnvFiles  = [Int]
ghcv [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
0,Int
2] --TODO: check this works in ghcjs
  , flagWarnMissingHomeModules :: Bool
flagWarnMissingHomeModules = [Int]
ghcv [Int] -> [Int] -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int
8,Int
2]
  }
  where
    ghcv :: [Int]
ghcv = Version -> [Int]
versionNumbers Version
ghcver