    -- Copyright © 2011 National Institute of Aerospace / Galois, Inc.

    {-# LANGUAGE Safe #-}

    -- | Boolean operators applied point-wise to streams.
    module Copilot.Language.Operators.Boolean
      ( (&&)
      , (||)
      , not
      , true
      , false
      , xor
      , (==>)
      ) where

    import qualified Copilot.Core as Core
    import Copilot.Language.Prelude
    import Copilot.Language.Operators.Constant (constant)
    import Copilot.Language.Stream
    import qualified Prelude as P

    -- | A stream that contains the constant value 'True'.
    true :: Stream Bool
    true :: Stream Bool
    true = Bool -> Stream Bool
    forall a. Typed a => a -> Stream a
    constant Bool
    True

    -- | A stream that contains the constant value 'False'.
    false :: Stream Bool
    false :: Stream Bool
    false = Bool -> Stream Bool
    forall a. Typed a => a -> Stream a
    constant Bool
    False

    infixr 4 &&

    -- | Apply the and ('&&') operator to two boolean streams, point-wise.
    (&&) :: Stream Bool -> Stream Bool -> Stream Bool
    (Const Bool
    False) && :: Stream Bool -> Stream Bool -> Stream Bool
    && Stream Bool
    _ = Stream Bool
    false
    Stream Bool
    _ && (Const Bool
    False) = Stream Bool
    false
    (Const Bool
    True) && Stream Bool
    y  = Stream Bool
    y
    Stream Bool
    x && (Const Bool
    True)  = Stream Bool
    x
    Stream Bool
    x && Stream Bool
    y             = Op2 Bool Bool Bool -> Stream Bool -> Stream Bool -> Stream Bool
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 Op2 Bool Bool Bool
    Core.And Stream Bool
    x Stream Bool
    y

    infixr 4 ||

    -- | Apply the or ('||') operator to two boolean streams, point-wise.
    (||) :: Stream Bool -> Stream Bool -> Stream Bool
    (Const Bool
    True) || :: Stream Bool -> Stream Bool -> Stream Bool
    || Stream Bool
    _  = Stream Bool
    true
    Stream Bool
    _ || (Const Bool
    True)  = Stream Bool
    true
    (Const Bool
    False) || Stream Bool
    y = Stream Bool
    y
    Stream Bool
    x || (Const Bool
    False) = Stream Bool
    x
    Stream Bool
    x || Stream Bool
    y             = Op2 Bool Bool Bool -> Stream Bool -> Stream Bool -> Stream Bool
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 Op2 Bool Bool Bool
    Core.Or Stream Bool
    x Stream Bool
    y

    -- | Negate all the values in a boolean stream.
    not :: Stream Bool -> Stream Bool
    not :: Stream Bool -> Stream Bool
    not (Const Bool
    c) = (Bool -> Stream Bool
    forall a. Typed a => a -> Stream a
    Const (Bool -> Stream Bool) -> Bool -> Stream Bool
    forall a b. (a -> b) -> a -> b
    $ Bool -> Bool
    P.not Bool
    c)
    not Stream Bool
    x         = Op1 Bool Bool -> Stream Bool -> Stream Bool
    forall a1 a.
    (Typed a1, Typed a) =>
    Op1 a1 a -> Stream a1 -> Stream a
    Op1 Op1 Bool Bool
    Core.Not Stream Bool
    x

    -- | Apply the exclusive-or ('xor') operator to two boolean streams,
    -- point-wise.
    xor :: Stream Bool -> Stream Bool -> Stream Bool
    xor :: Stream Bool -> Stream Bool -> Stream Bool
    xor Stream Bool
    x Stream Bool
    y = ( Stream Bool -> Stream Bool
    not Stream Bool
    x Stream Bool -> Stream Bool -> Stream Bool
    && Stream Bool
    y ) Stream Bool -> Stream Bool -> Stream Bool
    || ( Stream Bool
    x Stream Bool -> Stream Bool -> Stream Bool
    && Stream Bool -> Stream Bool
    not Stream Bool
    y )

    -- | Apply the implication ('==>') operator to two boolean streams, point-wise.
    (==>) :: Stream Bool -> Stream Bool -> Stream Bool
    Stream Bool
    x ==> :: Stream Bool -> Stream Bool -> Stream Bool
    ==> Stream Bool
    y = Stream Bool -> Stream Bool
    not Stream Bool
    x Stream Bool -> Stream Bool -> Stream Bool
    || Stream Bool
    y