{- | 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 -} -}