{-# LANGUAGE FlexibleInstances #-}

module HaskellWorks.Data.BalancedParens.OpenAt
  ( OpenAt(..)
  ) where

import Data.Word
import HaskellWorks.Data.Bits.BitLength
import HaskellWorks.Data.Bits.BitShown
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Bits.Broadword.Type
import HaskellWorks.Data.Naive
import HaskellWorks.Data.Positioning

import qualified Data.Vector.Storable as DVS

class OpenAt v where
  openAt :: v -> Count -> Bool

openAt' :: (BitLength a, TestBit a) => a -> Count -> Bool
openAt' :: forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt' a
v Count
c = (Count
0 forall a. Ord a => a -> a -> Bool
<= Count
c Bool -> Bool -> Bool
&& Count
c forall a. Ord a => a -> a -> Bool
< forall v. BitLength v => v -> Count
bitLength a
v) Bool -> Bool -> Bool
&& (a
v forall a. TestBit a => a -> Position -> Bool
.?. forall a. ToPosition a => a -> Position
toPosition (Count
c forall a. Num a => a -> a -> a
- Count
1))
{-# INLINE openAt' #-}

instance (BitLength a, TestBit a) => OpenAt (BitShown a) where
  openAt :: BitShown a -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. BitShown a -> a
bitShown
  {-# INLINE openAt #-}

instance OpenAt [Bool] where
  openAt :: [Bool] -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (DVS.Vector Word8) where
  openAt :: Vector Word8 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (DVS.Vector Word16) where
  openAt :: Vector Word16 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (DVS.Vector Word32) where
  openAt :: Vector Word32 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (DVS.Vector Word64) where
  openAt :: Vector Count -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt Word8 where
  openAt :: Word8 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt Word16 where
  openAt :: Word16 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt Word32 where
  openAt :: Word32 -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt Word64 where
  openAt :: Count -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (Naive Word64) where
  openAt :: Naive Count -> Count -> Bool
openAt = forall a. (BitLength a, TestBit a) => a -> Count -> Bool
openAt'
  {-# INLINE openAt #-}

instance OpenAt (Broadword Word64) where
  openAt :: Broadword Count -> Count -> Bool
openAt = forall v. OpenAt v => v -> Count -> Bool
openAt forall b c a. (b -> c) -> (a -> b) -> a -> c
. Broadword Count -> Count
broadword
  {-# INLINE openAt #-}