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)) 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, FilePath) -> DepGenM' FilePath joinPaths = runFunction JoinPaths isImageFilename :: Token FilePath -> DepGenM' Bool isImageFilename = runFunction IsImageFilename convertedImageFilename :: Token FilePath -> DepGenM' FilePath convertedImageFilename = runFunction ConvertedImageFilename applyTemplate :: Token (Template, String) -> DepGenM' String applyTemplate = runFunction ApplyTemplate listDirectory :: Token FilePath -> DepGenM' [FilePath] listDirectory = runFunctionIO ListDirectory readTemplate :: Token FilePath -> DepGenM' Template readTemplate = runFunctionIO ReadTemplate convertImage :: Token ((FilePath, FilePath), ImageConversionSettings) -> DepGenM () convertImage input = do _ <- runFunctionIO ConvertImage input pure () saveFile :: Token (String, FilePath) -> DepGenM () saveFile input = do _ <- runFunctionIO SaveFile input pure () makeDir :: Token FilePath -> DepGenM () makeDir input = do _ <- runFunctionIO MakeDir input pure () runPandoc :: Token FilePath -> DepGenM' String runPandoc = runFunctionIO RunPandoc