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

    {-# LANGUAGE CPP  #-}
    {-# LANGUAGE Safe #-}

    {-# OPTIONS_GHC -fno-warn-orphans #-}

    -- | Bitwise operators applied on streams, pointwise.
    module Copilot.Language.Operators.BitWise
      ( Bits ((.&.), complement, (.|.))
      , (.^.)
      , (.<<.)
      , (.>>.)
      ) where

    import Copilot.Core (Typed, typeOf)
    import qualified Copilot.Core as Core
    import Copilot.Language.Stream
    import qualified Prelude as P

    #if MIN_VERSION_base(4,17,0)
    import Data.Bits hiding ((.>>.), (.<<.))
    #else
    import Data.Bits
    #endif

    -- | Instance of the 'Bits' class for 'Stream's.
    --
    -- Only the methods '.&.', 'complement', '.|.' and 'xor' are defined.
    instance (Typed a, Bits a) => Bits (Stream a) where
      .&. :: Stream a -> Stream a -> Stream a
    (.&.)        = Op2 a a a -> Stream a -> Stream a -> Stream a
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 (Type a -> Op2 a a a
    forall a. Bits a => Type a -> Op2 a a a
    Core.BwAnd Type a
    forall a. Typed a => Type a
    typeOf)
      complement :: Stream a -> Stream a
    complement   = Op1 a a -> Stream a -> Stream a
    forall a1 a.
    (Typed a1, Typed a) =>
    Op1 a1 a -> Stream a1 -> Stream a
    Op1 (Type a -> Op1 a a
    forall a. Bits a => Type a -> Op1 a a
    Core.BwNot Type a
    forall a. Typed a => Type a
    typeOf)
      .|. :: Stream a -> Stream a -> Stream a
    (.|.)        = Op2 a a a -> Stream a -> Stream a -> Stream a
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 (Type a -> Op2 a a a
    forall a. Bits a => Type a -> Op2 a a a
    Core.BwOr  Type a
    forall a. Typed a => Type a
    typeOf)
      xor :: Stream a -> Stream a -> Stream a
    xor          = Op2 a a a -> Stream a -> Stream a -> Stream a
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 (Type a -> Op2 a a a
    forall a. Bits a => Type a -> Op2 a a a
    Core.BwXor Type a
    forall a. Typed a => Type a
    typeOf)
      shiftL :: Stream a -> Int -> Stream a
    shiftL       = [Char] -> Stream a -> Int -> Stream a
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "shiftL undefined, for left-shifting use .<<."
      shiftR :: Stream a -> Int -> Stream a
    shiftR       = [Char] -> Stream a -> Int -> Stream a
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "shiftR undefined, for right-shifting use .>>."
      rotate :: Stream a -> Int -> Stream a
    rotate       = [Char] -> Stream a -> Int -> Stream a
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: rotate"
      bitSize :: Stream a -> Int
    bitSize      = [Char] -> Stream a -> Int
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: bitSize"
      bitSizeMaybe :: Stream a -> Maybe Int
    bitSizeMaybe = [Char] -> Stream a -> Maybe Int
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: bitSizeMaybe"
      isSigned :: Stream a -> Bool
    isSigned     = [Char] -> Stream a -> Bool
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: issigned"
      testBit :: Stream a -> Int -> Bool
    testBit      = [Char] -> Stream a -> Int -> Bool
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: testBit"
      bit :: Int -> Stream a
    bit          = [Char] -> Int -> Stream a
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: bit"
      popCount :: Stream a -> Int
    popCount     = [Char] -> Stream a -> Int
    forall a. HasCallStack => [Char] -> a
    P.error [Char]
    "tbd: popCount"

    #if !MIN_VERSION_base(4,17,0)
    -- | See 'xor'.
    (.^.) :: Bits a => a -> a -> a
    (.^.) = xor -- Avoid redefinition of the Operators.Boolean xor
    #endif

    -- | Shifting values of a stream to the left.
    (.<<.) :: (Bits a, Typed a, Typed b, P.Integral b)
           => Stream a -> Stream b -> Stream a
    .<<. :: forall a b.
    (Bits a, Typed a, Typed b, Integral b) =>
    Stream a -> Stream b -> Stream a
    (.<<.) = Op2 a b a -> Stream a -> Stream b -> Stream a
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 (Type a -> Type b -> Op2 a b a
    forall a b. (Bits a, Integral b) => Type a -> Type b -> Op2 a b a
    Core.BwShiftL Type a
    forall a. Typed a => Type a
    typeOf Type b
    forall a. Typed a => Type a
    typeOf)

    -- | Shifting values of a stream to the right.
    (.>>.) :: (Bits a, Typed a, Typed b, P.Integral b)
           => Stream a -> Stream b -> Stream a
    .>>. :: forall a b.
    (Bits a, Typed a, Typed b, Integral b) =>
    Stream a -> Stream b -> Stream a
    (.>>.) = Op2 a b a -> Stream a -> Stream b -> Stream a
    forall a1 b a.
    (Typed a1, Typed b, Typed a) =>
    Op2 a1 b a -> Stream a1 -> Stream b -> Stream a
    Op2 (Type a -> Type b -> Op2 a b a
    forall a b. (Bits a, Integral b) => Type a -> Type b -> Op2 a b a
    Core.BwShiftR Type a
    forall a. Typed a => Type a
    typeOf Type b
    forall a. Typed a => Type a
    typeOf)