camfort-1.0: src/Language/Fortran/Model/Vars.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wall #-}
-- TODO: Variables for user-defined data types
{-|
Defines a strongly-typed representation of Fortran variables.
-}
module Language.Fortran.Model.Vars
(
-- * Variables
FortranVar(..)
-- * Names
, NamePair(..)
, npSource
, npUnique
, SourceName(..)
, UniqueName(..)
) where
import Data.Typeable ((:~:) (..))
import Control.Lens hiding (Index, op)
import Data.SBV.Dynamic
import Data.Vinyl (rtraverse)
import qualified Language.Fortran.AST as F
import Language.Expression.Pretty
import Language.Verification
import Language.Fortran.Model.Repr
import Language.Fortran.Model.Repr.Prim
import Language.Fortran.Model.Types
import Language.Fortran.Model.Types.Match
--------------------------------------------------------------------------------
-- Names
--------------------------------------------------------------------------------
-- | Newtype wrapper for source-level variable names.
newtype SourceName = SourceName { getSourceName :: F.Name }
deriving (Eq, Ord)
instance Show SourceName where show = show . getSourceName
-- | Newtype wrapper for unique variable names.
newtype UniqueName = UniqueName { getUniqueName :: F.Name }
deriving (Eq, Ord)
instance Show UniqueName where show = show . getUniqueName
makeWrapped ''SourceName
makeWrapped ''UniqueName
-- | A 'NamePair' represents the name of some part of a Fortran program,
-- including the human-readable source name and the unique name.
data NamePair =
NamePair
{ _npUnique :: UniqueName
, _npSource :: SourceName
}
deriving (Eq, Ord, Show)
makeLenses ''NamePair
instance Pretty SourceName where
pretty = view _Wrapped
-- | The pretty version of a 'NamePair' is its source name.
instance Pretty NamePair where
pretty = pretty . view npSource
--------------------------------------------------------------------------------
-- Fortran Variables
--------------------------------------------------------------------------------
-- | A variable representing a value of type @a@. Contains a @'D' a@ as proof
-- that the type has a corresponding Fortran type, and the variable name.
data FortranVar a where
FortranVar :: D a -> NamePair -> FortranVar a
instance VerifiableVar FortranVar where
type VarKey FortranVar = UniqueName
type VarSym FortranVar = CoreRepr
type VarEnv FortranVar = PrimReprHandlers
symForVar (FortranVar d np) env =
case d of
DPrim prim -> CRPrim d <$> primSymbolic prim uniqueName env
DArray i val -> CRArray d <$> arraySymbolic i val uniqueName env
DData _ _ -> fail "User-defined data type variables are not supported yet"
where
uniqueName = np ^. npUnique . _Wrapped
varKey (FortranVar _ np) = np ^. npUnique
eqVarTypes (FortranVar d1 _) (FortranVar d2 _) = eqD d1 d2
castVarSym (FortranVar d1 _) s = case s of
CRPrim d2 _ | Just Refl <- eqD d1 d2 -> Just s
CRArray d2 _ | Just Refl <- eqD d1 d2 -> Just s
CRData d2 _ | Just Refl <- eqD d1 d2 -> Just s
-- Variables can't have the 'Bool' type so 'CRProp' can't be casted.
_ -> Nothing
instance Pretty1 FortranVar where
pretty1 (FortranVar _ np) = pretty np
--------------------------------------------------------------------------------
-- Internals
--------------------------------------------------------------------------------
arraySymbolic :: (HasPrimReprHandlers r) => Index i -> ArrValue a -> String -> r -> Symbolic (ArrRepr i a)
arraySymbolic ixIndex@(Index ixPrim) valAV nm env =
case valAV of
ArrPrim valPrim -> ARPrim <$> arraySymbolicPrim ixPrim valPrim nm env
ArrData _ valData -> do
valReprs <- rtraverse (traverseField' (\av -> arraySymbolic ixIndex av nm env)) valData
return $ ARData valReprs
arraySymbolicPrim :: (HasPrimReprHandlers r) => Prim p1 k1 i -> Prim p2 k2 a -> String -> r -> Symbolic SArr
arraySymbolicPrim _ _ _ = error "arraySymbolicPrim: bit-rotted in new SBV 8.0 version" -- do
-- k1 <- primSBVKind ixPrim
-- k2 <- primSBVKind valPrim
-- return $ newSArr (k1, k2) (\i -> nm ++ "_" ++ show i)
-- pairProxy :: p1 a -> p2 b -> Proxy '(a, b)
-- pairProxy _ _ = Proxy