module Camfort.Transformation.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
import GHC.Generics
import Debug.Trace
deadCode :: Bool -> (Filename, F.ProgramFile A)
-> (Report, (Filename, F.ProgramFile A))
deadCode flag (fname, pf) = (report, (fname, fmap FA.prevAnnotation pf'))
where
(report, pf'') = 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 s2) 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