181 lines
5.3 KiB
Haskell
181 lines
5.3 KiB
Haskell
{-# LANGUAGE GADTs #-}
|
|
{-# LANGUAGE FunctionalDependencies #-}
|
|
module DependencyGenerator
|
|
( DepGenM
|
|
, DepGenM'
|
|
, TokenableTo(..)
|
|
, toTupleToken
|
|
, evalDepGenM
|
|
, inject
|
|
, runFunction
|
|
, runFunctionIO
|
|
, runFunctionIO_
|
|
, mapDepGenM
|
|
, mapDepGenM_
|
|
, forDepGenM
|
|
, forDepGenM_
|
|
, filterDepGenM
|
|
, filterDepGenM'
|
|
, zipDepGenM
|
|
, untupleFstDepGenM
|
|
, untupleSndDepGenM
|
|
, untupleDepGenM
|
|
, unzipFstDepGenM
|
|
, unzipSndDepGenM
|
|
, unzipDepGenM
|
|
) where
|
|
|
|
import Prelude hiding (String, FilePath)
|
|
|
|
import Types.Token (Token(..))
|
|
import Types.Value (Valuable(..))
|
|
import Types.FunctionIO (IsFunctionIO(..))
|
|
import Types.Function (IsFunction(..))
|
|
import Types.Dependency (Action(..), Dependency, makeDependency, makeUToken)
|
|
|
|
import Control.Monad.State (MonadState, State, runState, put, get)
|
|
import Control.Monad.Writer (MonadWriter, WriterT, runWriterT, 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)
|
|
|
|
runDepGenM :: Int -> DepGenM a -> ((a, [Dependency]), Int)
|
|
runDepGenM top m = runState (runWriterT (unDepGenM m)) top
|
|
|
|
evalDepGenM :: DepGenM () -> [Dependency]
|
|
evalDepGenM = snd . fst . runDepGenM 0
|
|
|
|
tellDep :: Dependency -> DepGenM ()
|
|
tellDep dep = tell [dep]
|
|
|
|
newToken :: DepGenM (Token a)
|
|
newToken = do
|
|
top <- get
|
|
let top' = top + 1
|
|
target = Token top'
|
|
put top'
|
|
pure target
|
|
|
|
genDependencyM :: (Token a -> DepGenM Dependency) -> DepGenM (Token a)
|
|
genDependencyM f = do
|
|
target <- newToken
|
|
result <- f target
|
|
tellDep result
|
|
pure target
|
|
|
|
genDependency :: (Token a -> Dependency) -> DepGenM (Token a)
|
|
genDependency f = genDependencyM (pure . f)
|
|
|
|
inject :: Valuable a => a -> DepGenM (Token a)
|
|
inject x = genDependency (makeDependency NoToken (Inject (toValue x)))
|
|
|
|
runFunction :: IsFunction f a b => f -> Token a -> DepGenM (Token b)
|
|
runFunction f input = genDependency (makeDependency input (Function f))
|
|
|
|
runFunctionIO :: IsFunctionIO f a b => f -> Token a -> DepGenM (Token b)
|
|
runFunctionIO f input = genDependency (makeDependency input (FunctionIO f))
|
|
|
|
runFunctionIO_ :: IsFunctionIO f a () => f -> Token a -> DepGenM ()
|
|
runFunctionIO_ f input = tellDep $ makeDependency input (FunctionIO f) NoToken
|
|
|
|
class TokenableTo t s | s -> t where
|
|
toToken :: s -> DepGenM (Token t)
|
|
|
|
instance TokenableTo a (Token a) where
|
|
toToken = pure
|
|
|
|
instance TokenableTo [a] [Token a] where
|
|
toToken = pure . ListToken
|
|
|
|
instance TokenableTo a (DepGenM (Token a)) where
|
|
toToken = id
|
|
|
|
instance TokenableTo [a] [DepGenM (Token a)] where
|
|
toToken = fmap ListToken . sequence
|
|
|
|
toTupleToken :: (TokenableTo ta a, TokenableTo tb b) => a -> b -> DepGenM (Token (ta, tb))
|
|
toTupleToken a b = TupleToken <$> toToken a <*> toToken b
|
|
|
|
mapDepGenM :: TokenableTo [a] v => (Token a -> DepGenM (Token b)) -> v -> DepGenM (Token [b])
|
|
mapDepGenM f input = do
|
|
input' <- toToken input
|
|
genDependencyM $ \target -> do
|
|
top <- get
|
|
let (((innerInp, innerOutp), subDeps), top') = runDepGenM top $ do
|
|
inp <- newToken
|
|
outp <- f inp
|
|
pure (inp, outp)
|
|
put top'
|
|
pure (makeDependency input' (MapComp subDeps (makeUToken innerInp) (makeUToken innerOutp)) target)
|
|
|
|
mapDepGenM_ :: TokenableTo [a] v => (Token a -> DepGenM ()) -> v -> DepGenM ()
|
|
mapDepGenM_ f input = do
|
|
_ <- mapDepGenM (\x -> f x >> pure NoToken) input
|
|
pure ()
|
|
|
|
forDepGenM :: TokenableTo [a] v => v -> (Token a -> DepGenM (Token b)) -> DepGenM (Token [b])
|
|
forDepGenM = flip mapDepGenM
|
|
|
|
forDepGenM_ :: TokenableTo [a] v => v -> (Token a -> DepGenM ()) -> DepGenM ()
|
|
forDepGenM_ = flip mapDepGenM_
|
|
|
|
filterDepGenM' :: (TokenableTo [Bool] v, TokenableTo [a] u) => v -> u -> DepGenM (Token [a])
|
|
filterDepGenM' mask input = do
|
|
tup <- toTupleToken input mask
|
|
genDependency (makeDependency tup FilterComp)
|
|
|
|
filterDepGenM :: TokenableTo [a] v => (Token a -> DepGenM (Token Bool)) -> v -> DepGenM (Token [a])
|
|
filterDepGenM f input = do
|
|
mask <- mapDepGenM f input
|
|
filterDepGenM' mask input
|
|
|
|
zipDepGenM :: (TokenableTo [a] v, TokenableTo [b] u) => v -> u -> DepGenM (Token [(a, b)])
|
|
zipDepGenM a b = do
|
|
a' <- toToken a
|
|
b' <- toToken b
|
|
pure $ ZipToken a' b'
|
|
|
|
untupleFstDepGenM :: TokenableTo (a, b) t => t -> DepGenM (Token a)
|
|
untupleFstDepGenM t = do
|
|
t' <- toToken t
|
|
case t' of
|
|
TupleToken a _ -> pure a
|
|
Token _ -> genDependency (makeDependency t' UntupleFst)
|
|
|
|
untupleSndDepGenM :: TokenableTo (a, b) t => t -> DepGenM (Token b)
|
|
untupleSndDepGenM t = do
|
|
t' <- toToken t
|
|
case t' of
|
|
TupleToken _ b -> pure b
|
|
Token _ -> genDependency (makeDependency t' UntupleSnd)
|
|
|
|
untupleDepGenM :: TokenableTo (a, b) t => t -> DepGenM (Token a, Token b)
|
|
untupleDepGenM t = do
|
|
t' <- toToken t
|
|
a <- untupleFstDepGenM t'
|
|
b <- untupleSndDepGenM t'
|
|
pure (a, b)
|
|
|
|
unzipFstDepGenM :: TokenableTo [(a, b)] t => t -> DepGenM (Token [a])
|
|
unzipFstDepGenM t = do
|
|
t' <- toToken t
|
|
case t' of
|
|
ZipToken a _ -> pure a
|
|
_ -> genDependency (makeDependency t' UnzipFst)
|
|
|
|
unzipSndDepGenM :: TokenableTo [(a, b)] t => t -> DepGenM (Token [b])
|
|
unzipSndDepGenM t = do
|
|
t' <- toToken t
|
|
case t' of
|
|
ZipToken _ b -> pure b
|
|
_ -> genDependency (makeDependency t' UnzipSnd)
|
|
|
|
unzipDepGenM :: TokenableTo [(a, b)] t => t -> DepGenM (Token [a], Token [b])
|
|
unzipDepGenM t = do
|
|
t' <- toToken t
|
|
a <- unzipFstDepGenM t'
|
|
b <- unzipSndDepGenM t'
|
|
pure (a, b)
|