camfort-1.0: src/Language/Fortran/Model/Op/Eval.hs
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wall #-}
module Language.Fortran.Model.Op.Eval where
import Control.Monad.Reader.Class (MonadReader (..))
import Data.SBV (SDouble, SFloat, SReal, sRTZ)
import qualified Data.SBV as SBV
import Data.SBV.Dynamic (SVal)
import qualified Data.SBV.Dynamic as SBV
import Data.SBV.Internals (SBV (..))
import Language.Fortran.Model.Repr.Prim
import Language.Fortran.Model.Types
--------------------------------------------------------------------------------
-- Monad
--------------------------------------------------------------------------------
class (MonadReader r m, HasPrimReprHandlers r) => MonadEvalFortran r m | m -> r where
instance (MonadReader r m, HasPrimReprHandlers r) => MonadEvalFortran r m where
--------------------------------------------------------------------------------
-- SBV Kinds
--------------------------------------------------------------------------------
coerceBy :: (SBV a -> SBV b) -> SVal -> SVal
coerceBy f x = unSBV (f (SBV x))
coerceSBVKinds :: SBV.Kind -> SBV.Kind -> (SVal -> SVal)
coerceSBVKinds SBV.KReal SBV.KReal = id
coerceSBVKinds SBV.KFloat SBV.KReal = coerceBy (SBV.fromSFloat sRTZ :: SFloat -> SReal)
coerceSBVKinds SBV.KDouble SBV.KReal = coerceBy (SBV.fromSDouble sRTZ :: SDouble -> SReal)
coerceSBVKinds _ k2@SBV.KReal = SBV.svFromIntegral k2
coerceSBVKinds SBV.KReal SBV.KDouble = coerceBy (SBV.toSDouble sRTZ :: SReal -> SDouble)
coerceSBVKinds SBV.KDouble SBV.KDouble = id
coerceSBVKinds SBV.KFloat SBV.KDouble = coerceBy (SBV.toSDouble sRTZ :: SFloat -> SDouble)
coerceSBVKinds _ k2@SBV.KDouble = SBV.svFromIntegral k2
coerceSBVKinds SBV.KReal SBV.KFloat = coerceBy (SBV.toSFloat sRTZ :: SReal -> SFloat)
coerceSBVKinds SBV.KDouble SBV.KFloat = coerceBy (SBV.toSFloat sRTZ :: SDouble -> SFloat)
coerceSBVKinds SBV.KFloat SBV.KFloat = id
coerceSBVKinds _ k2@SBV.KFloat = SBV.svFromIntegral k2
coerceSBVKinds _ k2 = SBV.svFromIntegral k2
coercePrimSVal :: (MonadEvalFortran r m) => Prim p k a -> SVal -> m SVal
coercePrimSVal p v = do
k2 <- primSBVKind p
let k1 = SBV.kindOf v
return $ coerceSBVKinds k1 k2 v