mad/byg/src/DependencyRunner.hs

116 lines
3.7 KiB
Haskell
Raw Normal View History

{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE PatternSynonyms #-}
2024-09-27 20:39:27 +02:00
module DependencyRunner
2024-09-27 21:13:16 +02:00
( DepRunM
, runDeps
, runDepRunMIO
2024-09-27 20:39:27 +02:00
) where
import Types (evalFunction, evalFunctionIO)
import Types.Value
import Types.Token
2024-09-27 20:39:27 +02:00
import Types.Dependency
import Type.Reflection (Typeable, TypeRep, typeRep, pattern App)
2024-09-27 20:39:27 +02:00
import Data.Map (Map)
import qualified Data.Map as M
import Control.Monad (void, forM)
2024-09-27 21:13:16 +02:00
import Control.Monad.State (MonadState, MonadIO, StateT, evalStateT, get, modify, liftIO)
2024-09-27 20:39:27 +02:00
2024-10-06 00:40:54 +02:00
data ValueExistence = Evaluated Value
| NotEvaluated (DepRunM Value)
newtype DepRunM a = DepRunM { unDepRunM :: StateT (Map Int ValueExistence) IO a }
deriving (Functor, Applicative, Monad, MonadIO, MonadState (Map Int ValueExistence))
2024-09-27 20:39:27 +02:00
runDeps :: [Dependency] -> DepRunM ()
runDeps = mapM_ runDep
runDepRunMIO :: DepRunM a -> IO a
runDepRunMIO m = evalStateT (unDepRunM m) M.empty
2024-09-27 21:13:16 +02:00
2024-10-06 00:40:54 +02:00
evaluate :: ValueExistence -> DepRunM Value
evaluate = \case
Evaluated v -> pure v
NotEvaluated m -> m
2024-09-27 20:39:27 +02:00
runDep :: Dependency -> DepRunM ()
runDep (Dependency _ a action _ b) =
2024-10-06 00:40:54 +02:00
if actionTouchesFilesystem action
then void m
else putTokenValue b $ NotEvaluated m
where m :: DepRunM Value
m = do
input <- getTokenValue a
result <- runAction action input
putTokenValue b $ Evaluated result
liftIO $ do
putStrLn ("input: " ++ show input)
putStrLn ("action: " ++ show action)
putStrLn ("output: " ++ show result)
putStrLn "----------"
pure result
2024-09-27 20:39:27 +02:00
getTokenValue :: (Typeable a, Show a) => Token a -> DepRunM Value
getTokenValue token = case token of
Token i -> do
2024-09-27 20:39:27 +02:00
m <- get
2024-10-06 00:40:54 +02:00
evaluate (m M.! i)
TupleToken a b -> do
2024-09-27 20:39:27 +02:00
va <- getTokenValue a
vb <- getTokenValue b
pure $ toValueRep (tokenTypeRep token) (fromValue va, fromValue vb)
ZipToken a b -> do
2024-09-27 20:39:27 +02:00
va <- getTokenValue a
vb <- getTokenValue b
pure $ toValueRep (tokenTypeRep token) $ zip (fromValue va) (fromValue vb)
ListToken ts -> do
vs <- mapM getTokenValue ts
pure $ toValueRep (tokenTypeRep token) (map fromValue vs)
NoToken ->
pure $ toValue ()
2024-09-27 20:39:27 +02:00
putTokenValue :: Token a -> ValueExistence -> DepRunM ()
2024-10-06 00:40:54 +02:00
putTokenValue t e = case t of
Token i ->
2024-10-06 00:40:54 +02:00
modify $ M.insert i e
NoToken ->
2024-09-27 20:39:27 +02:00
pure ()
_ ->
error "unexpected"
tupApp :: TypeRep a -> TypeRep b -> TypeRep (a, b)
tupApp ta tb = App (App (typeRep @(,)) ta) tb
listApp :: TypeRep a -> TypeRep [a]
listApp ta = App (typeRep @[]) ta
2024-10-14 20:50:55 +02:00
runAction :: Action a b -> Value -> DepRunM Value
2024-09-27 20:39:27 +02:00
runAction action input = case action of
Function f ->
2024-10-06 15:53:40 +02:00
pure $ toValue $ evalFunction f $ fromValue input
InlineFunction ta tb (F f) ->
pure $ toValueRep tb $ f $ fromValueRep ta input
2024-09-27 20:39:27 +02:00
FunctionIO f ->
liftIO (toValue <$> evalFunctionIO f (fromValue input))
2024-09-27 20:39:27 +02:00
Inject v ->
pure v
FilterComp t ->
let tl = listApp t
(vs, mask) = fromValueRep (tupApp tl (typeRep @[Bool])) input
in pure $ toValueRep tl $ map fst $ filter snd $ zip vs mask
UntupleFst ta tb ->
pure $ toValueRep ta $ fst $ fromValueRep (tupApp ta tb) input
UntupleSnd ta tb ->
pure $ toValueRep tb $ snd $ fromValueRep (tupApp ta tb) input
UnzipFst ta tb ->
pure $ toValueRep (listApp ta) $ map fst $ fromValueRep (listApp (tupApp ta tb)) input
UnzipSnd ta tb ->
pure $ toValueRep (listApp tb) $ map snd $ fromValueRep (listApp (tupApp ta tb)) input
MapComp ta tb subDeps innerInput innerOutput ->
(toValueRep (listApp tb) <$>) $ forM (fromValueRep (listApp ta) input) $ \x -> do
putTokenValue innerInput $ Evaluated $ toValueRep ta x
runDeps subDeps
fromValueRep tb <$> getTokenValue innerOutput