mad/byg/src/Byg/DependencyGenerator.hs

202 lines
6.6 KiB
Haskell
Raw Normal View History

2024-09-28 13:57:53 +02:00
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FunctionalDependencies #-}
2024-11-09 23:13:37 +01:00
-- | Combinators for generating a list of dependencies between calculations, to
-- be executed later in DependencyRunner.
module Byg.DependencyGenerator
2024-09-23 22:11:54 +02:00
( DepGenM
2024-09-24 23:01:07 +02:00
, DepGenM'
, TokenableTo(..)
, toTupleToken
, evalDepGenM
2024-09-23 22:11:54 +02:00
, inject
2024-10-14 22:48:58 +02:00
, onToken
, onTupleToken
2024-09-23 22:11:54 +02:00
, runFunctionIO
, runFunctionIO_
2024-09-23 22:11:54 +02:00
, mapDepGenM
, mapDepGenM_
2024-10-05 22:51:13 +02:00
, forDepGenM
, forDepGenM_
2024-09-23 22:11:54 +02:00
, filterDepGenM
, filterDepGenM'
2024-09-26 23:40:26 +02:00
, zipDepGenM
, untupleFstDepGenM
, untupleSndDepGenM
, untupleDepGenM
2024-09-25 23:06:53 +02:00
, unzipFstDepGenM
, unzipSndDepGenM
, unzipDepGenM
2024-09-23 22:11:54 +02:00
) where
import Byg.Types.Token (Token(..))
import Byg.Types.Functions (IsFunctionIO(..))
import Byg.Types.Dependency (Action(..), F(..), Dependency, makeDependency)
2024-09-23 22:11:54 +02:00
import Type.Reflection (Typeable, TypeRep, typeRep)
2024-09-23 22:11:54 +02:00
import Control.Monad.State (MonadState, State, runState, put, get)
import Control.Monad.Writer (MonadWriter, WriterT, runWriterT, tell)
2024-09-23 22:11:54 +02:00
2024-09-24 23:09:35 +02:00
newtype DepGenM a = DepGenM { unDepGenM :: WriterT [Dependency] (State Int) a }
2024-09-23 22:11:54 +02:00
deriving (Functor, Applicative, Monad, MonadState Int, MonadWriter [Dependency])
2024-09-24 23:09:35 +02:00
type DepGenM' a = DepGenM (Token a)
2024-09-23 22:11:54 +02:00
runDepGenM :: Int -> DepGenM a -> ((a, [Dependency]), Int)
runDepGenM top m = runState (runWriterT (unDepGenM m)) top
2024-09-23 22:11:54 +02:00
2024-09-24 23:09:35 +02:00
evalDepGenM :: DepGenM () -> [Dependency]
evalDepGenM = snd . fst . runDepGenM 0
2024-09-23 22:11:54 +02:00
2024-09-24 23:09:35 +02:00
tellDep :: Dependency -> DepGenM ()
2024-09-23 22:11:54 +02:00
tellDep dep = tell [dep]
newToken :: (Typeable a, Show a) => DepGenM (Token a)
newToken = do
2024-09-23 22:11:54 +02:00
top <- get
let top' = top + 1
target = Token top'
put top'
pure target
genDependencyM :: (Typeable a, Show a) => (Token a -> DepGenM Dependency) -> DepGenM (Token a)
genDependencyM f = do
target <- newToken
2024-09-23 22:11:54 +02:00
result <- f target
tellDep result
pure target
genDependency :: (Typeable a, Show a) => (Token a -> Dependency) -> DepGenM (Token a)
2024-09-23 22:11:54 +02:00
genDependency f = genDependencyM (pure . f)
inject :: (Show a, Typeable a) => a -> DepGenM (Token a)
2024-10-14 22:15:27 +02:00
inject x = genDependency (makeDependency NoToken (Inject x))
2024-09-23 22:11:54 +02:00
2024-10-14 22:48:58 +02:00
onToken :: (TokenableTo a t, Show a, Typeable a, Show b, Typeable b) => (a -> b) -> t -> DepGenM (Token b)
onToken f input = do
input' <- toToken input
genDependency (makeDependency input' (Function (F f)))
2024-10-14 22:48:58 +02:00
onTupleToken :: (TokenableTo a t1, Show a, Typeable a, TokenableTo b t2, Show b, Typeable b, Show r, Typeable r) => (a -> b -> r) -> t1 -> t2 -> DepGenM (Token r)
onTupleToken f input1 input2 = do
tup <- toTupleToken input1 input2
genDependency (makeDependency tup (Function (F (uncurry f))))
2024-09-23 22:11:54 +02:00
runFunctionIO :: IsFunctionIO f a b => f -> Token a -> DepGenM (Token b)
2024-09-23 22:11:54 +02:00
runFunctionIO f input = genDependency (makeDependency input (FunctionIO f))
2024-10-06 13:44:19 +02:00
runFunctionIO_ :: IsFunctionIO f a () => f -> Token a -> DepGenM ()
2024-10-06 13:06:34 +02:00
runFunctionIO_ f input = tellDep $ makeDependency input (FunctionIO f) NoToken
2024-09-25 19:45:10 +02:00
class (Show t, Typeable t) => TokenableTo t s | s -> t where
toToken :: s -> DepGenM (Token t)
tokenTypeRep :: s -> TypeRep t
2024-10-05 19:56:53 +02:00
instance (Show a, Typeable a) => TokenableTo a (Token a) where
2024-10-05 19:56:53 +02:00
toToken = pure
tokenTypeRep _ = typeRep
2024-10-05 19:56:53 +02:00
instance (Show a, Typeable a) => TokenableTo [a] [Token a] where
toToken = pure . ListToken
tokenTypeRep _ = typeRep
instance (Show a, Typeable a) => TokenableTo a (DepGenM (Token a)) where
2024-10-05 19:56:53 +02:00
toToken = id
tokenTypeRep _ = typeRep
2024-10-05 19:56:53 +02:00
instance (Show a, Typeable a) => TokenableTo [a] [DepGenM (Token a)] where
toToken = fmap ListToken . sequence
tokenTypeRep _ = typeRep
toTupleToken :: (TokenableTo ta a, TokenableTo tb b) => a -> b -> DepGenM (Token (ta, tb))
2024-10-05 19:56:53 +02:00
toTupleToken a b = TupleToken <$> toToken a <*> toToken b
mapDepGenM :: (TokenableTo [a] v, Typeable a, Show a, Typeable b, Show b) => (Token a -> DepGenM (Token b)) -> v -> DepGenM (Token [b])
2024-09-26 23:40:26 +02:00
mapDepGenM f input = do
input' <- toToken input
genDependencyM $ \target -> do
top <- get
let (((innerInp, innerOutp), subDeps), top') = runDepGenM top $ do
inp <- newToken
2024-09-26 23:40:26 +02:00
outp <- f inp
pure (inp, outp)
2024-09-26 23:40:26 +02:00
put top'
2024-10-14 22:15:27 +02:00
pure (makeDependency input' (MapComp subDeps innerInp innerOutp) target)
2024-09-26 23:40:26 +02:00
mapDepGenM_ :: (TokenableTo [a] v, Typeable a, Show a) => (Token a -> DepGenM ()) -> v -> DepGenM ()
2024-09-23 22:11:54 +02:00
mapDepGenM_ f input = do
2024-09-24 23:01:07 +02:00
_ <- mapDepGenM (\x -> f x >> pure NoToken) input
2024-09-24 22:23:43 +02:00
pure ()
2024-09-23 22:11:54 +02:00
forDepGenM :: (TokenableTo [a] v, Typeable a, Show a, Typeable b, Show b) => v -> (Token a -> DepGenM (Token b)) -> DepGenM (Token [b])
2024-10-05 22:51:13 +02:00
forDepGenM = flip mapDepGenM
forDepGenM_ :: (TokenableTo [a] v, Typeable a, Show a) => v -> (Token a -> DepGenM ()) -> DepGenM ()
2024-10-05 22:51:13 +02:00
forDepGenM_ = flip mapDepGenM_
filterDepGenM' :: (TokenableTo [Bool] v, TokenableTo [a] u, Typeable a, Show a) => v -> u -> DepGenM (Token [a])
filterDepGenM' mask input = do
2024-10-05 20:20:16 +02:00
tup <- toTupleToken input mask
2024-10-14 22:15:27 +02:00
genDependency (makeDependency tup FilterComp)
2024-09-26 23:40:26 +02:00
filterDepGenM :: (TokenableTo [a] v, Typeable a, Show a) => (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, Typeable a, Show a, Typeable b, Show b) => v -> u -> DepGenM (Token [(a, b)])
2024-09-26 23:40:26 +02:00
zipDepGenM a b = do
a' <- toToken a
b' <- toToken b
2024-10-05 19:44:28 +02:00
pure $ ZipToken a' b'
2024-09-23 22:11:54 +02:00
untupleFstDepGenM :: (TokenableTo (a, b) t, Typeable a, Show a, Typeable b, Show b) => t -> DepGenM (Token a)
untupleFstDepGenM t = do
t' <- toToken t
case t' of
TupleToken a _ ->
pure a
Token _ ->
2024-10-14 22:15:27 +02:00
genDependency (makeDependency t' UntupleFst)
untupleSndDepGenM :: (TokenableTo (a, b) t, Typeable a, Show a, Typeable b, Show b) => t -> DepGenM (Token b)
untupleSndDepGenM t = do
t' <- toToken t
case t' of
TupleToken _ b ->
pure b
Token _ ->
2024-10-14 22:15:27 +02:00
genDependency (makeDependency t' UntupleSnd)
untupleDepGenM :: (TokenableTo (a, b) t, Typeable a, Show a, Typeable b, Show b) => 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, Typeable a, Show a, Typeable b, Show b) => t -> DepGenM (Token [a])
2024-09-25 23:06:53 +02:00
unzipFstDepGenM t = do
t' <- toToken t
case t' of
ZipToken a _ ->
pure a
_ ->
2024-10-14 22:15:27 +02:00
genDependency (makeDependency t' UnzipFst)
unzipSndDepGenM :: (TokenableTo [(a, b)] t, Typeable a, Show a, Typeable b, Show b) => t -> DepGenM (Token [b])
2024-09-25 23:06:53 +02:00
unzipSndDepGenM t = do
t' <- toToken t
case t' of
ZipToken _ b ->
pure b
_ ->
2024-10-14 22:15:27 +02:00
genDependency (makeDependency t' UnzipSnd)
unzipDepGenM :: (TokenableTo [(a, b)] t, Typeable a, Show a, Typeable b, Show b) => t -> DepGenM (Token [a], Token [b])
2024-09-25 23:06:53 +02:00
unzipDepGenM t = do
t' <- toToken t
a <- unzipFstDepGenM t'
b <- unzipSndDepGenM t'
pure (a, b)