{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Test.BDD.LanguageFree
( given
, givenAndAfter_
, givenAndAfter
, then_
, then__
, when_
, GivenFree
, ThenFree
, FreeBDD
, testFreeBDD
, BDDResult (..)
)
where
import Control.Monad.Catch
import Control.Monad.Free
import Control.Monad.Reader
data Phase t = Preparing | Testing t
data Language m a where
Given :: m a -> (a -> Language m 'Preparing) -> Language m 'Preparing
GivenAndAfter
:: m (a, r)
-> (r -> m ())
-> (a -> Language m 'Preparing)
-> Language m 'Preparing
When :: m t -> Language m ('Testing t) -> Language m 'Preparing
Then
:: (t -> m ()) -> Language m ('Testing t) -> Language m ('Testing t)
End :: Language m x
And
:: Language m 'Preparing
-> Language m 'Preparing
-> Language m 'Preparing
data BDDResult m = Failed SomeException (m ()) | Succeded (m ())
type CJR m = ReaderT (m ()) m (BDDResult m)
catchCJR :: (MonadCatch m) => CJR m -> CJR m
catchCJR :: forall (m :: * -> *). MonadCatch m => CJR m -> CJR m
catchCJR CJR m
f = CJR m -> (SomeException -> CJR m) -> CJR m
forall e a.
(HasCallStack, Exception e) =>
ReaderT (m ()) m a
-> (e -> ReaderT (m ()) m a) -> ReaderT (m ()) m a
forall (m :: * -> *) e a.
(MonadCatch m, HasCallStack, Exception e) =>
m a -> (e -> m a) -> m a
catch CJR m
f ((SomeException -> CJR m) -> CJR m)
-> (SomeException -> CJR m) -> CJR m
forall a b. (a -> b) -> a -> b
$ (m () -> BDDResult m) -> CJR m
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ((m () -> BDDResult m) -> CJR m)
-> (SomeException -> m () -> BDDResult m) -> SomeException -> CJR m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> m () -> BDDResult m
forall (m :: * -> *). SomeException -> m () -> BDDResult m
Failed
stepIn :: (MonadCatch m) => m a -> (a -> CJR m) -> CJR m
stepIn :: forall (m :: * -> *) a.
MonadCatch m =>
m a -> (a -> CJR m) -> CJR m
stepIn m a
g a -> CJR m
q = CJR m -> CJR m
forall (m :: * -> *). MonadCatch m => CJR m -> CJR m
catchCJR (m a -> ReaderT (m ()) m a
forall (m :: * -> *) a. Monad m => m a -> ReaderT (m ()) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m a
g ReaderT (m ()) m a -> (a -> CJR m) -> CJR m
forall a b.
ReaderT (m ()) m a
-> (a -> ReaderT (m ()) m b) -> ReaderT (m ()) m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> CJR m
q)
releaseThen :: (MonadCatch m) => m () -> m () -> m ()
releaseThen :: forall (m :: * -> *). MonadCatch m => m () -> m () -> m ()
releaseThen m ()
release m ()
rest =
m () -> m (Either SomeException ())
forall (m :: * -> *) e a.
(HasCallStack, MonadCatch m, Exception e) =>
m a -> m (Either e a)
try m ()
release m (Either SomeException ())
-> (Either SomeException () -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Right () -> m ()
rest
Left (SomeException
e :: SomeException) -> do
(_ :: Either SomeException ()) <- m () -> m (Either SomeException ())
forall (m :: * -> *) e a.
(HasCallStack, MonadCatch m, Exception e) =>
m a -> m (Either e a)
try m ()
rest
throwM e
interpret
:: forall m. (MonadCatch m) => Language m 'Preparing -> m (BDDResult m)
interpret :: forall (m :: * -> *).
MonadCatch m =>
Language m 'Preparing -> m (BDDResult m)
interpret Language m 'Preparing
y = ReaderT (m ()) m (BDDResult m) -> m () -> m (BDDResult m)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' Language m 'Preparing
y) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
where
interpret' :: Language m 'Preparing -> CJR m
interpret' :: Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' (Given m a
g a -> Language m 'Preparing
p) = m a
-> (a -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall (m :: * -> *) a.
MonadCatch m =>
m a -> (a -> CJR m) -> CJR m
stepIn m a
g ((a -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m))
-> (a -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' (Language m 'Preparing -> ReaderT (m ()) m (BDDResult m))
-> (a -> Language m 'Preparing)
-> a
-> ReaderT (m ()) m (BDDResult m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Language m 'Preparing
p
interpret' (GivenAndAfter m (a, r)
g r -> m ()
z a -> Language m 'Preparing
p) =
m (a, r)
-> ((a, r) -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall (m :: * -> *) a.
MonadCatch m =>
m a -> (a -> CJR m) -> CJR m
stepIn m (a, r)
g (((a, r) -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m))
-> ((a, r) -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ \(a
x, r
r) -> (m () -> m ())
-> ReaderT (m ()) m (BDDResult m) -> ReaderT (m ()) m (BDDResult m)
forall a.
(m () -> m ()) -> ReaderT (m ()) m a -> ReaderT (m ()) m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (m () -> m () -> m ()
forall (m :: * -> *). MonadCatch m => m () -> m () -> m ()
releaseThen (m () -> m () -> m ()) -> m () -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ r -> m ()
z r
r) (ReaderT (m ()) m (BDDResult m) -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m) -> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' (Language m 'Preparing -> ReaderT (m ()) m (BDDResult m))
-> Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ a -> Language m 'Preparing
p a
x
interpret' (When m t
fa Language m ('Testing t)
p) =
m t
-> (t -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall (m :: * -> *) a.
MonadCatch m =>
m a -> (a -> CJR m) -> CJR m
stepIn m t
fa ((t -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m))
-> (t -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ \t
x -> t -> Language m ('Testing t) -> ReaderT (m ()) m (BDDResult m)
forall t.
t -> Language m ('Testing t) -> ReaderT (m ()) m (BDDResult m)
interpretT' t
x Language m ('Testing t)
p
interpret' (And Language m 'Preparing
f Language m 'Preparing
g) = do
r <- Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' Language m 'Preparing
f
case r of
Succeded m ()
_ -> Language m 'Preparing -> ReaderT (m ()) m (BDDResult m)
interpret' Language m 'Preparing
g
BDDResult m
w -> BDDResult m -> ReaderT (m ()) m (BDDResult m)
forall a. a -> ReaderT (m ()) m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure BDDResult m
w
interpret' Language m 'Preparing
End = (m () -> BDDResult m) -> ReaderT (m ()) m (BDDResult m)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks m () -> BDDResult m
forall (m :: * -> *). m () -> BDDResult m
Succeded
interpretT' :: t -> Language m ('Testing t) -> CJR m
interpretT' :: forall t.
t -> Language m ('Testing t) -> ReaderT (m ()) m (BDDResult m)
interpretT' t
_ Language m ('Testing t)
End = (m () -> BDDResult m) -> ReaderT (m ()) m (BDDResult m)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks m () -> BDDResult m
forall (m :: * -> *). m () -> BDDResult m
Succeded
interpretT' t
x (Then t -> m ()
f Language m ('Testing t)
p) =
m ()
-> (() -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall (m :: * -> *) a.
MonadCatch m =>
m a -> (a -> CJR m) -> CJR m
stepIn (t -> m ()
f t
t
x) ((() -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m))
-> (() -> ReaderT (m ()) m (BDDResult m))
-> ReaderT (m ()) m (BDDResult m)
forall a b. (a -> b) -> a -> b
$ \() -> t -> Language m ('Testing t) -> ReaderT (m ()) m (BDDResult m)
forall t.
t -> Language m ('Testing t) -> ReaderT (m ()) m (BDDResult m)
interpretT' t
x Language m ('Testing t)
Language m ('Testing t)
p
data GivenFree m a where
GivenFree :: m b -> (b -> a) -> GivenFree m a
GivenAndAfterFree
:: m (b, r) -> (r -> m ()) -> (b -> a) -> GivenFree m a
WhenFree :: m t -> Free (ThenFree m t) c -> a -> GivenFree m a
data ThenFree m t a
= ThenFree (t -> m ()) a
deriving ((forall a b. (a -> b) -> ThenFree m t a -> ThenFree m t b)
-> (forall a b. a -> ThenFree m t b -> ThenFree m t a)
-> Functor (ThenFree m t)
forall a b. a -> ThenFree m t b -> ThenFree m t a
forall a b. (a -> b) -> ThenFree m t a -> ThenFree m t b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
forall (m :: * -> *) t a b. a -> ThenFree m t b -> ThenFree m t a
forall (m :: * -> *) t a b.
(a -> b) -> ThenFree m t a -> ThenFree m t b
$cfmap :: forall (m :: * -> *) t a b.
(a -> b) -> ThenFree m t a -> ThenFree m t b
fmap :: forall a b. (a -> b) -> ThenFree m t a -> ThenFree m t b
$c<$ :: forall (m :: * -> *) t a b. a -> ThenFree m t b -> ThenFree m t a
<$ :: forall a b. a -> ThenFree m t b -> ThenFree m t a
Functor)
instance Functor (GivenFree m) where
fmap :: forall a b. (a -> b) -> GivenFree m a -> GivenFree m b
fmap a -> b
f (GivenFree m b
m b -> a
x) = m b -> (b -> b) -> GivenFree m b
forall (m :: * -> *) t a. m t -> (t -> a) -> GivenFree m a
GivenFree m b
m ((b -> b) -> GivenFree m b) -> (b -> b) -> GivenFree m b
forall a b. (a -> b) -> a -> b
$ a -> b
f (a -> b) -> (b -> a) -> b -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> a
x
fmap a -> b
f (GivenAndAfterFree m (b, r)
mr r -> m ()
rm b -> a
x) = m (b, r) -> (r -> m ()) -> (b -> b) -> GivenFree m b
forall (m :: * -> *) t r a.
m (t, r) -> (r -> m ()) -> (t -> a) -> GivenFree m a
GivenAndAfterFree m (b, r)
mr r -> m ()
rm ((b -> b) -> GivenFree m b) -> (b -> b) -> GivenFree m b
forall a b. (a -> b) -> a -> b
$ a -> b
f (a -> b) -> (b -> a) -> b -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> a
x
fmap a -> b
f (WhenFree m t
mt Free (ThenFree m t) c
ft a
x) = m t -> Free (ThenFree m t) c -> b -> GivenFree m b
forall (m :: * -> *) t r a.
m t -> Free (ThenFree m t) r -> a -> GivenFree m a
WhenFree m t
mt Free (ThenFree m t) c
ft (b -> GivenFree m b) -> b -> GivenFree m b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
x
type FreeBDD m x = Free (GivenFree m) x
given :: m a -> Free (GivenFree m) a
given :: forall (m :: * -> *) a. m a -> Free (GivenFree m) a
given m a
m = GivenFree m a -> Free (GivenFree m) a
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (GivenFree m a -> Free (GivenFree m) a)
-> GivenFree m a -> Free (GivenFree m) a
forall a b. (a -> b) -> a -> b
$ m a -> (a -> a) -> GivenFree m a
forall (m :: * -> *) t a. m t -> (t -> a) -> GivenFree m a
GivenFree m a
m a -> a
forall a. a -> a
id
givenAndAfter :: m (b, r) -> (r -> m ()) -> Free (GivenFree m) b
givenAndAfter :: forall (m :: * -> *) b r.
m (b, r) -> (r -> m ()) -> Free (GivenFree m) b
givenAndAfter m (b, r)
g r -> m ()
td = GivenFree m b -> Free (GivenFree m) b
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (GivenFree m b -> Free (GivenFree m) b)
-> GivenFree m b -> Free (GivenFree m) b
forall a b. (a -> b) -> a -> b
$ m (b, r) -> (r -> m ()) -> (b -> b) -> GivenFree m b
forall (m :: * -> *) t r a.
m (t, r) -> (r -> m ()) -> (t -> a) -> GivenFree m a
GivenAndAfterFree m (b, r)
g r -> m ()
td b -> b
forall a. a -> a
id
givenAndAfter_
:: (Functor m) => m r -> (r -> m ()) -> Free (GivenFree m) ()
givenAndAfter_ :: forall (m :: * -> *) r.
Functor m =>
m r -> (r -> m ()) -> Free (GivenFree m) ()
givenAndAfter_ m r
g r -> m ()
td = GivenFree m () -> Free (GivenFree m) ()
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (GivenFree m () -> Free (GivenFree m) ())
-> GivenFree m () -> Free (GivenFree m) ()
forall a b. (a -> b) -> a -> b
$ m ((), r) -> (r -> m ()) -> (() -> ()) -> GivenFree m ()
forall (m :: * -> *) t r a.
m (t, r) -> (r -> m ()) -> (t -> a) -> GivenFree m a
GivenAndAfterFree (((),) (r -> ((), r)) -> m r -> m ((), r)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m r
g) r -> m ()
td () -> ()
forall a. a -> a
id
when_ :: m t -> Free (ThenFree m t) b -> Free (GivenFree m) ()
when_ :: forall (m :: * -> *) t b.
m t -> Free (ThenFree m t) b -> Free (GivenFree m) ()
when_ m t
mt Free (ThenFree m t) b
ts = GivenFree m () -> Free (GivenFree m) ()
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (GivenFree m () -> Free (GivenFree m) ())
-> GivenFree m () -> Free (GivenFree m) ()
forall a b. (a -> b) -> a -> b
$ m t -> Free (ThenFree m t) b -> () -> GivenFree m ()
forall (m :: * -> *) t r a.
m t -> Free (ThenFree m t) r -> a -> GivenFree m a
WhenFree m t
mt Free (ThenFree m t) b
ts ()
thens :: Free (ThenFree m t) a -> Language m ('Testing t)
thens :: forall (m :: * -> *) t a.
Free (ThenFree m t) a -> Language m ('Testing t)
thens (Free (ThenFree t -> m ()
m Free (ThenFree m t) a
f)) = (t -> m ()) -> Language m ('Testing t) -> Language m ('Testing t)
forall t (m :: * -> *).
(t -> m ()) -> Language m ('Testing t) -> Language m ('Testing t)
Then t -> m ()
m (Language m ('Testing t) -> Language m ('Testing t))
-> Language m ('Testing t) -> Language m ('Testing t)
forall a b. (a -> b) -> a -> b
$ Free (ThenFree m t) a -> Language m ('Testing t)
forall (m :: * -> *) t a.
Free (ThenFree m t) a -> Language m ('Testing t)
thens Free (ThenFree m t) a
f
thens (Pure a
_) = Language m ('Testing t)
forall (m :: * -> *) (x :: Phase (*)). Language m x
End
bddFree :: Free (GivenFree m) x -> Language m 'Preparing
bddFree :: forall (m :: * -> *) x.
Free (GivenFree m) x -> Language m 'Preparing
bddFree (Free (GivenFree m b
m b -> Free (GivenFree m) x
f)) = m b -> (b -> Language m 'Preparing) -> Language m 'Preparing
forall (m :: * -> *) t.
m t -> (t -> Language m 'Preparing) -> Language m 'Preparing
Given m b
m ((b -> Language m 'Preparing) -> Language m 'Preparing)
-> (b -> Language m 'Preparing) -> Language m 'Preparing
forall a b. (a -> b) -> a -> b
$ Free (GivenFree m) x -> Language m 'Preparing
forall (m :: * -> *) x.
Free (GivenFree m) x -> Language m 'Preparing
bddFree (Free (GivenFree m) x -> Language m 'Preparing)
-> (b -> Free (GivenFree m) x) -> b -> Language m 'Preparing
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> Free (GivenFree m) x
f
bddFree (Free (GivenAndAfterFree m (b, r)
mr r -> m ()
rm b -> Free (GivenFree m) x
f)) =
m (b, r)
-> (r -> m ())
-> (b -> Language m 'Preparing)
-> Language m 'Preparing
forall (m :: * -> *) t r.
m (t, r)
-> (r -> m ())
-> (t -> Language m 'Preparing)
-> Language m 'Preparing
GivenAndAfter m (b, r)
mr r -> m ()
rm ((b -> Language m 'Preparing) -> Language m 'Preparing)
-> (b -> Language m 'Preparing) -> Language m 'Preparing
forall a b. (a -> b) -> a -> b
$ Free (GivenFree m) x -> Language m 'Preparing
forall (m :: * -> *) x.
Free (GivenFree m) x -> Language m 'Preparing
bddFree (Free (GivenFree m) x -> Language m 'Preparing)
-> (b -> Free (GivenFree m) x) -> b -> Language m 'Preparing
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> Free (GivenFree m) x
f
bddFree (Free (WhenFree m t
mt Free (ThenFree m t) c
ts Free (GivenFree m) x
f)) = Language m 'Preparing
-> Language m 'Preparing -> Language m 'Preparing
forall (m :: * -> *).
Language m 'Preparing
-> Language m 'Preparing -> Language m 'Preparing
And (m t -> Language m ('Testing t) -> Language m 'Preparing
forall (m :: * -> *) t.
m t -> Language m ('Testing t) -> Language m 'Preparing
When m t
mt (Language m ('Testing t) -> Language m 'Preparing)
-> Language m ('Testing t) -> Language m 'Preparing
forall a b. (a -> b) -> a -> b
$ Free (ThenFree m t) c -> Language m ('Testing t)
forall (m :: * -> *) t a.
Free (ThenFree m t) a -> Language m ('Testing t)
thens Free (ThenFree m t) c
ts) (Free (GivenFree m) x -> Language m 'Preparing
forall (m :: * -> *) x.
Free (GivenFree m) x -> Language m 'Preparing
bddFree Free (GivenFree m) x
f)
bddFree (Pure x
_) = Language m 'Preparing
forall (m :: * -> *) (x :: Phase (*)). Language m x
End
then_ :: (t -> m ()) -> Free (ThenFree m t) ()
then_ :: forall t (m :: * -> *). (t -> m ()) -> Free (ThenFree m t) ()
then_ t -> m ()
m = ThenFree m t () -> Free (ThenFree m t) ()
forall (f :: * -> *) (m :: * -> *) a.
(Functor f, MonadFree f m) =>
f a -> m a
liftF (ThenFree m t () -> Free (ThenFree m t) ())
-> ThenFree m t () -> Free (ThenFree m t) ()
forall a b. (a -> b) -> a -> b
$ (t -> m ()) -> () -> ThenFree m t ()
forall (m :: * -> *) t a. (t -> m ()) -> a -> ThenFree m t a
ThenFree t -> m ()
m ()
then__ :: m () -> Free (ThenFree m t) ()
then__ :: forall (m :: * -> *) t. m () -> Free (ThenFree m t) ()
then__ = (t -> m ()) -> Free (ThenFree m t) ()
forall t (m :: * -> *). (t -> m ()) -> Free (ThenFree m t) ()
then_ ((t -> m ()) -> Free (ThenFree m t) ())
-> (m () -> t -> m ()) -> m () -> Free (ThenFree m t) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m () -> t -> m ()
forall a b. a -> b -> a
const
testFreeBDD
:: (MonadCatch m)
=> Free (GivenFree m) x
-> m (BDDResult m)
testFreeBDD :: forall (m :: * -> *) x.
MonadCatch m =>
Free (GivenFree m) x -> m (BDDResult m)
testFreeBDD = Language m 'Preparing -> m (BDDResult m)
forall (m :: * -> *).
MonadCatch m =>
Language m 'Preparing -> m (BDDResult m)
interpret (Language m 'Preparing -> m (BDDResult m))
-> (Free (GivenFree m) x -> Language m 'Preparing)
-> Free (GivenFree m) x
-> m (BDDResult m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Free (GivenFree m) x -> Language m 'Preparing
forall (m :: * -> *) x.
Free (GivenFree m) x -> Language m 'Preparing
bddFree