fortran-vars-0.4.0: src/Language/Fortran/Vars/Utils.hs
module Language.Fortran.Vars.Utils where
import Language.Fortran.Analysis ( Analysis )
import Language.Fortran.AST
import Language.Fortran.Vars.Types ( SymbolTable
, ExpVal(..)
, Type
, SemType(..)
, Dim(..)
, Dims(..)
, Dimensions
)
import Language.Fortran.Vars.Eval ( eval
, eval'
)
import Language.Fortran.Vars.Kind ( setTypeKind
, kindOfBaseType
, baseToType
)
-- | Given dimenion declarators and the typespec, give ArrayTypeData evaluating
-- valid expressions for the upper and lower bound
typeSpecToArrayType
:: SymbolTable
-> [DimensionDeclarator (Analysis a)]
-> TypeSpec (Analysis a)
-> Type
--typeSpecToArrayType st dims tySpec = TArray scalarTy $ foldr go DimensionsEnd dims
typeSpecToArrayType st dims tySpec =
case foldr go [] dims of
[] -> error "invalid array spec: zero dimensions"
d:ds -> TArray scalarTy $ DimsExplicitShape $ d :| ds
where
scalarTy = typeSpecToScalarType st tySpec
go (DimensionDeclarator _ _ (Just lb) (Just ub)) dims =
Dim (Just (constInt lb)) (Just (constInt ub)) : dims
go (DimensionDeclarator _ _ Nothing (Just ub)) dims =
Dim (Just 1) (Just (constInt ub)) : dims
go _ _ = error "Invalid dimension declarator"
constInt x = case eval st x of
Int y -> y
_ -> error "Invalid array spec"
-- | Given the typespec of a scalar get the StaticType
typeSpecToScalarType :: SymbolTable -> TypeSpec (Analysis a) -> Type
typeSpecToScalarType st (TypeSpec _ _ ty selector) =
let ty' = baseToType ty
in case selector of
Just (Selector _ _ _ (Just k)) -> setTypeKind ty' (constInt k)
Just (Selector _ _ (Just l) _ ) -> setTypeKind ty' (constInt l)
Nothing -> setTypeKind ty' (Just $ kindOfBaseType ty)
_ -> error "Invalid type spec"
where
constInt x = case eval' st x of
Right (Int y) -> Just y
_ -> Nothing