module Camfort.Transformation.DeadCode
( deadCode
) where
import Camfort.Analysis.Annotations
import qualified Language.Fortran.Analysis.DataFlow as FAD
import qualified Language.Fortran.Analysis.Renaming as FAR
import qualified Language.Fortran.Analysis.BBlocks as FAB
import qualified Language.Fortran.AST as F
import qualified Language.Fortran.Util.Position as FU
import qualified Language.Fortran.Analysis as FA
import Camfort.Helpers
import Camfort.Helpers.Syntax
import qualified Data.IntMap as IM
import qualified Data.Set as S
import Data.Generics.Uniplate.Operations
import Data.Maybe
deadCode :: Bool -> F.ProgramFile A -> (Report, F.ProgramFile A)
deadCode flag pf = (report, fmap FA.prevAnnotation pf')
where
(report, _) = deadCode' flag lva pf'
pf' = FAB.analyseBBlocks . FAR.analyseRenames . FA.initAnalysis $ pf
bbm = FAB.genBBlockMap pf'
sgr = FAB.genSuperBBGr bbm
gr = FAB.superBBGrGraph sgr
lva = FAD.liveVariableAnalysis gr
deadCode' :: Bool -> FAD.InOutMap (S.Set F.Name)
-> F.ProgramFile (FA.Analysis A)
-> (Report, F.ProgramFile (FA.Analysis A))
deadCode' flag lva pf =
if null report
then (report, pf')
else (report, pf') >>= deadCode' flag lva
where
(report, pf') = transformBiM (perStmt flag lva) pf
perStmt :: Bool
-> FAD.InOutMap (S.Set F.Name)
-> F.Statement (FA.Analysis A) -> (Report, F.Statement (FA.Analysis A))
perStmt flag lva x@(F.StExpressionAssign a sp@(FU.SrcSpan s1 _) e1 e2)
| pRefactored (FA.prevAnnotation a) == flag =
fromMaybe ("", x) $
do label <- FA.insLabel a
(_, out) <- IM.lookup label lva
assignedName <- extractVariable e1
if assignedName `S.member` out
then Nothing
else
Just (report, F.StExpressionAssign a' (dropLine sp) e1 e2)
where report = "o" ++ show s1 ++ ": removed dead code\n"
a' = onPrev (\ap -> ap {refactored = Just s1}) a
perStmt _ _ x = return x