content: {-|
  Copyright  :  (C) 2013-2016, University of Twente
                    2022-2024, Google Inc.
  License    :  BSD2 (see the file LICENSE)
  Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>
  -}
  
  {-# LANGUAGE Trustworthy #-}
  {-# LANGUAGE TypeFamilies #-}
  
  {-# OPTIONS_HADDOCK show-extensions #-}
  
  module Clash.Sized.BitVector
    ( -- * Bit
      Bit
      -- ** Construction
      -- *** Initialisation
    , high
    , low
      -- * BitVector
    , BitVector
      -- ** Accessors
      -- *** Length information
    , size#
    , maxIndex#
      -- ** Construction
    , bLit
    , hLit
    , oLit
      -- ** Concatenation
    , (++#)
      -- * Modification
    , (+>>.)
    , (.<<+)
      -- ** Pattern matching
    , bitPattern
    )
  where
  
  import Clash.Sized.Internal.BitVector
  import Clash.Promoted.Nat (SNat(..), SNatLE(..), compareSNat, natToNum)
  import Data.Bits (shiftL, shiftR)
  import GHC.TypeNats (KnownNat)
  
  {- $setup
  >>> :set -XNumericUnderscores
  -}
  
  infixr 4 +>>.
  -- | Shift in a bit from the MSB side of a 'BitVector'. Equal to right shifting
  -- the 'BitVector' by one and replacing the MSB with the bit to be shifted in.
  --
  -- >>> 1 +>>. 0b1111_0000 :: BitVector 8
  -- 0b1111_1000
  -- >>> 0 +>>. 0b1111_0000 :: BitVector 8
  -- 0b0111_1000
  --
  (+>>.) :: forall n. KnownNat n => Bit -> BitVector n -> BitVector n
  b +>>. bv = case compareSNat (SNat @n) (SNat @0) of
    SNatGT -> replaceBit# (shiftR bv 1) (natToNum @n - 1) b
    SNatLE -> bv
  
  infixr 4 .<<+
  -- | Shift in a bit from the LSB side of a 'BitVector'. Equal to left shifting
  -- the 'BitVector' by one and replacing the LSB with the bit to be shifted in.
  --
  -- >>> 0b1111_0000 .<<+ 0 :: BitVector 8
  -- 0b1110_0000
  -- >>> 0b1111_0000 .<<+ 1 :: BitVector 8
  -- 0b1110_0001
  --
  (.<<+) :: forall n. KnownNat n => BitVector n -> Bit -> BitVector n
  bv .<<+ b = case compareSNat (SNat @n) (SNat @0) of
    SNatGT -> replaceBit# (shiftL bv 1) 0 b
    SNatLE -> bv
  