{- |
   Module     : Development.Shake.Plus.Oracle
   License    : MIT
   Stability  : experimental

Oracle utilities in "Development.Shake" lifted to `MonadAction` and `MonadRules`.
-}
module Development.Shake.Plus.Oracle (
  addOracle
, addOracleCache
, addOracleHash
, askOracle
, askOracles
, Development.Shake.RuleResult
) where

import           Control.Exception.Extra
import qualified Development.Shake
import           Development.Shake.Plus.Core
import           RIO

-- | Lifted version of `Development.Shake.addOracle` using `RAction` runner.
addOracle :: (MonadRules m, MonadReader r m, RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial)
          => (q -> RAction r a)
          -> m (q -> RAction r a)
addOracle :: (q -> RAction r a) -> m (q -> RAction r a)
addOracle q -> RAction r a
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
ask m r -> (r -> m (q -> RAction r a)) -> m (q -> RAction r a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules (q -> RAction r a) -> m (q -> RAction r a))
-> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall a b. (a -> b) -> a -> b
$ (Action a -> RAction r a
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action a -> RAction r a) -> (q -> Action a) -> q -> RAction r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ) ((q -> Action a) -> q -> RAction r a)
-> Rules (q -> Action a) -> Rules (q -> RAction r a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (q -> Action a) -> Rules (q -> Action a)
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
Development.Shake.addOracle (r -> RAction r a -> Action a
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r (RAction r a -> Action a) -> (q -> RAction r a) -> q -> Action a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. q -> RAction r a
ract)

-- | Lifted version of `Development.Shake.addOracleCache` using `RAction` runner.
addOracleCache :: (MonadRules m, MonadReader r m, RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial)
               => (q -> RAction r a)
               -> m (q -> RAction r a)
addOracleCache :: (q -> RAction r a) -> m (q -> RAction r a)
addOracleCache q -> RAction r a
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
ask m r -> (r -> m (q -> RAction r a)) -> m (q -> RAction r a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules (q -> RAction r a) -> m (q -> RAction r a))
-> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall a b. (a -> b) -> a -> b
$ (Action a -> RAction r a
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action a -> RAction r a) -> (q -> Action a) -> q -> RAction r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ) ((q -> Action a) -> q -> RAction r a)
-> Rules (q -> Action a) -> Rules (q -> RAction r a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (q -> Action a) -> Rules (q -> Action a)
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
Development.Shake.addOracleCache (r -> RAction r a -> Action a
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r (RAction r a -> Action a) -> (q -> RAction r a) -> q -> Action a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. q -> RAction r a
ract)

-- | Lifted version of `Development.Shake.addOracleHash` using `RAction` runner.
addOracleHash :: (MonadRules m, MonadReader r m, RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial)
               => (q -> RAction r a)
               -> m (q -> RAction r a)
addOracleHash :: (q -> RAction r a) -> m (q -> RAction r a)
addOracleHash q -> RAction r a
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
ask m r -> (r -> m (q -> RAction r a)) -> m (q -> RAction r a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules (q -> RAction r a) -> m (q -> RAction r a))
-> Rules (q -> RAction r a) -> m (q -> RAction r a)
forall a b. (a -> b) -> a -> b
$ (Action a -> RAction r a
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action a -> RAction r a) -> (q -> Action a) -> q -> RAction r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ) ((q -> Action a) -> q -> RAction r a)
-> Rules (q -> Action a) -> Rules (q -> RAction r a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (q -> Action a) -> Rules (q -> Action a)
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) =>
(q -> Action a) -> Rules (q -> Action a)
Development.Shake.addOracleHash (r -> RAction r a -> Action a
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r (RAction r a -> Action a) -> (q -> RAction r a) -> q -> Action a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. q -> RAction r a
ract)

-- | Lifted version of `Development.Shake.askOracle`.
askOracle :: (MonadAction m, RuleResult q ~ a, ShakeValue q, ShakeValue a) => q -> m a
askOracle :: q -> m a
askOracle = Action a -> m a
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action a -> m a) -> (q -> Action a) -> q -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. q -> Action a
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a) =>
q -> Action a
Development.Shake.askOracle

-- | Lifted version of `Development.Shake.askOracles`.
askOracles :: (MonadAction m, RuleResult q ~ a, ShakeValue q, ShakeValue a) => [q]-> m [a]
askOracles :: [q] -> m [a]
askOracles = Action [a] -> m [a]
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action [a] -> m [a]) -> ([q] -> Action [a]) -> [q] -> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [q] -> Action [a]
forall q a.
(RuleResult q ~ a, ShakeValue q, ShakeValue a) =>
[q] -> Action [a]
Development.Shake.askOracles