1-----------------------------------------------------------------------------
3-- Module : Language.PureScript.DeadCodeElimination
4-- Copyright : (c) 2014 Phil Freeman
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
11-- | Dead code elimination.
13-----------------------------------------------------------------------------
15module Language.PureScript.DeadCodeElimination (
21import Data.Maybe (mapMaybe)
23import Language.PureScript.CoreFn
24import Language.PureScript.Names
27-- Eliminate all declarations which are not a transitive dependency of the entry point module
29eliminateDeadCode :: [ModuleName] -> [Module a] -> [Module a]
30eliminateDeadCode entryPoints ms = map go ms
32 go (Module coms mn imps exps foreigns ds) = Module coms mn imps exps' foreigns' ds'
34 ds' = filter (isUsed mn graph vertexFor entryPointVertices) ds
35 foreigns' = filter (isUsed' mn graph vertexFor entryPointVertices . foreignIdent) foreigns
36 names = concatMap bindIdents ds' ++ map foreignIdent foreigns'
37 exps' = filter (`elem` names) exps
38 declarations = concatMap declarationsByModule ms
39 (graph, _, vertexFor) = graphFromEdges $ map (\(key, deps) -> (key, key, deps)) declarations
40 entryPointVertices = mapMaybe (vertexFor . fst) . filter (\((mn, _), _) -> mn `elem` entryPoints) $ declarations
43-- Extract declaration names for a binding group.
45bindIdents :: Bind a -> [Ident]
46bindIdents (NonRec name _) = [name]
47bindIdents (Rec names) = map fst names
50-- Extract the ident for a foreign declaration.
52foreignIdent :: ForeignDecl -> Ident
56-- Key type to use in graph
58type Key = (ModuleName, Ident)
61-- Find dependencies for each member in a module.
63declarationsByModule :: Module a -> [(Key, [Key])]
64declarationsByModule (Module _ mn _ _ fs ds) =
65 let fs' = map ((\name -> ((mn, name), [])) . foreignIdent) fs
66 in fs' ++ concatMap go ds
68 go :: Bind a -> [(Key, [Key])]
69 go d@(NonRec name _) = [((mn, name), dependencies d)]
70 go d@(Rec names') = map (\(name, _) -> ((mn, name), dependencies d)) names'
73-- Find all referenced values within a binding group.
75dependencies :: Bind a -> [Key]
77 let (f, _, _, _) = everythingOnValues (++) (const []) values binders (const [])
80 values :: Expr a -> [Key]
81 values (Var _ (Qualified (Just mn) ident)) = [(mn, ident)]
83 binders :: Binder a -> [Key]
84 binders (ConstructorBinder _ _ (Qualified (Just mn) ident) _) = [(mn, Ident $ runProperName ident)]
88-- Check whether a binding group is used.
90isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Bind a -> Bool
91isUsed mn graph vertexFor entryPointVertices (NonRec name _) =
92 isUsed' mn graph vertexFor entryPointVertices name
93isUsed mn graph vertexFor entryPointVertices (Rec ds) =
94 any (isUsed' mn graph vertexFor entryPointVertices . fst) ds
97-- Check whether a named declaration is used.
99isUsed' :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Ident -> Bool
100isUsed' mn graph vertexFor entryPointVertices name =
101 let Just v' = vertexFor (mn, name)
102 in any (\v -> path graph v v') entryPointVertices
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list