module Language.Fortran.Analysis
( initAnalysis, stripAnalysis, Analysis(..), varName, genVar, puName, blockRhsExprs, rhsExprs
, ModEnv, NameType(..), IDType(..), ConstructType(..), BaseType(..)
, lhsExprs, isLExpr, allVars, allLhsVars, blockVarUses, blockVarDefs
, BB, BBGr
, TransFunc, TransFuncM )
where
import Language.Fortran.Util.Position (SrcSpan)
import Data.Generics.Uniplate.Data
import Data.Generics.Uniplate.Operations
import Data.Data
import Language.Fortran.AST
import Data.Graph.Inductive.PatriciaTree (Gr)
import qualified Data.Map as M
type BB a = [Block a]
type BBGr a = Gr (BB a) ()
deriving instance (Typeable a, Typeable b) => Typeable (Gr a b)
instance (Typeable a, Typeable b) => Data (Gr a b) where
gfoldl _k z v = z v
toConstr _ = error "toConstr"
gunfold _ _ = error "gunfold"
dataTypeOf _ = mkNoRepType "Gr"
type TransFunc f g a = (f (Analysis a) -> f (Analysis a)) -> g (Analysis a) -> g (Analysis a)
type TransFuncM m f g a = (f (Analysis a) -> m (f (Analysis a))) -> g (Analysis a) -> m (g (Analysis a))
data NameType = NTSubprogram | NTVariable deriving (Show, Eq, Ord, Data, Typeable)
type ModEnv = M.Map String (String, NameType)
data ConstructType =
CTFunction
| CTSubroutine
| CTVariable
| CTArray
| CTParameter
deriving (Data, Show, Eq)
data IDType = IDType
{ idVType :: Maybe BaseType
, idCType :: Maybe ConstructType }
deriving (Data, Show, Eq)
data Analysis a = Analysis
{ prevAnnotation :: a
, uniqueName :: Maybe String
, bBlocks :: Maybe (BBGr (Analysis a))
, insLabel :: Maybe Int
, moduleEnv :: Maybe ModEnv
, idType :: Maybe IDType
}
deriving (Data, Show, Eq)
analysis0 a = Analysis { prevAnnotation = a
, uniqueName = Nothing
, bBlocks = Nothing
, insLabel = Nothing
, moduleEnv = Nothing
, idType = Nothing }
varName :: Expression (Analysis a) -> String
varName (ExpValue (Analysis { uniqueName = Just n }) _ (ValVariable {})) = n
varName (ExpValue (Analysis { uniqueName = Nothing }) _ (ValVariable n)) = n
varName _ = error "Use of varName on non-variable."
genVar :: Analysis a -> SrcSpan -> String -> Expression (Analysis a)
genVar a s n = ExpValue (a { uniqueName = Just n }) s (ValVariable n)
puName :: ProgramUnit (Analysis a) -> ProgramUnitName
puName pu
| Just n <- uniqueName (getAnnotation pu) = Named n
| otherwise = getName pu
initAnalysis :: Functor b => b a -> b (Analysis a)
initAnalysis = fmap analysis0
stripAnalysis :: ProgramFile (Analysis a) -> ProgramFile a
stripAnalysis = fmap prevAnnotation
lhsExprs :: (Data a, Data (b a)) => b a -> [Expression a]
lhsExprs x = concatMap lhsOfStmt (universeBi x) ++ concatMap lhsOfExp (universeBi x)
where
lhsOfStmt (StExpressionAssign _ _ e _) = [e]
lhsOfStmt (StCall _ _ _ (Just aexps)) = fstLvl aexps
lhsOfStmt _ = []
lhsOfExp (ExpFunctionCall _ _ _ (Just aexps)) = fstLvl aexps
lhsOfExp _ = []
fstLvl = filter isLExpr . map extractExp . aStrip
extractExp (Argument _ _ _ exp) = exp
rhsExprs :: (Data a, Data (b a)) => b a -> [Expression a]
rhsExprs x = concat [ blockRhsExprs b | b <- universeBi x ]
isLExpr :: Expression a -> Bool
isLExpr (ExpValue _ _ (ValVariable {})) = True
isLExpr (ExpSubscript _ _ _ _) = True
isLExpr _ = False
allVars :: forall a b. (Data a, Data (b (Analysis a))) => b (Analysis a) -> [Name]
allVars b = [ varName v | v@(ExpValue _ _ (ValVariable _)) <- uniBi b ]
where
uniBi x = universeBi x :: [Expression (Analysis a)]
allLhsVars :: (Data a, Data (b (Analysis a))) => b (Analysis a) -> [Name]
allLhsVars b = [ varName v | v@(ExpValue _ _ (ValVariable {})) <- lhsExprs b ] ++
[ varName v | ExpSubscript _ _ v@(ExpValue _ _ (ValVariable {})) _ <- lhsExprs b ]
blockRhsExprs :: Data a => Block a -> [Expression a]
blockRhsExprs (BlStatement _ _ _ (StExpressionAssign _ _ lhs rhs))
| ExpSubscript _ _ _ subs <- lhs = universeBi rhs ++ universeBi subs
| otherwise = universeBi rhs
blockRhsExprs (BlDo _ _ _ (Just (DoSpecification _ _ (StExpressionAssign _ _ lhs rhs) e1 e2)) _)
| ExpSubscript _ _ _ subs <- lhs = universeBi (rhs, e1, e2) ++ universeBi subs
| otherwise = universeBi (rhs, e1, e2)
blockRhsExprs (BlStatement _ _ _ (StDeclaration {})) = []
blockRhsExprs (BlDoWhile _ _ e1 e2 _) = universeBi (e1, e2)
blockRhsExprs (BlIf _ _ e1 e2 _) = universeBi (e1, e2)
blockRhsExprs b = universeBi b
blockVarUses :: Data a => Block (Analysis a) -> [Name]
blockVarUses (BlStatement _ _ _ (StExpressionAssign _ _ lhs rhs))
| ExpSubscript _ _ _ subs <- lhs = allVars rhs ++ concatMap allVars (aStrip subs)
| otherwise = allVars rhs
blockVarUses (BlDo _ _ _ (Just (DoSpecification _ _ (StExpressionAssign _ _ lhs rhs) e1 e2)) _)
| ExpSubscript _ _ _ subs <- lhs = allVars rhs ++ allVars e1 ++ maybe [] allVars e2 ++ concatMap allVars (aStrip subs)
| otherwise = allVars rhs ++ allVars e1 ++ maybe [] allVars e2
blockVarUses (BlStatement _ _ _ (StDeclaration {})) = []
blockVarUses (BlDoWhile _ _ e1 e2 _) = maybe [] allVars e1 ++ allVars e2
blockVarUses (BlIf _ _ e1 e2 _) = maybe [] allVars e1 ++ concatMap (maybe [] allVars) e2
blockVarUses b = allVars b
blockVarDefs :: Data a => Block (Analysis a) -> [Name]
blockVarDefs (BlStatement _ _ _ st) = allLhsVars st
blockVarDefs (BlDo _ _ _ (Just doSpec) _) = allLhsVars doSpec
blockVarDefs _ = []