module DependencyGenerator ( DepGenM , DepGenM' , evalDepGenM , inject , runFunction , runFunctionIO , mapDepGenM , mapDepGenM_ , filterDepGenM , joinPaths , isImageFilename , convertedImageFilename , applyTemplate , listDirectory , readTemplate , convertImage , saveFile , makeDir , runPandoc ) where import Types.Token (Token(..)) import Types.Values import Types.Value (Valuable(..)) import Types.Function (Function(..)) import Types.FunctionIO (FunctionIO(..)) import Types.Dependency (Action(..), Dependency, makeDependency) import Control.Monad.State (MonadState, State, runState, put, get) import Control.Monad.Writer (MonadWriter, WriterT, execWriterT, tell) newtype DepGenM a = DepGenM { unDepGenM :: WriterT [Dependency] (State Int) a } deriving (Functor, Applicative, Monad, MonadState Int, MonadWriter [Dependency]) type DepGenM' a = DepGenM (Token a) evalDepGenM' :: Int -> DepGenM () -> ([Dependency], Int) evalDepGenM' top m = runState (execWriterT (unDepGenM m)) top evalDepGenM :: DepGenM () -> [Dependency] evalDepGenM m = fst (evalDepGenM' 0 m) tellDep :: Dependency -> DepGenM () tellDep dep = tell [dep] genDependencyM :: (Token a -> DepGenM Dependency) -> DepGenM' a genDependencyM f = do top <- get let top' = top + 1 target = Token top' put top' result <- f target tellDep result pure target genDependency :: (Token a -> Dependency) -> DepGenM' a genDependency f = genDependencyM (pure . f) inject :: Valuable a => a -> DepGenM' a inject x = genDependency (makeDependency NoToken (Inject (toValue x))) getListElem :: Token [a] -> DepGenM' a getListElem outer = genDependency (makeDependency outer GetListElem) setListElem :: Token a -> Token [a] -> DepGenM () setListElem a outer = do tellDep (makeDependency a SetListElem outer) runFunction :: Function -> Token a -> DepGenM' b runFunction f input = genDependency (makeDependency input (Function f)) runFunctionIO :: FunctionIO -> Token a -> DepGenM' b runFunctionIO f input = genDependency (makeDependency input (FunctionIO f)) runFunctionIO' :: FunctionIO -> Token a -> DepGenM () runFunctionIO' f input = do _ <- runFunctionIO f input pure () mapDepGenM :: (Token a -> DepGenM' b) -> Token [a] -> DepGenM' [b] mapDepGenM f input = genDependencyM $ \target -> do top <- get let (res, top') = evalDepGenM' top $ do inp <- getListElem input outp <- f inp setListElem outp target put top' pure (makeDependency input (MapComp res) target) mapDepGenM_ :: (Token a -> DepGenM ()) -> Token [a] -> DepGenM () mapDepGenM_ f input = do _ <- mapDepGenM (\x -> f x >> pure NoToken) input pure () filterDepGenM :: (Token a -> DepGenM' Bool) -> Token [a] -> DepGenM' [a] filterDepGenM f input = do conds <- mapDepGenM f input genDependency (makeDependency (TupleToken (input, conds)) FilterComp) joinPaths :: (Token FilePath, Token FilePath) -> DepGenM' FilePath joinPaths = runFunction JoinPaths . TupleToken isImageFilename :: Token FilePath -> DepGenM' Bool isImageFilename = runFunction IsImageFilename convertedImageFilename :: Token FilePath -> DepGenM' FilePath convertedImageFilename = runFunction ConvertedImageFilename applyTemplate :: (Token Template, Token String) -> DepGenM' String applyTemplate = runFunction ApplyTemplate . TupleToken listDirectory :: Token FilePath -> DepGenM' [FilePath] listDirectory = runFunctionIO ListDirectory readTemplate :: Token FilePath -> DepGenM' Template readTemplate = runFunctionIO ReadTemplate convertImage :: (Token (FilePath, FilePath), Token ImageConversionSettings) -> DepGenM () convertImage = runFunctionIO' ConvertImage . TupleToken saveFile :: (Token String, Token FilePath) -> DepGenM () saveFile = runFunctionIO' SaveFile . TupleToken makeDir :: Token FilePath -> DepGenM () makeDir = runFunctionIO' MakeDir runPandoc :: Token FilePath -> DepGenM' String runPandoc = runFunctionIO RunPandoc