    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric #-}

    module Distribution.Types.Condition (
        Condition(..),
        cNot,
        cAnd,
        cOr,
        simplifyCondition,
    ) where

    import Prelude ()
    import Distribution.Compat.Prelude

    -- | A boolean expression parameterized over the variable type used.
    data Condition c = Var c
                     | Lit Bool
                     | CNot (Condition c)
                     | COr (Condition c) (Condition c)
                     | CAnd (Condition c) (Condition c)
        deriving (Int -> Condition c -> ShowS
    forall c. Show c => Int -> Condition c -> ShowS
    forall c. Show c => [Condition c] -> ShowS
    forall c. Show c => Condition c -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [Condition c] -> ShowS
    $cshowList :: forall c. Show c => [Condition c] -> ShowS
    show :: Condition c -> String
    $cshow :: forall c. Show c => Condition c -> String
    showsPrec :: Int -> Condition c -> ShowS
    $cshowsPrec :: forall c. Show c => Int -> Condition c -> ShowS
    Show, Condition c -> Condition c -> Bool
    forall c. Eq c => Condition c -> Condition c -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Condition c -> Condition c -> Bool
    $c/= :: forall c. Eq c => Condition c -> Condition c -> Bool
    == :: Condition c -> Condition c -> Bool
    $c== :: forall c. Eq c => Condition c -> Condition c -> Bool
    Eq, Typeable, Condition c -> DataType
    Condition c -> Constr
    forall {c}. Data c => Typeable (Condition c)
    forall c. Data c => Condition c -> DataType
    forall c. Data c => Condition c -> Constr
    forall c.
    Data c =>
    (forall b. Data b => b -> b) -> Condition c -> Condition c
    forall c u.
    Data c =>
    Int -> (forall d. Data d => d -> u) -> Condition c -> u
    forall c u.
    Data c =>
    (forall d. Data d => d -> u) -> Condition c -> [u]
    forall c r r'.
    Data c =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    forall c r r'.
    Data c =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    forall c (m :: * -> *).
    (Data c, Monad m) =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    forall c (m :: * -> *).
    (Data c, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    forall c (c :: * -> *).
    Data c =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Condition c)
    forall c (c :: * -> *).
    Data c =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Condition c -> c (Condition c)
    forall c (t :: * -> *) (c :: * -> *).
    (Data c, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (Condition c))
    forall c (t :: * -> * -> *) (c :: * -> *).
    (Data c, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Condition c))
    forall a.
    Typeable a
    -> (forall (c :: * -> *).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Condition c)
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Condition c -> c (Condition c)
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Condition c))
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    $cgmapMo :: forall c (m :: * -> *).
    (Data c, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    $cgmapMp :: forall c (m :: * -> *).
    (Data c, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    $cgmapM :: forall c (m :: * -> *).
    (Data c, Monad m) =>
    (forall d. Data d => d -> m d) -> Condition c -> m (Condition c)
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Condition c -> u
    $cgmapQi :: forall c u.
    Data c =>
    Int -> (forall d. Data d => d -> u) -> Condition c -> u
    gmapQ :: forall u. (forall d. Data d => d -> u) -> Condition c -> [u]
    $cgmapQ :: forall c u.
    Data c =>
    (forall d. Data d => d -> u) -> Condition c -> [u]
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    $cgmapQr :: forall c r r'.
    Data c =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    $cgmapQl :: forall c r r'.
    Data c =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Condition c -> r
    gmapT :: (forall b. Data b => b -> b) -> Condition c -> Condition c
    $cgmapT :: forall c.
    Data c =>
    (forall b. Data b => b -> b) -> Condition c -> Condition c
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Condition c))
    $cdataCast2 :: forall c (t :: * -> * -> *) (c :: * -> *).
    (Data c, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Condition c))
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Condition c))
    $cdataCast1 :: forall c (t :: * -> *) (c :: * -> *).
    (Data c, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (Condition c))
    dataTypeOf :: Condition c -> DataType
    $cdataTypeOf :: forall c. Data c => Condition c -> DataType
    toConstr :: Condition c -> Constr
    $ctoConstr :: forall c. Data c => Condition c -> Constr
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Condition c)
    $cgunfold :: forall c (c :: * -> *).
    Data c =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Condition c)
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Condition c -> c (Condition c)
    $cgfoldl :: forall c (c :: * -> *).
    Data c =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Condition c -> c (Condition c)
    Data, forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall c x. Rep (Condition c) x -> Condition c
    forall c x. Condition c -> Rep (Condition c) x
    $cto :: forall c x. Rep (Condition c) x -> Condition c
    $cfrom :: forall c x. Condition c -> Rep (Condition c) x
    Generic)

    -- | Boolean negation of a 'Condition' value.
    cNot :: Condition a -> Condition a
    cNot :: forall a. Condition a -> Condition a
    cNot (Lit Bool
    b)  = forall c. Bool -> Condition c
    Lit (Bool -> Bool
    not Bool
    b)
    cNot (CNot Condition a
    c) = Condition a
    c
    cNot Condition a
    c        = forall a. Condition a -> Condition a
    CNot Condition a
    c

    -- | Boolean AND of two 'Condtion' values.
    cAnd :: Condition a -> Condition a -> Condition a
    cAnd :: forall a. Condition a -> Condition a -> Condition a
    cAnd (Lit Bool
    False) Condition a
    _           = forall c. Bool -> Condition c
    Lit Bool
    False
    cAnd Condition a
    _           (Lit Bool
    False) = forall c. Bool -> Condition c
    Lit Bool
    False
    cAnd (Lit Bool
    True)  Condition a
    x           = Condition a
    x
    cAnd Condition a
    x           (Lit Bool
    True)  = Condition a
    x
    cAnd Condition a
    x           Condition a
    y           = forall a. Condition a -> Condition a -> Condition a
    CAnd Condition a
    x Condition a
    y

    -- | Boolean OR of two 'Condition' values.
    cOr :: Eq v => Condition v -> Condition v -> Condition v
    cOr :: forall v. Eq v => Condition v -> Condition v -> Condition v
    cOr  (Lit Bool
    True)  Condition v
    _           = forall c. Bool -> Condition c
    Lit Bool
    True
    cOr  Condition v
    _           (Lit Bool
    True)  = forall c. Bool -> Condition c
    Lit Bool
    True
    cOr  (Lit Bool
    False) Condition v
    x           = Condition v
    x
    cOr  Condition v
    x           (Lit Bool
    False) = Condition v
    x
    cOr  Condition v
    c           (CNot Condition v
    d)
      | Condition v
    c forall a. Eq a => a -> a -> Bool
    == Condition v
    d                   = forall c. Bool -> Condition c
    Lit Bool
    True
    cOr  (CNot Condition v
    c)    Condition v
    d
      | Condition v
    c forall a. Eq a => a -> a -> Bool
    == Condition v
    d                   = forall c. Bool -> Condition c
    Lit Bool
    True
    cOr  Condition v
    x           Condition v
    y           = forall a. Condition a -> Condition a -> Condition a
    COr Condition v
    x Condition v
    y

    instance Functor Condition where
      a -> b
    f fmap :: forall a b. (a -> b) -> Condition a -> Condition b
    `fmap` Var a
    c    = forall c. c -> Condition c
    Var (a -> b
    f a
    c)
      a -> b
    _ `fmap` Lit Bool
    c    = forall c. Bool -> Condition c
    Lit Bool
    c
      a -> b
    f `fmap` CNot Condition a
    c   = forall a. Condition a -> Condition a
    CNot (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f Condition a
    c)
      a -> b
    f `fmap` COr Condition a
    c Condition a
    d  = forall a. Condition a -> Condition a -> Condition a
    COr  (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f Condition a
    c) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f Condition a
    d)
      a -> b
    f `fmap` CAnd Condition a
    c Condition a
    d = forall a. Condition a -> Condition a -> Condition a
    CAnd (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f Condition a
    c) (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f Condition a
    d)

    instance Foldable Condition where
      a -> m
    f foldMap :: forall m a. Monoid m => (a -> m) -> Condition a -> m
    `foldMap` Var a
    c    = a -> m
    f a
    c
      a -> m
    _ `foldMap` Lit Bool
    _    = forall a. Monoid a => a
    mempty
      a -> m
    f `foldMap` CNot Condition a
    c   = forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f Condition a
    c
      a -> m
    f `foldMap` COr Condition a
    c Condition a
    d  = forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f Condition a
    c forall a. Monoid a => a -> a -> a
    `mappend` forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f Condition a
    d
      a -> m
    f `foldMap` CAnd Condition a
    c Condition a
    d = forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f Condition a
    c forall a. Monoid a => a -> a -> a
    `mappend` forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f Condition a
    d

    instance Traversable Condition where
      a -> f b
    f traverse :: forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Condition a -> f (Condition b)
    `traverse` Var a
    c    = forall c. c -> Condition c
    Var forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` a -> f b
    f a
    c
      a -> f b
    _ `traverse` Lit Bool
    c    = forall (f :: * -> *) a. Applicative f => a -> f a
    pure forall a b. (a -> b) -> a -> b
    $ forall c. Bool -> Condition c
    Lit Bool
    c
      a -> f b
    f `traverse` CNot Condition a
    c   = forall a. Condition a -> Condition a
    CNot forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f Condition a
    c
      a -> f b
    f `traverse` COr Condition a
    c Condition a
    d  = forall a. Condition a -> Condition a -> Condition a
    COr  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f Condition a
    c forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f Condition a
    d
      a -> f b
    f `traverse` CAnd Condition a
    c Condition a
    d = forall a. Condition a -> Condition a -> Condition a
    CAnd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f Condition a
    c forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f Condition a
    d

    instance Applicative Condition where
      pure :: forall c. c -> Condition c
    pure  = forall c. c -> Condition c
    Var
      <*> :: forall a b. Condition (a -> b) -> Condition a -> Condition b
    (<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
    ap

    instance Monad Condition where
      return :: forall c. c -> Condition c
    return = forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      -- Terminating cases
      >>= :: forall a b. Condition a -> (a -> Condition b) -> Condition b
    (>>=) (Lit Bool
    x) a -> Condition b
    _ = forall c. Bool -> Condition c
    Lit Bool
    x
      (>>=) (Var a
    x) a -> Condition b
    f = a -> Condition b
    f a
    x
      -- Recursing cases
      (>>=) (CNot  Condition a
    x  ) a -> Condition b
    f = forall a. Condition a -> Condition a
    CNot (Condition a
    x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> Condition b
    f)
      (>>=) (COr   Condition a
    x Condition a
    y) a -> Condition b
    f = forall a. Condition a -> Condition a -> Condition a
    COr  (Condition a
    x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> Condition b
    f) (Condition a
    y forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> Condition b
    f)
      (>>=) (CAnd  Condition a
    x Condition a
    y) a -> Condition b
    f = forall a. Condition a -> Condition a -> Condition a
    CAnd (Condition a
    x forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> Condition b
    f) (Condition a
    y forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> Condition b
    f)

    instance Monoid (Condition a) where
      mempty :: Condition a
    mempty = forall c. Bool -> Condition c
    Lit Bool
    False
      mappend :: Condition a -> Condition a -> Condition a
    mappend = forall a. Semigroup a => a -> a -> a
    (<>)

    instance Semigroup (Condition a) where
      <> :: Condition a -> Condition a -> Condition a
    (<>) = forall a. Condition a -> Condition a -> Condition a
    COr

    instance Alternative Condition where
      empty :: forall a. Condition a
    empty = forall a. Monoid a => a
    mempty
      <|> :: forall a. Condition a -> Condition a -> Condition a
    (<|>) = forall a. Monoid a => a -> a -> a
    mappend

    instance MonadPlus Condition where
      mzero :: forall a. Condition a
    mzero = forall a. Monoid a => a
    mempty
      mplus :: forall a. Condition a -> Condition a -> Condition a
    mplus = forall a. Monoid a => a -> a -> a
    mappend

    instance Binary c => Binary (Condition c)
    instance Structured c => Structured (Condition c)
    instance NFData c => NFData (Condition c) where rnf :: Condition c -> ()
    rnf = forall a. (Generic a, GNFData (Rep a)) => a -> ()
    genericRnf

    -- | Simplify the condition and return its free variables.
    simplifyCondition :: Condition c
                      -> (c -> Either d Bool)   -- ^ (partial) variable assignment
                      -> (Condition d, [d])
    simplifyCondition :: forall c d.
    Condition c -> (c -> Either d Bool) -> (Condition d, [d])
    simplifyCondition Condition c
    cond c -> Either d Bool
    i = forall {a}. Condition a -> (Condition a, [a])
    fv forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Condition c -> Condition d
    walk forall a b. (a -> b) -> a -> b
    $ Condition c
    cond
      where
        walk :: Condition c -> Condition d
    walk Condition c
    cnd = case Condition c
    cnd of
          Var c
    v   -> forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either forall c. c -> Condition c
    Var forall c. Bool -> Condition c
    Lit (c -> Either d Bool
    i c
    v)
          Lit Bool
    b   -> forall c. Bool -> Condition c
    Lit Bool
    b
          CNot Condition c
    c  -> case Condition c -> Condition d
    walk Condition c
    c of
                       Lit Bool
    True -> forall c. Bool -> Condition c
    Lit Bool
    False
                       Lit Bool
    False -> forall c. Bool -> Condition c
    Lit Bool
    True
                       Condition d
    c' -> forall a. Condition a -> Condition a
    CNot Condition d
    c'
          COr Condition c
    c Condition c
    d -> case (Condition c -> Condition d
    walk Condition c
    c, Condition c -> Condition d
    walk Condition c
    d) of
                       (Lit Bool
    False, Condition d
    d') -> Condition d
    d'
                       (Lit Bool
    True, Condition d
    _)   -> forall c. Bool -> Condition c
    Lit Bool
    True
                       (Condition d
    c', Lit Bool
    False) -> Condition d
    c'
                       (Condition d
    _, Lit Bool
    True)   -> forall c. Bool -> Condition c
    Lit Bool
    True
                       (Condition d
    c',Condition d
    d')         -> forall a. Condition a -> Condition a -> Condition a
    COr Condition d
    c' Condition d
    d'
          CAnd Condition c
    c Condition c
    d -> case (Condition c -> Condition d
    walk Condition c
    c, Condition c -> Condition d
    walk Condition c
    d) of
                        (Lit Bool
    False, Condition d
    _) -> forall c. Bool -> Condition c
    Lit Bool
    False
                        (Lit Bool
    True, Condition d
    d') -> Condition d
    d'
                        (Condition d
    _, Lit Bool
    False) -> forall c. Bool -> Condition c
    Lit Bool
    False
                        (Condition d
    c', Lit Bool
    True) -> Condition d
    c'
                        (Condition d
    c',Condition d
    d')        -> forall a. Condition a -> Condition a -> Condition a
    CAnd Condition d
    c' Condition d
    d'
        -- gather free vars
        fv :: Condition a -> (Condition a, [a])
    fv Condition a
    c = (Condition a
    c, forall a. Condition a -> [a]
    fv' Condition a
    c)
        fv' :: Condition a -> [a]
    fv' Condition a
    c = case Condition a
    c of
          Var a
    v     -> [a
    v]
          Lit Bool
    _      -> []
          CNot Condition a
    c'    -> Condition a -> [a]
    fv' Condition a
    c'
          COr Condition a
    c1 Condition a
    c2  -> Condition a -> [a]
    fv' Condition a
    c1 forall a. [a] -> [a] -> [a]
    ++ Condition a -> [a]
    fv' Condition a
    c2
          CAnd Condition a
    c1 Condition a
    c2 -> Condition a -> [a]
    fv' Condition a
    c1 forall a. [a] -> [a] -> [a]
    ++ Condition a -> [a]
    fv' Condition a
    c2