purescript-0.15.15: src/Language/PureScript/CoreImp/Optimizer/Unused.hs
-- | Removes unused variables
module Language.PureScript.CoreImp.Optimizer.Unused
( removeCodeAfterReturnStatements
, removeUndefinedApp
, removeUnusedEffectFreeVars
) where
import Prelude
import Control.Monad (filterM)
import Data.Monoid (Any(..))
import Data.Set qualified as S
import Data.Text (Text)
import Language.PureScript.CoreImp.AST (AST(..), InitializerEffects(..), everything, everywhere)
import Language.PureScript.CoreImp.Optimizer.Common (removeFromBlock)
import Language.PureScript.Constants.Prim qualified as C
removeCodeAfterReturnStatements :: AST -> AST
removeCodeAfterReturnStatements = everywhere (removeFromBlock go)
where
go :: [AST] -> [AST]
go jss =
case break isReturn jss of
(_, []) -> jss
(body, ret : _ ) -> body ++ [ret]
isReturn (Return _ _) = True
isReturn (ReturnNoResult _) = True
isReturn _ = False
removeUndefinedApp :: AST -> AST
removeUndefinedApp = everywhere convert
where
convert (App ss fn [Var _ C.S_undefined]) = App ss fn []
convert js = js
removeUnusedEffectFreeVars :: [Text] -> [[AST]] -> [[AST]]
removeUnusedEffectFreeVars exps = loop
where
expsSet = S.fromList exps
loop :: [[AST]] -> [[AST]]
loop asts = if changed then loop (filter (not . null) asts') else asts
where
used = expsSet <> foldMap (foldMap (everything (<>) (\case Var _ x -> S.singleton x; _ -> S.empty))) asts
(Any changed, asts') = traverse (filterM (anyFalses . isInUsedSet used)) asts
isInUsedSet :: S.Set Text -> AST -> Bool
isInUsedSet used = \case
VariableIntroduction _ var (Just (NoEffects, _)) -> var `S.member` used
_ -> True
anyFalses :: Bool -> (Any, Bool)
anyFalses x = (Any (not x), x)