@@ -0,0 +1,76 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.DeadCodeElimination
4+-- Copyright : (c) 2014 Phil Freeman
5+-- License : MIT
6+--
7+-- Maintainer : Phil Freeman <paf31@cantab.net>
8+-- Stability : experimental
9+-- Portability :
10+--
11+-- |
12+--
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.DeadCodeElimination (
16+ eliminateDeadCode
17+) where
18+
19+import Data.Data
20+import Data.List
21+import Data.Graph
22+import Data.Generics
23+import Data.Maybe (mapMaybe)
24+
25+import Language.PureScript.Names
26+import Language.PureScript.Values
27+import Language.PureScript.Declarations
28+import Language.PureScript.TypeChecker.Monad
29+
30+-- |
31+-- Eliminate all declarations which are not a transitive dependency of the entry point module
32+--
33+eliminateDeadCode :: Environment -> String -> [Module] -> [Module]
34+eliminateDeadCode env entryPoint ms =
35+ let declarations = concatMap (declarationsByModule env) ms
36+ (graph, _, vertexFor) = graphFromEdges $ map (\(key, deps) -> (key, key, deps)) declarations
37+ entryPointVertices = mapMaybe (vertexFor . fst) . filter (\((ModuleName (ProperName mn), _), _) -> mn == entryPoint) $ declarations
38+ in flip map ms $ \(Module moduleName ds) -> Module moduleName (filter (isUsed (ModuleName moduleName) graph vertexFor entryPointVertices) ds)
39+
40+type Key = (ModuleName, Either Ident ProperName)
41+
42+declarationsByModule :: Environment -> Module -> [(Key, [Key])]
43+declarationsByModule env (Module moduleName ds) = concatMap go $ ds
44+ where
45+ go :: Declaration -> [(Key, [Key])]
46+ go d@(ValueDeclaration name _ _ _) = [((ModuleName moduleName, Left name), dependencies env (ModuleName moduleName) d)]
47+ go (DataDeclaration _ _ dctors) = map (\(name, _) -> ((ModuleName moduleName, Right name), [])) dctors
48+ go (ExternDeclaration _ name _ _) = [((ModuleName moduleName, Left name), [])]
49+ go d@(BindingGroupDeclaration names) = map (\(name, _) -> ((ModuleName moduleName, Left name), dependencies env (ModuleName moduleName) d)) names
50+ go (DataBindingGroupDeclaration ds) = concatMap go ds
51+ go _ = []
52+
53+dependencies :: (Data d) => Environment -> ModuleName -> d -> [Key]
54+dependencies env moduleName = nub . everything (++) (mkQ [] values)
55+ where
56+ values :: Value -> [Key]
57+ values (Var ident) = let (mn, name) = canonicalize moduleName env ident in [(mn, Left name)]
58+ values (Constructor pn) = let (mn, name) = canonicalizeDataConstructor moduleName env pn in [(mn, Right name)]
59+ values _ = []
60+
61+isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Declaration -> Bool
62+isUsed moduleName graph vertexFor entryPointVertices (ValueDeclaration name _ _ _) =
63+ let Just v' = vertexFor (moduleName, Left name)
64+ in any (\v -> path graph v v') entryPointVertices
65+isUsed moduleName graph vertexFor entryPointVertices (DataDeclaration _ _ dctors) =
66+ any (\(pn, _) -> let Just v' = vertexFor (moduleName, Right pn)
67+ in any (\v -> path graph v v') entryPointVertices) dctors
68+isUsed moduleName graph vertexFor entryPointVertices (ExternDeclaration _ name _ _) =
69+ let Just v' = vertexFor (moduleName, Left name)
70+ in any (\v -> path graph v v') entryPointVertices
71+isUsed moduleName graph vertexFor entryPointVertices (BindingGroupDeclaration ds) =
72+ any (\(name, _) -> let Just v' = vertexFor (moduleName, Left name)
73+ in any (\v -> path graph v v') entryPointVertices) ds
74+isUsed moduleName graph vertexFor entryPointVertices (DataBindingGroupDeclaration ds) =
75+ any (isUsed moduleName graph vertexFor entryPointVertices) ds
76+isUsed _ _ _ _ _ = True