@@ -1,9 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22
3−module Idris.Erasure
4− ( buildDepMap
5− , minimalUsage
6− ) where
3+module Idris.Erasure (performUsageAnalysis) where
74
85import Idris.AbsSyntax
96import Idris.Core.CaseTree
@@ -51,6 +48,42 @@ type Cond = Set Node
5148type Var = Set Node
5249type Vars = Map Name Var
5350
51+-- Perform usage analysis, write the relevant information in the internal
52+-- structures, returning the list of reachable names.
53+performUsageAnalysis :: Idris [Name]
54+performUsageAnalysis = do
55+ ctx <- tt_ctxt <$> getIState
56+ ci <- idris_classes <$> getIState
57+
58+ -- Build the dependency graph.
59+ let depMap = buildDepMap ci ctx (sNS (sUN "main") ["Main"])
60+
61+ -- Search for reachable nodes in the graph.
62+ let (residDeps, (reachableNames, minUse)) = minimalUsage depMap
63+
64+ -- Print some debug info.
65+ logLvl 3 $ "Reachable names:\n" ++ unlines (map show . S.toList $ reachableNames)
66+ logLvl 4 $ "Minimal usage:\n" ++ fmtUseMap minUse
67+ logLvl 5 $ "Residual deps:\n" ++ unlines (map fmtItem . M.toList $ residDeps)
68+
69+ -- Store the usage info in the internal state.
70+ mapM_ storeUsage . M.toList $ minUse
71+
72+ return $ S.toList reachableNames
73+ where
74+ fmtItem :: (Cond, Set Node) -> String
75+ fmtItem (cond, deps) = show (S.toList cond) ++ " -> " ++ show (S.toList deps)
76+
77+ fmtUseMap :: UseMap -> String
78+ fmtUseMap = unlines . map (\(n,is) -> show n ++ " -> " ++ show (IS.toList is)) . M.toList
79+
80+ storeUsage :: (Name, IntSet) -> Idris ()
81+ storeUsage (n, args) = do
82+ cg <- idris_callgraph <$> getIState
83+ case lookupCtxt n cg of
84+ [x] -> addToCG n x{ usedpos = IS.toList args } -- functions
85+ _ -> addToCG n (CGInfo [] [] [] [] (IS.toList args)) -- data ctors
86+
5487-- Find the minimal consistent usage by forward chaining.
5588minimalUsage :: Deps -> (Deps, (Set Name, UseMap))
5689minimalUsage = second gather . forwardChain
@@ -75,8 +108,8 @@ forwardChain deps
75108
76109-- Build the dependency graph,
77110-- starting the depth-first search from a list of Names.
78−buildDepMap :: Ctxt ClassInfo -> Context -> [Name] -> Deps
79−buildDepMap ci ctx ns = addPostulates $ dfs S.empty M.empty ns
111+buildDepMap :: Ctxt ClassInfo -> Context -> Name -> Deps
112+buildDepMap ci ctx rootName = addPostulates $ dfs S.empty M.empty [rootName]
80113 where
81114 -- mark the result of Main.main as used with the empty assumption
82115 addPostulates :: Deps -> Deps