fortran-src-0.16.9: src/Language/Fortran/Repr/Value/Scalar/Int/Idealized.hs
{- | Idealized Fortran INTEGER values.
This module stores Fortran INTEGER values in a Haskell 'Integer', together with
a phantom type describing the Fortran kind. This way, we can safely check for
bounds issues, and leave exact behaviour up to the user.
-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeFamilyDependencies #-} -- just for better inference (maybe)
{-# LANGUAGE DerivingVia #-}
module Language.Fortran.Repr.Value.Scalar.Int.Idealized where
import Language.Fortran.Repr.Type.Scalar.Int
import Data.Kind
import Data.Int
import GHC.Generics ( Generic )
import Data.Data ( Data )
import Data.Binary ( Binary )
import Text.PrettyPrint.GenericPretty ( Out )
type FIntMRep :: FTInt -> Type
type family FIntMRep k = r | r -> k where
FIntMRep 'FTInt1 = Int8
FIntMRep 'FTInt2 = Int16
FIntMRep 'FTInt4 = Int32
FIntMRep 'FTInt8 = Int64
newtype FIntI (k :: FTInt) = FIntI Integer
deriving stock (Show, Generic, Data)
deriving (Eq, Ord) via Integer
deriving anyclass (Binary, Out)
fIntICheckBounds
:: forall k rep. (rep ~ FIntMRep k, Bounded rep, Integral rep)
=> FIntI k -> Maybe String
fIntICheckBounds (FIntI i) =
if i > fromIntegral (maxBound @rep)
then Just "TODO too large"
else if i < fromIntegral (minBound @rep)
then Just "TODO too small"
else Nothing
data SomeFIntI = forall fk. SomeFIntI (FIntI fk)
deriving stock instance Show SomeFIntI
instance Eq SomeFIntI where
(SomeFIntI (FIntI l)) == (SomeFIntI (FIntI r)) = l == r
-- this might look silly, but it's because even if we don't do kinded
-- calculations, we must still kind the output
someFIntIBOpWrap
:: (Integer -> Integer -> Integer)
-> SomeFIntI -> SomeFIntI -> SomeFIntI
someFIntIBOpWrap f (SomeFIntI (FIntI li :: FIntI lfk)) (SomeFIntI (FIntI ri :: FIntI rfk)) =
SomeFIntI $ FIntI @(FTIntCombine lfk rfk) $ f li ri
{-
fIntIBOpWrap
:: forall kl kr. (Integer -> Integer -> Integer)
-> FIntI kl -> FIntI kr -> FIntI (FTIntCombine kl kr)
fIntIBOpWrap f l r =
case (l, r) of
(FIntI il :: FIntI 'FTInt16, FIntI ir) -> FIntI @'FTInt16 $ f il ir
{-
(FIntI l) (FIntI r) =
case (demote @kl, demote @kr) of
(FTInt16, _) -> FIntI @'FTInt16 x
(_, FTInt16) -> FIntI @'FTInt16 x
(FTInt8, _) -> FIntI @'FTInt8 x
(_, FTInt8) -> FIntI @'FTInt8 x
(FTInt4, _) -> FIntI @'FTInt4 x
(_, FTInt4) -> FIntI @'FTInt4 x
(FTInt2, _) -> FIntI @'FTInt2 x
(_, FTInt2) -> FIntI @'FTInt2 x
(FTInt1, FTInt1) -> FIntI @'FTInt1 x
-}
-}