module Distribution.Client.Dynamic.PackageDescription
( Target(..)
, TargetName(..)
, PackageDescription()
, targets
) where
import Control.Applicative
import Data.Version
import Distribution.Client.Dynamic.Query
import Language.Haskell.Exts.Syntax
import Language.Haskell.Generate
data PackageDescription
data BuildInfo
data CompilerFlavor
data Extension
data Dependency
instance Eq CompilerFlavor where _ == _ = undefined
data TargetName = Library | Executable String | TestSuite String | BenchSuite String deriving (Show, Eq, Read, Ord)
data Target = Target
{
name :: TargetName
, dependencies :: [(String, Maybe Version)]
, sourceDirs :: [FilePath]
, includeDirs :: [FilePath]
, ghcOptions :: [String]
, extensions :: [String]
, buildable :: Bool
, enabled :: Bool
} deriving (Show, Eq, Read)
buildable' :: Selector BuildInfo Bool
buildable' = selector $ const $ useValue "Distribution.PackageDescription" $ Ident "buildable"
hsSourceDirs' :: Selector BuildInfo [FilePath]
hsSourceDirs' = selector $ const $ useValue "Distribution.PackageDescription" $ Ident "hsSourceDirs"
includeDirs' :: Selector BuildInfo [FilePath]
includeDirs' = selector $ const $ useValue "Distribution.PackageDescription" $ Ident "includeDirs"
extensions' :: Selector BuildInfo [String]
extensions' = selector $ const $ expr $ \bi -> applyE2 map' display' $ append' <>$ applyE defaultExtensions' bi <>$ applyE oldExtensions' bi
where display' :: ExpG (Extension -> String)
display' = useValue "Distribution.Text" $ Ident "display"
defaultExtensions', oldExtensions' :: ExpG (BuildInfo -> [Extension])
defaultExtensions' = useValue "Distribution.PackageDescription" $ Ident "defaultExtensions"
oldExtensions' = useValue "Distribution.PackageDescription" $ Ident "oldExtensions"
ghcOptions' :: Selector BuildInfo [FilePath]
ghcOptions' = selector $ const $ concat' <>. applyE map' snd' <>. applyE filter' (applyE equal' ghc <>. fst') <>. options'
where options' :: ExpG (BuildInfo -> [(CompilerFlavor, [String])])
options' = useValue "Distribution.PackageDescription" $ Ident "options"
ghc :: ExpG CompilerFlavor
ghc = useValue "Distribution.Compiler" $ Ident "GHC"
dependencies' :: Selector BuildInfo [(String, Maybe Version)]
dependencies' = selector $ const $ applyE map' serializeDep <>. targetBuildDepends'
where serializeDep :: ExpG (Dependency -> (String, Maybe Version))
serializeDep = expr $ \dep -> do
dependency <- useCon "Distribution.Package" $ Ident "Dependency"
packageName <- useCon "Distribution.Package" $ Ident "PackageName"
let isSpecificVersion = useValue "Distribution.Version" $ Ident "isSpecificVersion"
nameVar <- newName "name"
versionVar <- newName "version"
caseE dep
[ ( PApp dependency [PApp packageName [PVar nameVar], PVar versionVar],
tuple2 <>$ useVar nameVar <>$ applyE isSpecificVersion (useVar versionVar)
)
]
targetBuildDepends' :: ExpG (BuildInfo -> [Dependency])
targetBuildDepends' = useValue "Distribution.PackageDescription" $ Ident "targetBuildDepends"
buildInfoTarget :: Query BuildInfo (TargetName -> Bool -> Target)
buildInfoTarget = (\d src inc opts exts ba n -> Target n d src inc opts exts ba)
<$> query dependencies'
<*> query hsSourceDirs'
<*> query includeDirs'
<*> query ghcOptions'
<*> query extensions'
<*> query buildable'
library' :: ExpG (PackageDescription -> [BuildInfo])
library' = applyE2 maybe' (returnE $ List []) serialize' <>. useValue "Distribution.PackageDescription" (Ident "library")
where serialize' = expr $ \lib -> expr [applyE buildInfo' lib]
buildInfo' = useValue "Distribution.PackageDescription" $ Ident "libBuildInfo"
executables' :: ExpG (PackageDescription -> [(String, BuildInfo)])
executables'= applyE map' serialize' <>. useValue "Distribution.PackageDescription" (Ident "executables")
where serialize' = expr $ \exe -> tuple2 <>$ applyE exeName' exe <>$ applyE buildInfo' exe
exeName' = useValue "Distribution.PackageDescription" $ Ident "exeName"
buildInfo' = useValue "Distribution.PackageDescription" $ Ident "buildInfo"
tests' :: ExpG (PackageDescription -> [((String, Bool), BuildInfo)])
tests' = applyE map' serialize' <>. useValue "Distribution.PackageDescription" (Ident "testSuites")
where serialize' = expr $ \test -> tuple2
<>$ applyE2 tuple2 (testName' <>$ test) (testEnabled' <>$ test)
<>$ applyE buildInfo' test
testName' = useValue "Distribution.PackageDescription" $ Ident "testName"
testEnabled' = useValue "Distribution.PackageDescription" $ Ident "testEnabled"
buildInfo' = useValue "Distribution.PackageDescription" $ Ident "testBuildInfo"
benchmarks' :: ExpG (PackageDescription -> [((String, Bool), BuildInfo)])
benchmarks' = applyE map' serialize' <>. useValue "Distribution.PackageDescription" (Ident "benchmarks")
where serialize' = expr $ \bench -> tuple2
<>$ applyE2 tuple2 (benchName' <>$ bench) (benchEnabled' <>$ bench)
<>$ applyE buildInfo' bench
benchName' = useValue "Distribution.PackageDescription" $ Ident "benchmarkName"
benchEnabled' = useValue "Distribution.PackageDescription" $ Ident "benchmarkEnabled"
buildInfo' = useValue "Distribution.PackageDescription" $ Ident "benchmarkBuildInfo"
targetInfos :: Query PackageDescription [(TargetName, Bool)]
targetInfos = build <$> query hasLib <*> query exeNames <*> query testInfo <*> query benchInfo
where hasLib :: Selector PackageDescription Bool
hasLib = selector $ const $ not' <>. null' <>. library'
exeNames :: Selector PackageDescription [String]
exeNames = selector $ const $ applyE map' fst' <>. executables'
testInfo :: Selector PackageDescription [(String, Bool)]
testInfo = selector $ const $ applyE map' fst' <>. tests'
benchInfo :: Selector PackageDescription [(String, Bool)]
benchInfo = selector $ const $ applyE map' fst' <>. benchmarks'
build lib exe test bench = concat
[ [ (Library , True) | lib ]
, [ (Executable x , True) | x <- exe ]
, [ (TestSuite x , e) | (x,e) <- test ]
, [ (BenchSuite x , e) | (x,e) <- bench ]
]
buildInfos :: Selector PackageDescription [BuildInfo]
buildInfos = selector $ const $ expr $ \bi -> applyE concat' $ expr $ map (<>$ bi) [libraryBI, exesBI, testsBI, benchsBI]
where libraryBI :: ExpG (PackageDescription -> [BuildInfo])
libraryBI = library'
exesBI :: ExpG (PackageDescription -> [BuildInfo])
exesBI = applyE map' snd' <>. executables'
testsBI :: ExpG (PackageDescription -> [BuildInfo])
testsBI = applyE map' snd' <>. tests'
benchsBI :: ExpG (PackageDescription -> [BuildInfo])
benchsBI = applyE map' snd' <>. benchmarks'
targets :: Query PackageDescription [Target]
targets = zipWith uncurry <$> on buildInfos (fmapQ buildInfoTarget) <*> targetInfos