module Language.Drasil.Code.Imperative.Build.Import (
makeBuild
) where
import Language.Drasil.Code.Imperative.Build.AST (asFragment, DocConfig(..),
BuildConfig(BuildConfig), BuildDependencies(..), Ext(..), includeExt,
NameOpts, nameOpts, packSep, Runnable(Runnable), BuildName(..), RunType(..))
import GOOL.Drasil (FileData(..), ProgData(..), GOOLState(..), headers, sources,
mainMod)
import Build.Drasil ((+:+), genMake, makeS, MakeString, mkFile, mkRule,
mkCheckedCommand, mkFreeVar, RuleTransformer(makeRule))
import Control.Lens ((^.))
import Data.Maybe (maybeToList)
import Data.List (nub)
import System.FilePath.Posix (takeExtension, takeBaseName)
import Text.PrettyPrint.HughesPJ (Doc)
data CodeHarness = Ch {
CodeHarness -> Maybe BuildConfig
buildConfig :: Maybe BuildConfig,
CodeHarness -> Maybe Runnable
runnable :: Maybe Runnable,
CodeHarness -> GOOLState
goolState :: GOOLState,
CodeHarness -> ProgData
progData :: ProgData,
CodeHarness -> Maybe DocConfig
docConfig :: Maybe DocConfig}
instance RuleTransformer CodeHarness where
makeRule :: CodeHarness -> [Rule]
makeRule (Ch b :: Maybe BuildConfig
b r :: Maybe Runnable
r s :: GOOLState
s m :: ProgData
m d :: Maybe DocConfig
d) = [Rule] -> (BuildConfig -> [Rule]) -> Maybe BuildConfig -> [Rule]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Target -> Dependencies -> [Command] -> Rule
mkRule Target
buildTarget [] []]
(\(BuildConfig comp :: Dependencies -> Target -> Target -> [Dependencies]
comp onm :: Maybe BuildName
onm anm :: Maybe BuildName
anm bt :: BuildDependencies
bt) ->
let outnm :: Target
outnm = Target -> (BuildName -> Target) -> Maybe BuildName -> Target
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Target
asFragment "") (GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
m NameOpts
nameOpts) Maybe BuildName
onm
addnm :: Target
addnm = Target -> (BuildName -> Target) -> Maybe BuildName -> Target
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Target
asFragment "") (GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
m NameOpts
nameOpts) Maybe BuildName
anm
in [
Target -> Dependencies -> [Command] -> Rule
mkRule Target
buildTarget [Target
outnm] [],
Target -> Dependencies -> [Command] -> Rule
mkFile Target
outnm ((FileData -> Target) -> [FileData] -> Dependencies
forall a b. (a -> b) -> [a] -> [b]
map (String -> Target
makeS (String -> Target) -> (FileData -> String) -> FileData -> Target
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileData -> String
filePath) (ProgData -> [FileData]
progMods ProgData
m)) ([Command] -> Rule) -> [Command] -> Rule
forall a b. (a -> b) -> a -> b
$
(Dependencies -> Command) -> [Dependencies] -> [Command]
forall a b. (a -> b) -> [a] -> [b]
map (Target -> Command
mkCheckedCommand (Target -> Command)
-> (Dependencies -> Target) -> Dependencies -> Command
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Target -> Target -> Target) -> Target -> Dependencies -> Target
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Target -> Target -> Target
(+:+) Target
forall a. Monoid a => a
mempty) ([Dependencies] -> [Command]) -> [Dependencies] -> [Command]
forall a b. (a -> b) -> a -> b
$
Dependencies -> Target -> Target -> [Dependencies]
comp (BuildDependencies -> GOOLState -> ProgData -> Dependencies
getCompilerInput BuildDependencies
bt GOOLState
s ProgData
m) Target
outnm Target
addnm
]) Maybe BuildConfig
b [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule] -> (Runnable -> [Rule]) -> Maybe Runnable -> [Rule]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(Runnable nm :: BuildName
nm no :: NameOpts
no ty :: RunType
ty) -> [
Target -> Dependencies -> [Command] -> Rule
mkRule (String -> Target
makeS "run") [Target
buildTarget] [
Target -> Command
mkCheckedCommand (Target -> Command) -> Target -> Command
forall a b. (a -> b) -> a -> b
$ Target -> RunType -> Target
buildRunTarget (GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
m NameOpts
no BuildName
nm) RunType
ty Target -> Target -> Target
+:+ String -> Target
mkFreeVar "RUNARGS"
]
]) Maybe Runnable
r [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule] -> (DocConfig -> [Rule]) -> Maybe DocConfig -> [Rule]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(DocConfig dps :: Dependencies
dps cmds :: [Command]
cmds) -> [
Target -> Dependencies -> [Command] -> Rule
mkRule (String -> Target
makeS "doc") (Dependencies
dps Dependencies -> Dependencies -> Dependencies
forall a. [a] -> [a] -> [a]
++ GOOLState -> Dependencies
getCommentedFiles GOOLState
s) [Command]
cmds
]) Maybe DocConfig
d where
buildTarget :: Target
buildTarget = String -> Target
makeS "build"
renderBuildName :: GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName :: GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName s :: GOOLState
s _ _ BMain = String -> Target
makeS (String -> Target) -> String -> Target
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> String
forall a. HasCallStack => String -> a
error "Main module missing")
String -> String
takeBaseName (GOOLState
s GOOLState
-> Getting (Maybe String) GOOLState (Maybe String) -> Maybe String
forall s a. s -> Getting a s a -> a
^. Getting (Maybe String) GOOLState (Maybe String)
Lens' GOOLState (Maybe String)
mainMod)
renderBuildName _ p :: ProgData
p _ BPackName = String -> Target
makeS (ProgData -> String
progName ProgData
p)
renderBuildName s :: GOOLState
s p :: ProgData
p o :: NameOpts
o (BPack a :: BuildName
a) = GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
BPackName Target -> Target -> Target
forall a. Semigroup a => a -> a -> a
<>
String -> Target
makeS (NameOpts -> String
packSep NameOpts
o) Target -> Target -> Target
forall a. Semigroup a => a -> a -> a
<> GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
a
renderBuildName s :: GOOLState
s p :: ProgData
p o :: NameOpts
o (BWithExt a :: BuildName
a e :: Ext
e) = GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
a Target -> Target -> Target
forall a. Semigroup a => a -> a -> a
<>
if NameOpts -> Bool
includeExt NameOpts
o then Ext -> String -> Target
renderExt Ext
e ([String] -> String
forall p. [p] -> p
takeSrc ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ GOOLState
s GOOLState -> Getting [String] GOOLState [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] GOOLState [String]
Lens' GOOLState [String]
sources) else String -> Target
makeS ""
where takeSrc :: [p] -> p
takeSrc (src :: p
src:_) = p
src
takeSrc [] = String -> p
forall a. HasCallStack => String -> a
error "Generated code has no source files"
renderExt :: Ext -> FilePath -> MakeString
renderExt :: Ext -> String -> Target
renderExt CodeExt f :: String
f = String -> Target
makeS (String -> Target) -> String -> Target
forall a b. (a -> b) -> a -> b
$ String -> String
takeExtension String
f
renderExt (OtherExt e :: Target
e) _ = Target
e
getCompilerInput :: BuildDependencies -> GOOLState -> ProgData -> [MakeString]
getCompilerInput :: BuildDependencies -> GOOLState -> ProgData -> Dependencies
getCompilerInput BcSource s :: GOOLState
s _ = (String -> Target) -> [String] -> Dependencies
forall a b. (a -> b) -> [a] -> [b]
map String -> Target
makeS ([String] -> Dependencies) -> [String] -> Dependencies
forall a b. (a -> b) -> a -> b
$ GOOLState
s GOOLState -> Getting [String] GOOLState [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] GOOLState [String]
Lens' GOOLState [String]
sources
getCompilerInput (BcSingle n :: BuildName
n) s :: GOOLState
s p :: ProgData
p = [GOOLState -> ProgData -> NameOpts -> BuildName -> Target
renderBuildName GOOLState
s ProgData
p NameOpts
nameOpts BuildName
n]
getCommentedFiles :: GOOLState -> [MakeString]
s :: GOOLState
s = (String -> Target) -> [String] -> Dependencies
forall a b. (a -> b) -> [a] -> [b]
map String -> Target
makeS ([String] -> [String]
forall a. Eq a => [a] -> [a]
nub (GOOLState
s GOOLState -> Getting [String] GOOLState [String] -> [String]
forall s a. s -> Getting a s a -> a
^. Getting [String] GOOLState [String]
Lens' GOOLState [String]
headers [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
Maybe String -> [String]
forall a. Maybe a -> [a]
maybeToList (GOOLState
s GOOLState
-> Getting (Maybe String) GOOLState (Maybe String) -> Maybe String
forall s a. s -> Getting a s a -> a
^. Getting (Maybe String) GOOLState (Maybe String)
Lens' GOOLState (Maybe String)
mainMod)))
buildRunTarget :: MakeString -> RunType -> MakeString
buildRunTarget :: Target -> RunType -> Target
buildRunTarget fn :: Target
fn Standalone = String -> Target
makeS "./" Target -> Target -> Target
forall a. Semigroup a => a -> a -> a
<> Target
fn
buildRunTarget fn :: Target
fn (Interpreter i :: Dependencies
i) = (Target -> Target -> Target) -> Target -> Dependencies -> Target
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Target -> Target -> Target
(+:+) Target
forall a. Monoid a => a
mempty (Dependencies -> Target) -> Dependencies -> Target
forall a b. (a -> b) -> a -> b
$ Dependencies
i Dependencies -> Dependencies -> Dependencies
forall a. [a] -> [a] -> [a]
++ [Target
fn]
makeBuild :: Maybe DocConfig -> Maybe BuildConfig -> Maybe Runnable ->
GOOLState -> ProgData -> Doc
makeBuild :: Maybe DocConfig
-> Maybe BuildConfig
-> Maybe Runnable
-> GOOLState
-> ProgData
-> Doc
makeBuild d :: Maybe DocConfig
d b :: Maybe BuildConfig
b r :: Maybe Runnable
r s :: GOOLState
s p :: ProgData
p = [CodeHarness] -> Doc
forall c. RuleTransformer c => [c] -> Doc
genMake [Ch :: Maybe BuildConfig
-> Maybe Runnable
-> GOOLState
-> ProgData
-> Maybe DocConfig
-> CodeHarness
Ch {
buildConfig :: Maybe BuildConfig
buildConfig = Maybe BuildConfig
b,
runnable :: Maybe Runnable
runnable = Maybe Runnable
r,
goolState :: GOOLState
goolState = GOOLState
s,
progData :: ProgData
progData = ProgData
p,
docConfig :: Maybe DocConfig
docConfig = Maybe DocConfig
d}]