{-# LANGUAGE NoGeneralizedNewtypeDeriving #-}
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Clash.Class.Resize
( Resize(..)
, checkedResize
, checkedFromIntegral
, checkedTruncateB
) where
import Data.Kind (Type)
import Data.Proxy (Proxy(Proxy))
import GHC.Stack (HasCallStack)
import GHC.TypeLits (Nat, KnownNat, type (+))
import Clash.Sized.Internal (formatRange)
class Resize (f :: Nat -> Type) where
resize :: (KnownNat a, KnownNat b) => f a -> f b
extend :: (KnownNat a, KnownNat b) => f a -> f (b + a)
extend = f a -> f (b + a)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f b
resize
zeroExtend :: (KnownNat a, KnownNat b) => f a -> f (b + a)
signExtend :: (KnownNat a, KnownNat b) => f a -> f (b + a)
signExtend = f a -> f (b + a)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f b
resize
truncateB :: KnownNat a => f (a + b) -> f a
checkIntegral ::
forall a b.
HasCallStack =>
(Integral a, Integral b, Bounded b) =>
Proxy b ->
a -> ()
checkIntegral :: Proxy b -> a -> ()
checkIntegral Proxy b
Proxy a
v =
if a -> Integer
forall a. Integral a => a -> Integer
toInteger a
v Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> b -> Integer
forall a. Integral a => a -> Integer
toInteger (Bounded b => b
forall a. Bounded a => a
maxBound @b)
Bool -> Bool -> Bool
|| a -> Integer
forall a. Integral a => a -> Integer
toInteger a
v Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< b -> Integer
forall a. Integral a => a -> Integer
toInteger (Bounded b => b
forall a. Bounded a => a
minBound @b) then
[Char] -> ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> ()) -> [Char] -> ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Given integral " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Integer -> [Char]
forall a. Show a => a -> [Char]
show (a -> Integer
forall a. Integral a => a -> Integer
toInteger a
v) [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" is out of bounds for" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<>
[Char]
" target type. Bounds of target type are: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<>
Integer -> Integer -> [Char]
forall a. (Ord a, Show a) => a -> a -> [Char]
formatRange (b -> Integer
forall a. Integral a => a -> Integer
toInteger (Bounded b => b
forall a. Bounded a => a
minBound @b)) (b -> Integer
forall a. Integral a => a -> Integer
toInteger (Bounded b => b
forall a. Bounded a => a
maxBound @b)) [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
"."
else
()
checkedFromIntegral ::
forall a b.
HasCallStack =>
(Integral a, Integral b, Bounded b) =>
a -> b
checkedFromIntegral :: a -> b
checkedFromIntegral a
v =
Proxy b -> a -> ()
forall a b.
(HasCallStack, Integral a, Integral b, Bounded b) =>
Proxy b -> a -> ()
checkIntegral (Proxy b
forall k (t :: k). Proxy t
Proxy @b) a
v () -> b -> b
`seq` a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
v
checkedResize ::
forall a b f.
( HasCallStack
, Resize f
, KnownNat a, Integral (f a)
, KnownNat b, Integral (f b), Bounded (f b) ) =>
f a -> f b
checkedResize :: f a -> f b
checkedResize f a
v =
Proxy (f b) -> f a -> ()
forall a b.
(HasCallStack, Integral a, Integral b, Bounded b) =>
Proxy b -> a -> ()
checkIntegral (Proxy (f b)
forall k (t :: k). Proxy t
Proxy @(f b)) f a
v () -> f b -> f b
`seq` f a -> f b
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f b
resize f a
v
checkedTruncateB ::
forall a b f.
( HasCallStack
, Resize f
, KnownNat b, Integral (f (a + b))
, KnownNat a, Integral (f a), Bounded (f a) ) =>
f (a + b) -> f a
checkedTruncateB :: f (a + b) -> f a
checkedTruncateB f (a + b)
v =
Proxy (f a) -> f (a + b) -> ()
forall a b.
(HasCallStack, Integral a, Integral b, Bounded b) =>
Proxy b -> a -> ()
checkIntegral (Proxy (f a)
forall k (t :: k). Proxy t
Proxy @(f a)) f (a + b)
v () -> f a -> f a
`seq` f (a + b) -> f a
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a) =>
f (a + b) -> f a
truncateB f (a + b)
v