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

-- | Boolean operators.

{-# LANGUAGE Safe #-}

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

--------------------------------------------------------------------------------

true :: Stream Bool
true :: Stream Bool
true = Bool -> Stream Bool
forall a. Typed a => a -> Stream a
constant Bool
True

false :: Stream Bool
false :: Stream Bool
false = Bool -> Stream Bool
forall a. Typed a => a -> Stream a
constant Bool
False

infixr 4 &&

(&&) :: 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 a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
Op2 Op2 Bool Bool Bool
Core.And Stream Bool
x Stream Bool
y

infixr 4 ||

(||) :: 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 a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
Op2 Op2 Bool Bool Bool
Core.Or Stream Bool
x Stream Bool
y

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 a b. (Typed a, Typed b) => Op1 a b -> Stream a -> Stream b
Op1 Op1 Bool Bool
Core.Not Stream Bool
x

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 )

(==>) :: 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

--------------------------------------------------------------------------------