{-# LANGUAGE TypeFamilies #-}

-- | The logic to render Swift auxiliary files is contained in this module
module Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.SwiftRenderer (
  SwiftProject(..)
) where

import Language.Drasil.Choices (ImplementationType(..))
import Language.Drasil.Code.Imperative.GOOL.ClassInterface (ReadMeInfo(..),
  PackageSym(..), AuxiliarySym(..))
import qualified
  Language.Drasil.Code.Imperative.GOOL.LanguageRenderer.LanguagePolymorphic as
  G (sampleInput, readMe, makefile, noRunIfLib, docIfEnabled)
import Language.Drasil.Code.Imperative.GOOL.Data (AuxData(..), ad, PackData(..),
  packD)
import Language.Drasil.Code.Imperative.Build.AST (BuildConfig, Runnable,
  DocConfig(..), asFragment, buildAll, nativeBinary, executable, sharedLibrary)

import GOOL.Drasil (onCodeList, swiftName, swiftVersion)

import Prelude hiding (break,print,(<>),sin,cos,tan,floor)
import Text.PrettyPrint.HughesPJ (Doc, empty)

-- | Holds a Swift project.
newtype SwiftProject a = SP {forall a. SwiftProject a -> a
unSP :: a}

instance Functor SwiftProject where
  fmap :: forall a b. (a -> b) -> SwiftProject a -> SwiftProject b
fmap a -> b
f (SP a
x) = forall a. a -> SwiftProject a
SP (a -> b
f a
x)

instance Applicative SwiftProject where
  pure :: forall a. a -> SwiftProject a
pure = forall a. a -> SwiftProject a
SP
  (SP a -> b
f) <*> :: forall a b.
SwiftProject (a -> b) -> SwiftProject a -> SwiftProject b
<*> (SP a
x) = forall a. a -> SwiftProject a
SP (a -> b
f a
x)

instance Monad SwiftProject where
  SP a
x >>= :: forall a b.
SwiftProject a -> (a -> SwiftProject b) -> SwiftProject b
>>= a -> SwiftProject b
f = a -> SwiftProject b
f a
x

instance PackageSym SwiftProject where
  type Package SwiftProject = PackData
  package :: ProgData
-> [SwiftProject (Auxiliary SwiftProject)]
-> SwiftProject (Package SwiftProject)
package ProgData
p = forall (m :: * -> *) a b. Monad m => ([a] -> b) -> [m a] -> m b
onCodeList (ProgData -> [AuxData] -> PackData
packD ProgData
p)

instance AuxiliarySym SwiftProject where
  type Auxiliary SwiftProject = AuxData
  type AuxHelper SwiftProject = Doc
  doxConfig :: String
-> GOOLState -> Verbosity -> SwiftProject (Auxiliary SwiftProject)
doxConfig String
_ GOOLState
_ Verbosity
_ = forall (r :: * -> *).
AuxiliarySym r =>
String -> Doc -> r (Auxiliary r)
auxFromData String
"" Doc
empty
  readMe :: ReadMeInfo -> SwiftProject (Auxiliary SwiftProject)
readMe ReadMeInfo
rmi = forall (r :: * -> *).
AuxiliarySym r =>
ReadMeInfo -> r (Auxiliary r)
G.readMe ReadMeInfo
rmi {
        langName :: String
langName = String
swiftName,
        langVersion :: String
langVersion = String
swiftVersion}
  sampleInput :: ChunkDB
-> DataDesc -> [Expr] -> SwiftProject (Auxiliary SwiftProject)
sampleInput = forall (r :: * -> *).
AuxiliarySym r =>
ChunkDB -> DataDesc -> [Expr] -> r (Auxiliary r)
G.sampleInput

  optimizeDox :: SwiftProject (AuxHelper SwiftProject)
optimizeDox = forall a. HasCallStack => String -> a
error String
doxError

  makefile :: [String]
-> ImplementationType
-> [Comments]
-> GOOLState
-> ProgData
-> SwiftProject (Auxiliary SwiftProject)
makefile [String]
fs ImplementationType
it [Comments]
cms = forall (r :: * -> *).
AuxiliarySym r =>
Maybe BuildConfig
-> Maybe Runnable
-> Maybe DocConfig
-> GOOLState
-> ProgData
-> r (Auxiliary r)
G.makefile ([String] -> ImplementationType -> Maybe BuildConfig
swiftBuildConfig [String]
fs ImplementationType
it) (ImplementationType -> Maybe Runnable -> Maybe Runnable
G.noRunIfLib ImplementationType
it Maybe Runnable
swiftRunnable) ([Comments] -> DocConfig -> Maybe DocConfig
G.docIfEnabled [Comments]
cms (Dependencies -> [Command] -> DocConfig
DocConfig [] []))

  auxHelperDoc :: SwiftProject (AuxHelper SwiftProject) -> Doc
auxHelperDoc = forall a. SwiftProject a -> a
unSP
  auxFromData :: String -> Doc -> SwiftProject (Auxiliary SwiftProject)
auxFromData String
fp Doc
d = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ String -> Doc -> AuxData
ad String
fp Doc
d

-- | Create a build configuration for Swift files. Takes in 'FilePath's and the type of implementation.
swiftBuildConfig :: [FilePath] -> ImplementationType -> Maybe BuildConfig
swiftBuildConfig :: [String] -> ImplementationType -> Maybe BuildConfig
swiftBuildConfig [String]
fs ImplementationType
it = (Dependencies -> CommandFragment -> [Dependencies])
-> BuildName -> Maybe BuildConfig
buildAll (\Dependencies
i CommandFragment
o -> [String -> CommandFragment
asFragment String
"swiftc" forall a. a -> [a] -> [a]
: Dependencies
i forall a. [a] -> [a] -> [a]
++
  [String -> CommandFragment
asFragment String
"-o", CommandFragment
o] forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\String
f -> forall a b. (a -> b) -> [a] -> [b]
map String -> CommandFragment
asFragment [String
"-I", String
f]) [String]
fs forall a. [a] -> [a] -> [a]
++
  ImplementationType -> Dependencies
asLib ImplementationType
it]) (ImplementationType -> BuildName
outName ImplementationType
it)
  where asLib :: ImplementationType -> Dependencies
asLib ImplementationType
Library = [String -> CommandFragment
asFragment String
"-emit-library"]
        asLib ImplementationType
Program = []
        outName :: ImplementationType -> BuildName
outName ImplementationType
Library = BuildName
sharedLibrary
        outName ImplementationType
Program = BuildName
executable

-- | Default runnable information for Swift files.
swiftRunnable :: Maybe Runnable
swiftRunnable :: Maybe Runnable
swiftRunnable = Maybe Runnable
nativeBinary

-- | Swift is not compatible with Doxygen, so raise an error if trying to compile Doxygen documentation.
doxError :: String
doxError :: String
doxError = String
swiftName forall a. [a] -> [a] -> [a]
++ String
" is not compatible with Doxygen."