-- | Defines types and functions for generating Makefiles.
module Build.Drasil.Make.MakeString where

-- * Types

-- | Type synonym for variable names.
type VarName = String
-- | Type synonym for variable values.
type VarVal = String

data MakeString = Mr String -- ^ A string for Makefiles.
                | Mv MVar -- ^ Holds a Makefile variable.
                | Mc MakeString MakeString -- ^ Concatenates two 'MakeString's.

instance Semigroup MakeString where
  <> :: MakeString -> MakeString -> MakeString
(<>) = MakeString -> MakeString -> MakeString
Mc

instance Monoid MakeString where
  mempty :: MakeString
mempty = String -> MakeString
Mr String
""

-- | For creating Makefile variables.
data MVar = Os VarName VarVal VarVal VarVal -- ^ Operating System specific variable. Holds information for Windows, Mac, and Linux systems.
          | Implicit VarName -- ^ Implicit OS.
          | Free VarName -- ^ Independent of OS.
          deriving MVar -> MVar -> Bool
(MVar -> MVar -> Bool) -> (MVar -> MVar -> Bool) -> Eq MVar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MVar -> MVar -> Bool
== :: MVar -> MVar -> Bool
$c/= :: MVar -> MVar -> Bool
/= :: MVar -> MVar -> Bool
Eq

-- * Functions

-- | Concatenates two 'MakeString's with a space in between.
(+:+) :: MakeString -> MakeString -> MakeString
MakeString
a +:+ :: MakeString -> MakeString -> MakeString
+:+ (Mr String
"") = MakeString
a
(Mr String
"") +:+ MakeString
b = MakeString
b
MakeString
a +:+ MakeString
b = MakeString
a MakeString -> MakeString -> MakeString
forall a. Semigroup a => a -> a -> a
<> String -> MakeString
Mr String
" " MakeString -> MakeString -> MakeString
forall a. Semigroup a => a -> a -> a
<> MakeString
b

-- | Renders a 'MakeString'. Variables have the form \"$(@var@)\".
renderMS :: MakeString -> String
renderMS :: MakeString -> String
renderMS (Mr String
s) = String
s
renderMS (Mv MVar
v) = (String -> String) -> MVar -> String
renderVar (\String
x -> String
"$(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")") MVar
v
renderMS (Mc MakeString
a MakeString
b) = MakeString -> String
renderMS MakeString
a String -> String -> String
forall a. [a] -> [a] -> [a]
++ MakeString -> String
renderMS MakeString
b

-- | Renders variables. Takes in a function for the variable, and the type of variable.
renderVar :: (String -> String) -> MVar -> String
renderVar :: (String -> String) -> MVar -> String
renderVar String -> String
f (Os String
nm String
_ String
_ String
_) = String -> String
f String
nm
renderVar String -> String
f (Implicit String
nm) = String
"\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
f String
nm String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
renderVar String -> String
f (Free String
nm) = String -> String
f String
nm

-- | Constructor for converting a 'String' into a 'MakeString'.
makeS :: String -> MakeString
makeS :: String -> MakeString
makeS = String -> MakeString
Mr

-- | Constructor for Windows OS variables.
mkWindowsVar :: VarName -> VarVal -> VarVal -> MakeString
mkWindowsVar :: String -> String -> String -> MakeString
mkWindowsVar String
n String
w String
e = MVar -> MakeString
Mv (MVar -> MakeString) -> MVar -> MakeString
forall a b. (a -> b) -> a -> b
$ String -> String -> String -> String -> MVar
Os String
n String
w String
e String
e

-- | Constructor for OS variables.
mkOSVar :: VarName -> VarVal -> VarVal -> VarVal -> MakeString
mkOSVar :: String -> String -> String -> String -> MakeString
mkOSVar String
n String
w String
m String
l = MVar -> MakeString
Mv (MVar -> MakeString) -> MVar -> MakeString
forall a b. (a -> b) -> a -> b
$ String -> String -> String -> String -> MVar
Os String
n String
w String
m String
l

-- | Constructor for 'Implicit' variables.
mkImplicitVar :: VarName -> MakeString
mkImplicitVar :: String -> MakeString
mkImplicitVar = MVar -> MakeString
Mv (MVar -> MakeString) -> (String -> MVar) -> String -> MakeString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> MVar
Implicit

-- | Constructor for 'Free' variables.
mkFreeVar :: VarName -> MakeString
mkFreeVar :: String -> MakeString
mkFreeVar = MVar -> MakeString
Mv (MVar -> MakeString) -> (String -> MVar) -> String -> MakeString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> MVar
Free