fortran-vars-0.4.0: src/Language/Fortran/Vars/Eval/FortranSrc.hs
{- | fortran-vars-style expression evaluation which piggybacks off the evaluator
in fortran-src.
-}
{-# LANGUAGE DerivingVia #-}
module Language.Fortran.Vars.Eval.FortranSrc
( module Language.Fortran.Vars.Eval.FortranSrc
, module Language.Fortran.Vars.Eval.FortranSrc.Translate
) where
import Language.Fortran.Vars.Eval.FortranSrc.Translate
import Language.Fortran.Vars.Types.SymbolTable
import qualified Language.Fortran.Repr as FS.Rep
import qualified Language.Fortran.Repr.Eval.Common as FS.Eval
import qualified Language.Fortran.Repr.Eval.Value as FS.Eval
import Control.Monad.Reader
import Control.Monad.Except
import qualified Data.Map as Map
-- | Fortran expression evaluation monad, using 'SymbolTable' and reporting
-- fortran-src evaluator errors.
--
-- We use a newtype wrapper on this at 'Eval'. The type synonym assists some
-- boilerplate.
type Eval' = ExceptT FS.Eval.Error (Reader SymbolTable)
-- | Fortran expression evaluation monad, using 'SymbolTable' and reporting
-- fortran-src evaluator errors.
newtype Eval a = Eval { unEval :: Eval' a }
deriving (Functor, Applicative, Monad) via Eval'
deriving (MonadReader SymbolTable) via Eval'
deriving (MonadError FS.Eval.Error) via Eval'
-- | Execute a program in the Fortran expression evaluation monad 'Eval'.
runEval :: SymbolTable -> Eval a -> Either FS.Eval.Error a
runEval symt = flip runReader symt . runExceptT . unEval
-- | Evaluate Fortran expressions to 'FS.FValue's.
--
-- We look up variables from a plain 'SymbolTable', but evaluate using
-- fortran-src's machinery. We must therefore translate 'SymbolTable' 'ExpVal's
-- to 'FS.FValue'. If we want to return fortran-vars-style types, we must
-- translate the other way after executing a program in this monad.
instance FS.Eval.MonadFEval Eval where
type EvalTo Eval = FS.Rep.FValue
lookupFVar name = do
symt <- ask
case Map.lookup name symt of
Nothing -> return Nothing
Just entry ->
case entry of
SParameter _ val ->
return $ Just $ FS.Rep.MkFScalarValue $ translateExpVal val
_ -> do
FS.Eval.warn $
"found variable in SymbolTable, but wasn't an SParameter: "
<>name
return Nothing
-- | Ignore warnings. fortran-vars doesn't have a method to report warnings
-- during evaluation.
warn _ = pure ()