{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-|

Module      : Data.Makefile
Copyright   : (c) 2016 Nicolas Mattia
License     : MIT
Maintainer  : Nicolas Mattia <nicolas@nmattia.com>
Stability   : experimental

This module defines the different types used when working with a Makefile.


@
# File: Makefile

hello = world

foo: bar
  baz
@

@
Makefile {
  entries =
    [ Assignment RecursiveAssign "hello" "world"
    , Rule (Target "foo") [Dependency "bar"] [Command "baz"]
    ]
  }
@

-}

module Data.Makefile where

import           Data.String                      (IsString)

import qualified Data.Text as T


-- | A Makefile object, a list of makefile entries
data Makefile = Makefile { Makefile -> [Entry]
entries :: [Entry] } deriving (Int -> Makefile -> ShowS
[Makefile] -> ShowS
Makefile -> String
(Int -> Makefile -> ShowS)
-> (Makefile -> String) -> ([Makefile] -> ShowS) -> Show Makefile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Makefile -> ShowS
showsPrec :: Int -> Makefile -> ShowS
$cshow :: Makefile -> String
show :: Makefile -> String
$cshowList :: [Makefile] -> ShowS
showList :: [Makefile] -> ShowS
Show, ReadPrec [Makefile]
ReadPrec Makefile
Int -> ReadS Makefile
ReadS [Makefile]
(Int -> ReadS Makefile)
-> ReadS [Makefile]
-> ReadPrec Makefile
-> ReadPrec [Makefile]
-> Read Makefile
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Makefile
readsPrec :: Int -> ReadS Makefile
$creadList :: ReadS [Makefile]
readList :: ReadS [Makefile]
$creadPrec :: ReadPrec Makefile
readPrec :: ReadPrec Makefile
$creadListPrec :: ReadPrec [Makefile]
readListPrec :: ReadPrec [Makefile]
Read, Makefile -> Makefile -> Bool
(Makefile -> Makefile -> Bool)
-> (Makefile -> Makefile -> Bool) -> Eq Makefile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Makefile -> Makefile -> Bool
== :: Makefile -> Makefile -> Bool
$c/= :: Makefile -> Makefile -> Bool
/= :: Makefile -> Makefile -> Bool
Eq)

-- | A makefile entry, either a rule @(target: dep1 dep1; commands)@ or a
-- variable assignment (@hello = world@ or @hello := world@)
data Entry = Rule Target [Dependency] [Command]
           | Assignment AssignmentType T.Text T.Text
           | OtherLine T.Text
           -- ^ Catch all value for comments, empty lines and lines that failed
           -- to parse.
           deriving (Int -> Entry -> ShowS
[Entry] -> ShowS
Entry -> String
(Int -> Entry -> ShowS)
-> (Entry -> String) -> ([Entry] -> ShowS) -> Show Entry
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Entry -> ShowS
showsPrec :: Int -> Entry -> ShowS
$cshow :: Entry -> String
show :: Entry -> String
$cshowList :: [Entry] -> ShowS
showList :: [Entry] -> ShowS
Show, ReadPrec [Entry]
ReadPrec Entry
Int -> ReadS Entry
ReadS [Entry]
(Int -> ReadS Entry)
-> ReadS [Entry]
-> ReadPrec Entry
-> ReadPrec [Entry]
-> Read Entry
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Entry
readsPrec :: Int -> ReadS Entry
$creadList :: ReadS [Entry]
readList :: ReadS [Entry]
$creadPrec :: ReadPrec Entry
readPrec :: ReadPrec Entry
$creadListPrec :: ReadPrec [Entry]
readListPrec :: ReadPrec [Entry]
Read, Entry -> Entry -> Bool
(Entry -> Entry -> Bool) -> (Entry -> Entry -> Bool) -> Eq Entry
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Entry -> Entry -> Bool
== :: Entry -> Entry -> Bool
$c/= :: Entry -> Entry -> Bool
/= :: Entry -> Entry -> Bool
Eq)

data AssignmentType
  = RecursiveAssign
    -- ^ foo = bar
  | SimpleAssign
    -- ^ foo := bar
  | SimplePosixAssign
    -- ^ foo ::= bar
  | ConditionalAssign
    -- ^ foo ?= bar
  | ShellAssign
    -- ^ foo != bar
  | AppendAssign
    -- ^ foo += bar
  deriving (Int -> AssignmentType -> ShowS
[AssignmentType] -> ShowS
AssignmentType -> String
(Int -> AssignmentType -> ShowS)
-> (AssignmentType -> String)
-> ([AssignmentType] -> ShowS)
-> Show AssignmentType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AssignmentType -> ShowS
showsPrec :: Int -> AssignmentType -> ShowS
$cshow :: AssignmentType -> String
show :: AssignmentType -> String
$cshowList :: [AssignmentType] -> ShowS
showList :: [AssignmentType] -> ShowS
Show, ReadPrec [AssignmentType]
ReadPrec AssignmentType
Int -> ReadS AssignmentType
ReadS [AssignmentType]
(Int -> ReadS AssignmentType)
-> ReadS [AssignmentType]
-> ReadPrec AssignmentType
-> ReadPrec [AssignmentType]
-> Read AssignmentType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS AssignmentType
readsPrec :: Int -> ReadS AssignmentType
$creadList :: ReadS [AssignmentType]
readList :: ReadS [AssignmentType]
$creadPrec :: ReadPrec AssignmentType
readPrec :: ReadPrec AssignmentType
$creadListPrec :: ReadPrec [AssignmentType]
readListPrec :: ReadPrec [AssignmentType]
Read, AssignmentType -> AssignmentType -> Bool
(AssignmentType -> AssignmentType -> Bool)
-> (AssignmentType -> AssignmentType -> Bool) -> Eq AssignmentType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AssignmentType -> AssignmentType -> Bool
== :: AssignmentType -> AssignmentType -> Bool
$c/= :: AssignmentType -> AssignmentType -> Bool
/= :: AssignmentType -> AssignmentType -> Bool
Eq, Int -> AssignmentType
AssignmentType -> Int
AssignmentType -> [AssignmentType]
AssignmentType -> AssignmentType
AssignmentType -> AssignmentType -> [AssignmentType]
AssignmentType
-> AssignmentType -> AssignmentType -> [AssignmentType]
(AssignmentType -> AssignmentType)
-> (AssignmentType -> AssignmentType)
-> (Int -> AssignmentType)
-> (AssignmentType -> Int)
-> (AssignmentType -> [AssignmentType])
-> (AssignmentType -> AssignmentType -> [AssignmentType])
-> (AssignmentType -> AssignmentType -> [AssignmentType])
-> (AssignmentType
    -> AssignmentType -> AssignmentType -> [AssignmentType])
-> Enum AssignmentType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: AssignmentType -> AssignmentType
succ :: AssignmentType -> AssignmentType
$cpred :: AssignmentType -> AssignmentType
pred :: AssignmentType -> AssignmentType
$ctoEnum :: Int -> AssignmentType
toEnum :: Int -> AssignmentType
$cfromEnum :: AssignmentType -> Int
fromEnum :: AssignmentType -> Int
$cenumFrom :: AssignmentType -> [AssignmentType]
enumFrom :: AssignmentType -> [AssignmentType]
$cenumFromThen :: AssignmentType -> AssignmentType -> [AssignmentType]
enumFromThen :: AssignmentType -> AssignmentType -> [AssignmentType]
$cenumFromTo :: AssignmentType -> AssignmentType -> [AssignmentType]
enumFromTo :: AssignmentType -> AssignmentType -> [AssignmentType]
$cenumFromThenTo :: AssignmentType
-> AssignmentType -> AssignmentType -> [AssignmentType]
enumFromThenTo :: AssignmentType
-> AssignmentType -> AssignmentType -> [AssignmentType]
Enum, AssignmentType
AssignmentType -> AssignmentType -> Bounded AssignmentType
forall a. a -> a -> Bounded a
$cminBound :: AssignmentType
minBound :: AssignmentType
$cmaxBound :: AssignmentType
maxBound :: AssignmentType
Bounded)

-- | Makefile target (@foo@ in the example above)
newtype Target = Target T.Text deriving (Int -> Target -> ShowS
[Target] -> ShowS
Target -> String
(Int -> Target -> ShowS)
-> (Target -> String) -> ([Target] -> ShowS) -> Show Target
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Target -> ShowS
showsPrec :: Int -> Target -> ShowS
$cshow :: Target -> String
show :: Target -> String
$cshowList :: [Target] -> ShowS
showList :: [Target] -> ShowS
Show, ReadPrec [Target]
ReadPrec Target
Int -> ReadS Target
ReadS [Target]
(Int -> ReadS Target)
-> ReadS [Target]
-> ReadPrec Target
-> ReadPrec [Target]
-> Read Target
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Target
readsPrec :: Int -> ReadS Target
$creadList :: ReadS [Target]
readList :: ReadS [Target]
$creadPrec :: ReadPrec Target
readPrec :: ReadPrec Target
$creadListPrec :: ReadPrec [Target]
readListPrec :: ReadPrec [Target]
Read, Target -> Target -> Bool
(Target -> Target -> Bool)
-> (Target -> Target -> Bool) -> Eq Target
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Target -> Target -> Bool
== :: Target -> Target -> Bool
$c/= :: Target -> Target -> Bool
/= :: Target -> Target -> Bool
Eq, String -> Target
(String -> Target) -> IsString Target
forall a. (String -> a) -> IsString a
$cfromString :: String -> Target
fromString :: String -> Target
IsString)

-- | Target dependency (@bar@ in the example above)
newtype Dependency = Dependency T.Text deriving (Int -> Dependency -> ShowS
[Dependency] -> ShowS
Dependency -> String
(Int -> Dependency -> ShowS)
-> (Dependency -> String)
-> ([Dependency] -> ShowS)
-> Show Dependency
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Dependency -> ShowS
showsPrec :: Int -> Dependency -> ShowS
$cshow :: Dependency -> String
show :: Dependency -> String
$cshowList :: [Dependency] -> ShowS
showList :: [Dependency] -> ShowS
Show, ReadPrec [Dependency]
ReadPrec Dependency
Int -> ReadS Dependency
ReadS [Dependency]
(Int -> ReadS Dependency)
-> ReadS [Dependency]
-> ReadPrec Dependency
-> ReadPrec [Dependency]
-> Read Dependency
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Dependency
readsPrec :: Int -> ReadS Dependency
$creadList :: ReadS [Dependency]
readList :: ReadS [Dependency]
$creadPrec :: ReadPrec Dependency
readPrec :: ReadPrec Dependency
$creadListPrec :: ReadPrec [Dependency]
readListPrec :: ReadPrec [Dependency]
Read, Dependency -> Dependency -> Bool
(Dependency -> Dependency -> Bool)
-> (Dependency -> Dependency -> Bool) -> Eq Dependency
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Dependency -> Dependency -> Bool
== :: Dependency -> Dependency -> Bool
$c/= :: Dependency -> Dependency -> Bool
/= :: Dependency -> Dependency -> Bool
Eq, String -> Dependency
(String -> Dependency) -> IsString Dependency
forall a. (String -> a) -> IsString a
$cfromString :: String -> Dependency
fromString :: String -> Dependency
IsString)

-- | Command (@baz@ in the example above)
newtype Command = Command T.Text deriving (Int -> Command -> ShowS
[Command] -> ShowS
Command -> String
(Int -> Command -> ShowS)
-> (Command -> String) -> ([Command] -> ShowS) -> Show Command
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Command -> ShowS
showsPrec :: Int -> Command -> ShowS
$cshow :: Command -> String
show :: Command -> String
$cshowList :: [Command] -> ShowS
showList :: [Command] -> ShowS
Show, ReadPrec [Command]
ReadPrec Command
Int -> ReadS Command
ReadS [Command]
(Int -> ReadS Command)
-> ReadS [Command]
-> ReadPrec Command
-> ReadPrec [Command]
-> Read Command
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Command
readsPrec :: Int -> ReadS Command
$creadList :: ReadS [Command]
readList :: ReadS [Command]
$creadPrec :: ReadPrec Command
readPrec :: ReadPrec Command
$creadListPrec :: ReadPrec [Command]
readListPrec :: ReadPrec [Command]
Read, Command -> Command -> Bool
(Command -> Command -> Bool)
-> (Command -> Command -> Bool) -> Eq Command
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Command -> Command -> Bool
== :: Command -> Command -> Bool
$c/= :: Command -> Command -> Bool
/= :: Command -> Command -> Bool
Eq, String -> Command
(String -> Command) -> IsString Command
forall a. (String -> a) -> IsString a
$cfromString :: String -> Command
fromString :: String -> Command
IsString)