-- | Defines a Makefile abstract syntax tree.
module Build.Drasil.Make.AST where
import Build.Drasil.Make.MakeString (MakeString)
import CodeLang.Drasil (Comment)

-- * Types

-- | A Makefile is made up of Makefile rules.
newtype Makefile = M [Rule]

-- | A Makefile Rule can have comments and commands but needs a target,
-- dependencies, and a type.
data Rule = R Annotation Target Dependencies Type [Command]

-- | A command is made up of 'MakeString's and command operators.
data Command = C MakeString [CommandOpts]

-- | Ignore the return code from the system.
data CommandOpts =
  IgnoreReturnCode deriving CommandOpts -> CommandOpts -> Bool
(CommandOpts -> CommandOpts -> Bool)
-> (CommandOpts -> CommandOpts -> Bool) -> Eq CommandOpts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CommandOpts -> CommandOpts -> Bool
== :: CommandOpts -> CommandOpts -> Bool
$c/= :: CommandOpts -> CommandOpts -> Bool
/= :: CommandOpts -> CommandOpts -> Bool
Eq

-- | Type of rule, either abstract or file-oriented.
data Type = Abstract
          | File deriving Type -> Type -> Bool
(Type -> Type -> Bool) -> (Type -> Type -> Bool) -> Eq Type
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Type -> Type -> Bool
== :: Type -> Type -> Bool
$c/= :: Type -> Type -> Bool
/= :: Type -> Type -> Bool
Eq

-- | A Makefile Annotation is made of 0 or more 'Comment's
type Annotation = [Comment]

-- | A Makefile target is made from a 'MakeString'.
type Target = MakeString
-- | Dependencies are made up of 0 or more 'Target's.
type Dependencies = [Target]

-- * Constructors

-- | Creates a Rule which results in a file being created.
mkFile :: Annotation -> Target -> Dependencies -> [Command] -> Rule
mkFile :: Annotation -> Target -> Dependencies -> [Command] -> Rule
mkFile Annotation
c Target
t Dependencies
d = Annotation -> Target -> Dependencies -> Type -> [Command] -> Rule
R Annotation
c Target
t Dependencies
d Type
File

-- | Creates an abstract Rule not associated to a specific file.
mkRule :: Annotation -> Target -> Dependencies -> [Command] -> Rule
mkRule :: Annotation -> Target -> Dependencies -> [Command] -> Rule
mkRule Annotation
c Target
t Dependencies
d = Annotation -> Target -> Dependencies -> Type -> [Command] -> Rule
R Annotation
c Target
t Dependencies
d Type
Abstract

-- | Creates a Command which fails the make process if it does not return zero.
mkCheckedCommand :: MakeString -> Command
mkCheckedCommand :: Target -> Command
mkCheckedCommand = (Target -> [CommandOpts] -> Command)
-> [CommandOpts] -> Target -> Command
forall a b c. (a -> b -> c) -> b -> a -> c
flip Target -> [CommandOpts] -> Command
C []

-- | Creates a command which executes and ignores the return code.
mkCommand :: MakeString -> Command
mkCommand :: Target -> Command
mkCommand = (Target -> [CommandOpts] -> Command)
-> [CommandOpts] -> Target -> Command
forall a b c. (a -> b -> c) -> b -> a -> c
flip Target -> [CommandOpts] -> Command
C [CommandOpts
IgnoreReturnCode]