{-# LANGUAGE Safe #-}
{-# LANGUAGE DataKinds, ConstraintKinds, MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleInstances, UndecidableInstances, TypeFamilies, TypeOperators, CPP #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
{-# OPTIONS_HADDOCK hide #-}
module Text.Gigaparsec.Internal.Token.BitBounds (
module Text.Gigaparsec.Internal.Token.BitBounds
) where
import Data.Kind (Constraint)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import Numeric.Natural (Natural)
#if __GLASGOW_HASKELL__ >= 904
import GHC.TypeLits (type (<=?), Nat)
import GHC.TypeError (TypeError, ErrorMessage(Text, (:<>:), ShowType), Assert)
#else
import GHC.TypeLits (type (<=?), Nat, TypeError, ErrorMessage(Text, (:<>:), ShowType))
type Assert :: Bool -> Constraint -> Constraint
type family Assert b c where
Assert 'True _ = ()
Assert 'False c = c
#endif
type Bits :: *
data Bits
= B8
| B16
| B32
| B64
type BitWidth :: * -> Bits
type family BitWidth t where
BitWidth Integer = 'B64
BitWidth Int = 'B64
BitWidth Word = 'B64
BitWidth Word64 = 'B64
BitWidth Natural = 'B64
BitWidth Int32 = 'B32
BitWidth Word32 = 'B32
BitWidth Int16 = 'B16
BitWidth Word16 = 'B16
BitWidth Int8 = 'B8
BitWidth Word8 = 'B8
BitWidth t = TypeError ('Text "The type '" ' :<>: 'ShowType t
':<>: 'Text "' is not a numeric type supported by Gigaparsec")
type SignednessK :: *
data SignednessK = Signed | Unsigned
type Signedness :: * -> SignednessK -> Constraint
type family Signedness t s where
Signedness Integer _ = ()
Signedness Int 'Signed = ()
Signedness Word 'Unsigned = ()
Signedness Word64 'Unsigned = ()
Signedness Natural 'Unsigned = ()
Signedness Int32 'Signed = ()
Signedness Word32 'Unsigned = ()
Signedness Int16 'Signed = ()
Signedness Word16 'Unsigned = ()
Signedness Int8 'Signed = ()
Signedness Word8 'Unsigned = ()
Signedness t 'Signed = TypeError ('Text "The type '" ':<>: 'ShowType t
':<>: 'Text "' does not hold signed numbers")
Signedness t 'Unsigned = TypeError ('Text "The type '" ' :<>: 'ShowType t
':<>: 'Text "' does not hold unsigned numbers")
type ShowBits :: Bits -> ErrorMessage
type ShowBits b = 'ShowType (BitsNat b)
type HasWidthFor :: Bits -> * -> Constraint
type family HasWidthFor bits t where
HasWidthFor bits t = Assert (BitsNat bits <=? BitsNat (BitWidth t))
(TypeError ('Text "The type '"
':<>: 'ShowType t ' :<>: 'Text "' cannot store a "
':<>: ShowBits bits ' :<>: 'Text " bit number (only supports up to "
':<>: ShowBits (BitWidth t) ' :<>: 'Text " bits)."))
type BitBounds :: Bits -> Constraint
class BitBounds b where
upperSigned :: Integer
lowerSigned :: Integer
upperUnsigned :: Integer
bits :: Bits
type BitsNat b :: Nat
instance BitBounds 'B8 where
upperSigned :: Integer
upperSigned = Int8 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Int8)
lowerSigned :: Integer
lowerSigned = Int8 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound @Int8)
upperUnsigned :: Integer
upperUnsigned = Word8 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Word8)
bits :: Bits
bits = Bits
B8
type BitsNat 'B8 = 8
instance BitBounds 'B16 where
upperSigned :: Integer
upperSigned = Int16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Int16)
lowerSigned :: Integer
lowerSigned = Int16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound @Int16)
upperUnsigned :: Integer
upperUnsigned = Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Word16)
bits :: Bits
bits = Bits
B16
type BitsNat 'B16 = 16
instance BitBounds 'B32 where
upperSigned :: Integer
upperSigned = Int32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Int32)
lowerSigned :: Integer
lowerSigned = Int32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound @Int32)
upperUnsigned :: Integer
upperUnsigned = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Word32)
bits :: Bits
bits = Bits
B32
type BitsNat 'B32 = 32
instance BitBounds 'B64 where
upperSigned :: Integer
upperSigned = Int64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Int64)
lowerSigned :: Integer
lowerSigned = Int64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound @Int64)
upperUnsigned :: Integer
upperUnsigned = Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound @Word64)
bits :: Bits
bits = Bits
B64
type BitsNat 'B64 = 64
type CanHoldSigned :: Bits -> * -> Constraint
class (BitBounds bits, Num t) => CanHoldSigned bits t where
instance (BitBounds bits, Num t, Signedness t 'Signed, HasWidthFor bits t) => CanHoldSigned bits t
type CanHoldUnsigned :: Bits -> * -> Constraint
class (BitBounds bits, Num t) => CanHoldUnsigned bits t where
instance (BitBounds bits, Num t, Signedness t 'Unsigned, HasWidthFor bits t) => CanHoldUnsigned bits t