{-# OPTIONS_GHC -fno-warn-orphans #-}

{-# LANGUAGE DeriveAnyClass             #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE DuplicateRecordFields      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving         #-}

module Language.ATS.Package.Type ( -- * Types
                                   Pkg (..)
                                 , ATSDependency (..)
                                 , Bin (..)
                                 , Lib (..)
                                 , Src (..)
                                 , Version (..)
                                 , ForeignCabal (..)
                                 , ATSConstraint (..)
                                 , TargetPair (..)
                                 , CCompiler (..)
                                 , LibDep
                                 , DepSelector
                                 -- * Lenses
                                 , dirLens
                                 ) where

import           Data.Dependency
import           Development.Shake.ATS
import           Language.ATS.Package.Debian
import           Quaalude

data ATSConstraint = ATSConstraint { ATSConstraint -> Maybe Version
lower :: Maybe Version
                                   , ATSConstraint -> Maybe Version
upper :: Maybe Version
                                   }
                deriving (ATSConstraint -> ATSConstraint -> Bool
(ATSConstraint -> ATSConstraint -> Bool)
-> (ATSConstraint -> ATSConstraint -> Bool) -> Eq ATSConstraint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ATSConstraint -> ATSConstraint -> Bool
$c/= :: ATSConstraint -> ATSConstraint -> Bool
== :: ATSConstraint -> ATSConstraint -> Bool
$c== :: ATSConstraint -> ATSConstraint -> Bool
Eq, Int -> ATSConstraint -> ShowS
[ATSConstraint] -> ShowS
ATSConstraint -> String
(Int -> ATSConstraint -> ShowS)
-> (ATSConstraint -> String)
-> ([ATSConstraint] -> ShowS)
-> Show ATSConstraint
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ATSConstraint] -> ShowS
$cshowList :: [ATSConstraint] -> ShowS
show :: ATSConstraint -> String
$cshow :: ATSConstraint -> String
showsPrec :: Int -> ATSConstraint -> ShowS
$cshowsPrec :: Int -> ATSConstraint -> ShowS
Show, (forall x. ATSConstraint -> Rep ATSConstraint x)
-> (forall x. Rep ATSConstraint x -> ATSConstraint)
-> Generic ATSConstraint
forall x. Rep ATSConstraint x -> ATSConstraint
forall x. ATSConstraint -> Rep ATSConstraint x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ATSConstraint x -> ATSConstraint
$cfrom :: forall x. ATSConstraint -> Rep ATSConstraint x
Generic, Get ATSConstraint
[ATSConstraint] -> Put
ATSConstraint -> Put
(ATSConstraint -> Put)
-> Get ATSConstraint
-> ([ATSConstraint] -> Put)
-> Binary ATSConstraint
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [ATSConstraint] -> Put
$cputList :: [ATSConstraint] -> Put
get :: Get ATSConstraint
$cget :: Get ATSConstraint
put :: ATSConstraint -> Put
$cput :: ATSConstraint -> Put
Binary, InputNormalizer -> Decoder ATSConstraint
(InputNormalizer -> Decoder ATSConstraint)
-> FromDhall ATSConstraint
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder ATSConstraint
$cautoWith :: InputNormalizer -> Decoder ATSConstraint
FromDhall)

deriving newtype instance ToDhall Version

type LibDep = (Text, ATSConstraint)

-- | You likely want 'libDeps' or 'libBldDeps'
type DepSelector = ATSDependency -> [LibDep]

-- TODO add a field for configure stage??
-- | Type for a dependency
data ATSDependency = ATSDependency { ATSDependency -> Text
libName     :: Text -- ^ Library name, e.g.
                                   , ATSDependency -> Text
dir         :: Text -- ^ Directory we should unpack to
                                   , ATSDependency -> Text
url         :: Text -- ^ Url pointing to tarball
                                   , ATSDependency -> Maybe Text
description :: Maybe Text -- ^ Package description
                                   , ATSDependency -> Version
libVersion  :: Version
                                   , ATSDependency -> [LibDep]
libDeps     :: [LibDep] -- ^ Dependencies to be unpacked
                                   , ATSDependency -> [LibDep]
libBldDeps  :: [LibDep] -- ^ Dependencies to be built
                                   , ATSDependency -> [LibDep]
libCDeps    :: [LibDep] -- ^ C dependencies to be built
                                   , ATSDependency -> [Text]
script      :: [Text] -- ^ Optional build script for C library
                                   }
                   deriving ((forall x. ATSDependency -> Rep ATSDependency x)
-> (forall x. Rep ATSDependency x -> ATSDependency)
-> Generic ATSDependency
forall x. Rep ATSDependency x -> ATSDependency
forall x. ATSDependency -> Rep ATSDependency x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ATSDependency x -> ATSDependency
$cfrom :: forall x. ATSDependency -> Rep ATSDependency x
Generic, InputNormalizer -> Decoder ATSDependency
(InputNormalizer -> Decoder ATSDependency)
-> FromDhall ATSDependency
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder ATSDependency
$cautoWith :: InputNormalizer -> Decoder ATSDependency
FromDhall, Get ATSDependency
[ATSDependency] -> Put
ATSDependency -> Put
(ATSDependency -> Put)
-> Get ATSDependency
-> ([ATSDependency] -> Put)
-> Binary ATSDependency
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [ATSDependency] -> Put
$cputList :: [ATSDependency] -> Put
get :: Get ATSDependency
$cget :: Get ATSDependency
put :: ATSDependency -> Put
$cput :: ATSDependency -> Put
Binary)

dirLens :: Lens' ATSDependency Text
dirLens :: (Text -> f Text) -> ATSDependency -> f ATSDependency
dirLens Text -> f Text
f ATSDependency
s = (Text -> ATSDependency) -> f Text -> f ATSDependency
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Text
x -> ATSDependency
s { $sel:dir:ATSDependency :: Text
dir = Text
x }) (Text -> f Text
f (ATSDependency -> Text
dir ATSDependency
s))

-- | This is just a tuple, except I can figure out how to use it with Dhall.
data TargetPair = TargetPair { TargetPair -> Text
hs    :: Text
                             , TargetPair -> Text
ats   :: Text
                             , TargetPair -> Bool
cpphs :: Bool
                             } deriving ((forall x. TargetPair -> Rep TargetPair x)
-> (forall x. Rep TargetPair x -> TargetPair) -> Generic TargetPair
forall x. Rep TargetPair x -> TargetPair
forall x. TargetPair -> Rep TargetPair x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TargetPair x -> TargetPair
$cfrom :: forall x. TargetPair -> Rep TargetPair x
Generic, InputNormalizer -> Decoder TargetPair
(InputNormalizer -> Decoder TargetPair) -> FromDhall TargetPair
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder TargetPair
$cautoWith :: InputNormalizer -> Decoder TargetPair
FromDhall, Get TargetPair
[TargetPair] -> Put
TargetPair -> Put
(TargetPair -> Put)
-> Get TargetPair -> ([TargetPair] -> Put) -> Binary TargetPair
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [TargetPair] -> Put
$cputList :: [TargetPair] -> Put
get :: Get TargetPair
$cget :: Get TargetPair
put :: TargetPair -> Put
$cput :: TargetPair -> Put
Binary)

deriving instance FromDhall ForeignCabal

deriving instance FromDhall Solver

data Src = Src { Src -> Text
atsSrc  :: Text
               , Src -> Text
cTarget :: Text
               , Src -> [TargetPair]
atsGen  :: [TargetPair]
               , Src -> [Text]
extras  :: [Text]
               }
         deriving ((forall x. Src -> Rep Src x)
-> (forall x. Rep Src x -> Src) -> Generic Src
forall x. Rep Src x -> Src
forall x. Src -> Rep Src x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Src x -> Src
$cfrom :: forall x. Src -> Rep Src x
Generic, InputNormalizer -> Decoder Src
(InputNormalizer -> Decoder Src) -> FromDhall Src
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder Src
$cautoWith :: InputNormalizer -> Decoder Src
FromDhall, Get Src
[Src] -> Put
Src -> Put
(Src -> Put) -> Get Src -> ([Src] -> Put) -> Binary Src
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Src] -> Put
$cputList :: [Src] -> Put
get :: Get Src
$cget :: Get Src
put :: Src -> Put
$cput :: Src -> Put
Binary)

data Bin = Bin { Bin -> Text
src    :: Text -- ^ Source file (should end with @.dats@)
               , Bin -> Text
target :: Text -- ^ Binary to be built
               , Bin -> [Text]
libs   :: [Text] -- ^ Libraries to link against (e.g. @[ "pthread" ]@)
               , Bin -> [ForeignCabal]
hsDeps :: [ForeignCabal] -- ^ Haskell @.cabal@ files associated with the final library we want to make
               , Bin -> [TargetPair]
hs2ats :: [TargetPair] -- ^ List of sources and targets for @hs2ats@
               , Bin -> Bool
gcBin  :: Bool -- ^ Whether to use the garbage collector
               , Bin -> [Text]
extras :: [Text] -- ^ Extra source files the build depends on
               }
         deriving ((forall x. Bin -> Rep Bin x)
-> (forall x. Rep Bin x -> Bin) -> Generic Bin
forall x. Rep Bin x -> Bin
forall x. Bin -> Rep Bin x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Bin x -> Bin
$cfrom :: forall x. Bin -> Rep Bin x
Generic, InputNormalizer -> Decoder Bin
(InputNormalizer -> Decoder Bin) -> FromDhall Bin
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder Bin
$cautoWith :: InputNormalizer -> Decoder Bin
FromDhall, Get Bin
[Bin] -> Put
Bin -> Put
(Bin -> Put) -> Get Bin -> ([Bin] -> Put) -> Binary Bin
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Bin] -> Put
$cputList :: [Bin] -> Put
get :: Get Bin
$cget :: Get Bin
put :: Bin -> Put
$cput :: Bin -> Put
Binary)

data Lib = Lib { Lib -> Text
name      :: Text -- ^ Name of library being provided
               , Lib -> [Text]
src       :: [Text] -- ^ Source files (should end with @.dats@) to be compiled to object files
               , Lib -> Text
libTarget :: Text
               , Lib -> [Text]
libs      :: [Text] -- ^ Libraries to link against (e.g. @[ "pthread" ]@)
               , Lib -> [Text]
includes  :: [Text] -- ^ Include files to be installed with the library
               , Lib -> [ForeignCabal]
hsDeps    :: [ForeignCabal] -- ^ Haskell @.cabal@ files associated with object files
               , Lib -> [(Text, Text)]
links     :: [(Text, Text)] -- ^ Generate link files.
               , Lib -> [TargetPair]
hs2ats    :: [TargetPair] -- ^ Sources and targets for @hs2ats@
               , Lib -> [Text]
extras    :: [Text] -- ^ Other source files the build depends on
               , Lib -> Bool
static    :: Bool -- ^ Whether to make a static library
               }
         deriving ((forall x. Lib -> Rep Lib x)
-> (forall x. Rep Lib x -> Lib) -> Generic Lib
forall x. Rep Lib x -> Lib
forall x. Lib -> Rep Lib x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Lib x -> Lib
$cfrom :: forall x. Lib -> Rep Lib x
Generic, InputNormalizer -> Decoder Lib
(InputNormalizer -> Decoder Lib) -> FromDhall Lib
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder Lib
$cautoWith :: InputNormalizer -> Decoder Lib
FromDhall, Get Lib
[Lib] -> Put
Lib -> Put
(Lib -> Put) -> Get Lib -> ([Lib] -> Put) -> Binary Lib
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Lib] -> Put
$cputList :: [Lib] -> Put
get :: Get Lib
$cget :: Get Lib
put :: Lib -> Put
$cput :: Lib -> Put
Binary)

-- | Data type associated with @atspkg.dhall@ file.
data Pkg = Pkg { Pkg -> [Bin]
bin          :: [Bin] -- ^ List of binaries to be built
               , Pkg -> [Bin]
test         :: [Bin] -- ^ List of test suites
               , Pkg -> [Bin]
bench        :: [Bin] -- ^ List of benchmarks
               , Pkg -> [Lib]
libraries    :: [Lib] -- ^ List of libraries to be built
               , Pkg -> Maybe Text
man          :: Maybe Text -- ^ Optional (markdown) manpages to be converted using @pandoc@.
               , Pkg -> Maybe Text
completions  :: Maybe Text -- ^ Optional @compleat@ completions to be installed alongside package.
               , Pkg -> Version
version      :: Version -- ^ Library version
               , Pkg -> Version
compiler     :: Version -- ^ Compiler version
               , Pkg -> [LibDep]
dependencies :: [LibDep] -- ^ List of library dependencies
               , Pkg -> [LibDep]
clib         :: [LibDep] -- ^ List of C library dependencies
               , Pkg -> [LibDep]
buildDeps    :: [LibDep] -- ^ List of ATS library dependencies
               , Pkg -> Text
ccompiler    :: Text -- ^ The C compiler we should use
               , Pkg -> [Text]
cflags       :: [Text] -- ^ List of flags to pass to the C compiler
               , Pkg -> [Text]
atsFlags     :: [Text] -- ^ List of flags to pass to @patsopt@.
               , Pkg -> [Src]
atsSource    :: [Src] -- ^ ATS source to be compile to C.
               , Pkg -> Bool
dynLink      :: Bool -- ^ Don't link statically, instead, use libraries installed by @atspkg@.
               , Pkg -> Solver
extSolve     :: Solver -- ^ Solver to use.
               , Pkg -> Maybe Debian
debPkg       :: Maybe Debian -- ^ Optional specificiation as a debian package.
               , Pkg -> Bool
atsLib       :: Bool -- ^ Whether to link/build @atslib@.
               }
         deriving ((forall x. Pkg -> Rep Pkg x)
-> (forall x. Rep Pkg x -> Pkg) -> Generic Pkg
forall x. Rep Pkg x -> Pkg
forall x. Pkg -> Rep Pkg x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Pkg x -> Pkg
$cfrom :: forall x. Pkg -> Rep Pkg x
Generic, InputNormalizer -> Decoder Pkg
(InputNormalizer -> Decoder Pkg) -> FromDhall Pkg
forall a. (InputNormalizer -> Decoder a) -> FromDhall a
autoWith :: InputNormalizer -> Decoder Pkg
$cautoWith :: InputNormalizer -> Decoder Pkg
FromDhall, Get Pkg
[Pkg] -> Put
Pkg -> Put
(Pkg -> Put) -> Get Pkg -> ([Pkg] -> Put) -> Binary Pkg
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Pkg] -> Put
$cputList :: [Pkg] -> Put
get :: Get Pkg
$cget :: Get Pkg
put :: Pkg -> Put
$cput :: Pkg -> Put
Binary)