
module Development.Make.Type where

import Control.Monad


data Makefile = Makefile [Stmt] deriving Show

data Stmt
    = Rule
        {targets :: Expr
        ,prerequisites :: Expr
        ,commands :: [Command]
        }
    | Assign
        {name :: String
        ,assign :: Assign
        ,expr :: Expr
        }
      deriving Show

data Assign = Equals | ColonEquals | PlusEquals | QuestionEquals deriving Show

data Expr = Apply String [Expr]
          | Concat [Expr]
          | Var String
          | Lit String
            deriving Show

data Command = Expr Expr | String := Expr deriving Show

descendExpr :: (Expr -> Expr) -> Expr -> Expr
descendExpr f (Apply a b) = Apply a $ map f b
descendExpr f (Concat xs) = Concat $ map f xs
descendExpr f x = x

descendExprM :: Monad m => (Expr -> m Expr) -> Expr -> m Expr
descendExprM f (Apply a b) = Apply a `liftM` mapM f b
descendExprM f (Concat xs) = Concat `liftM` mapM f xs
descendExprM f x = return x

transformExpr :: (Expr -> Expr) -> Expr -> Expr
transformExpr f = f . descendExpr (transformExpr f)

simplifyExpr :: Expr -> Expr
simplifyExpr = transformExpr f
    where
        f (Concat xs) = case g xs of
            [] -> Lit ""
            [x] -> x
            xs -> Concat xs
        f x = x

        g (Concat x:xs) = g $ x ++ xs
        g (Lit x:Lit y:xs) = g $ Lit (x ++ y) : xs
        g (x:xs) = x : g xs
        g [] = []
