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

{-# 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
import Data.Bits

-- | 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 a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
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 a b. (Typed a, Typed b) => Op1 a b -> Stream a -> Stream b
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 a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
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 a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
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"

-- | See 'xor'.
(.^.) :: Bits a => a -> a -> a
.^. :: a -> a -> a
(.^.) = a -> a -> a
forall a. Bits a => a -> a -> a
xor -- Avoid redefinition of the Operators.Boolean xor

-- | Shifting values of a stream to the left.
(.<<.) :: (Bits a, Typed a, Typed b, P.Integral b)
       => Stream a -> Stream b -> Stream a
.<<. :: Stream a -> Stream b -> Stream a
(.<<.) = Op2 a b a -> Stream a -> Stream b -> Stream a
forall a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
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
.>>. :: Stream a -> Stream b -> Stream a
(.>>.) = Op2 a b a -> Stream a -> Stream b -> Stream a
forall a b c.
(Typed a, Typed b, Typed c) =>
Op2 a b c -> Stream a -> Stream b -> Stream c
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)