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 (Annotation, (+:+), 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)
import Utils.Drasil (capitalize)
import Metadata.Drasil.DrasilMetaCall (watermark)
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 Maybe BuildConfig
b Maybe Runnable
r GOOLState
s ProgData
m Maybe DocConfig
d) = forall b a. b -> (a -> b) -> Maybe a -> b
maybe [[String] -> MakeString -> Dependencies -> [Command] -> Rule
mkRule (ProgData -> [String]
openingComments ProgData
m) MakeString
buildTarget [] []]
(\(BuildConfig Dependencies -> MakeString -> MakeString -> [Dependencies]
comp Maybe BuildName
onm Maybe BuildName
anm BuildDependencies
bt) ->
let outnm :: MakeString
outnm = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> MakeString
asFragment String
"") (GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
m NameOpts
nameOpts) Maybe BuildName
onm
addnm :: MakeString
addnm = forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> MakeString
asFragment String
"") (GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
m NameOpts
nameOpts) Maybe BuildName
anm
in [
[String] -> MakeString -> Dependencies -> [Command] -> Rule
mkRule (ProgData -> [String]
openingComments ProgData
m) MakeString
buildTarget [MakeString
outnm] [],
[String] -> MakeString -> Dependencies -> [Command] -> Rule
mkFile [] MakeString
outnm (forall a b. (a -> b) -> [a] -> [b]
map (String -> MakeString
makeS forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileData -> String
filePath) (ProgData -> [FileData]
progMods ProgData
m)) forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map (MakeString -> Command
mkCheckedCommand forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr MakeString -> MakeString -> MakeString
(+:+) forall a. Monoid a => a
mempty) forall a b. (a -> b) -> a -> b
$
Dependencies -> MakeString -> MakeString -> [Dependencies]
comp (BuildDependencies -> GOOLState -> ProgData -> Dependencies
getCompilerInput BuildDependencies
bt GOOLState
s ProgData
m) MakeString
outnm MakeString
addnm
]) Maybe BuildConfig
b forall a. [a] -> [a] -> [a]
++ forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(Runnable BuildName
nm NameOpts
no RunType
ty) -> [
[String] -> MakeString -> Dependencies -> [Command] -> Rule
mkRule [] (String -> MakeString
makeS String
"run") [MakeString
buildTarget] [
MakeString -> Command
mkCheckedCommand forall a b. (a -> b) -> a -> b
$ MakeString -> RunType -> MakeString
buildRunTarget (GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
m NameOpts
no BuildName
nm) RunType
ty MakeString -> MakeString -> MakeString
+:+
String -> MakeString
mkFreeVar String
"RUNARGS"
]
]) Maybe Runnable
r forall a. [a] -> [a] -> [a]
++ forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\(DocConfig Dependencies
dps [Command]
cmds) -> [
[String] -> MakeString -> Dependencies -> [Command] -> Rule
mkRule [] (String -> MakeString
makeS String
"doc") (Dependencies
dps forall a. [a] -> [a] -> [a]
++ GOOLState -> Dependencies
getCommentedFiles GOOLState
s) [Command]
cmds
]) Maybe DocConfig
d where
buildTarget :: MakeString
buildTarget = String -> MakeString
makeS String
"build"
openingComments :: ProgData -> Annotation
ProgData
m = [String
watermark,String
"Project Name: " forall a. [a] -> [a] -> [a]
++ ProgData -> String
progName ProgData
m, ProgData -> String
progPurpAdd ProgData
m]
progPurpAdd :: ProgData -> String
progPurpAdd :: ProgData -> String
progPurpAdd ProgData
m = if ProgData -> String
progPurp ProgData
m forall a. Eq a => a -> a -> Bool
/= [] then String
"Project Purpose: " forall a. [a] -> [a] -> [a]
++
String -> String
capitalize (ProgData -> String
progPurp ProgData
m)
else []
renderBuildName :: GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName :: GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
_ NameOpts
_ BuildName
BMain = String -> MakeString
makeS forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. HasCallStack => String -> a
error String
"Main module missing")
String -> String
takeBaseName (GOOLState
s forall s a. s -> Getting a s a -> a
^. Lens' GOOLState (Maybe String)
mainMod)
renderBuildName GOOLState
_ ProgData
p NameOpts
_ BuildName
BPackName = String -> MakeString
makeS (ProgData -> String
progName ProgData
p)
renderBuildName GOOLState
s ProgData
p NameOpts
o (BPack BuildName
a) = GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
BPackName forall a. Semigroup a => a -> a -> a
<>
String -> MakeString
makeS (NameOpts -> String
packSep NameOpts
o) forall a. Semigroup a => a -> a -> a
<> GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
a
renderBuildName GOOLState
s ProgData
p NameOpts
o (BWithExt BuildName
a Ext
e) = GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
p NameOpts
o BuildName
a forall a. Semigroup a => a -> a -> a
<>
if NameOpts -> Bool
includeExt NameOpts
o then Ext -> String -> MakeString
renderExt Ext
e (forall {a}. [a] -> a
takeSrc forall a b. (a -> b) -> a -> b
$ GOOLState
s forall s a. s -> Getting a s a -> a
^. Lens' GOOLState [String]
sources) else String -> MakeString
makeS String
""
where takeSrc :: [a] -> a
takeSrc (a
src:[a]
_) = a
src
takeSrc [] = forall a. HasCallStack => String -> a
error String
"Generated code has no source files"
renderExt :: Ext -> FilePath -> MakeString
renderExt :: Ext -> String -> MakeString
renderExt Ext
CodeExt String
f = String -> MakeString
makeS forall a b. (a -> b) -> a -> b
$ String -> String
takeExtension String
f
renderExt (OtherExt MakeString
e) String
_ = MakeString
e
getCompilerInput :: BuildDependencies -> GOOLState -> ProgData -> [MakeString]
getCompilerInput :: BuildDependencies -> GOOLState -> ProgData -> Dependencies
getCompilerInput BuildDependencies
BcSource GOOLState
s ProgData
_ = forall a b. (a -> b) -> [a] -> [b]
map String -> MakeString
makeS forall a b. (a -> b) -> a -> b
$ GOOLState
s forall s a. s -> Getting a s a -> a
^. Lens' GOOLState [String]
sources
getCompilerInput (BcSingle BuildName
n) GOOLState
s ProgData
p = [GOOLState -> ProgData -> NameOpts -> BuildName -> MakeString
renderBuildName GOOLState
s ProgData
p NameOpts
nameOpts BuildName
n]
getCommentedFiles :: GOOLState -> [MakeString]
GOOLState
s = forall a b. (a -> b) -> [a] -> [b]
map String -> MakeString
makeS (forall a. Eq a => [a] -> [a]
nub (GOOLState
s forall s a. s -> Getting a s a -> a
^. Lens' GOOLState [String]
headers forall a. [a] -> [a] -> [a]
++
forall a. Maybe a -> [a]
maybeToList (GOOLState
s forall s a. s -> Getting a s a -> a
^. Lens' GOOLState (Maybe String)
mainMod)))
buildRunTarget :: MakeString -> RunType -> MakeString
buildRunTarget :: MakeString -> RunType -> MakeString
buildRunTarget MakeString
fn RunType
Standalone = String -> MakeString
makeS String
"./" forall a. Semigroup a => a -> a -> a
<> MakeString
fn
buildRunTarget MakeString
fn (Interpreter Dependencies
i) = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr MakeString -> MakeString -> MakeString
(+:+) forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$ Dependencies
i forall a. [a] -> [a] -> [a]
++ [MakeString
fn]
makeBuild :: Maybe DocConfig -> Maybe BuildConfig -> Maybe Runnable ->
GOOLState -> ProgData -> Doc
makeBuild :: Maybe DocConfig
-> Maybe BuildConfig
-> Maybe Runnable
-> GOOLState
-> ProgData
-> Doc
makeBuild Maybe DocConfig
d Maybe BuildConfig
b Maybe Runnable
r GOOLState
s ProgData
p = forall c. RuleTransformer c => [c] -> Doc
genMake [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}]