@@ -0,0 +1,62 @@
1+module Idris.UnusedArgs where
8+import Control.Monad.State
12+findUnusedArgs :: [Name] -> Idris ()
13+findUnusedArgs ns = mapM_ traceUnused ns
15+traceUnused :: Name -> Idris ()
18+ case lookupCtxt Nothing n (idris_callgraph i) of
19+ [CGInfo args calls usedns _] ->
20+ do let argpos = zip args [0..]
21+ let fargs = concatMap (getFargpos calls) argpos
22+ logLvl 3 $ show n ++ " used TRACE: " ++ show fargs
23+ recused <- mapM (\ (argn, i, (g, j)) ->
24+ do u <- used [(n, i)] g j
25+ return (argn, u)) fargs
26+ let fused = nub $ usedns ++ map fst (filter snd recused)
27+ logLvl 1 $ show n ++ " used args: " ++ show fused
28+ let unusedpos = mapMaybe (getUnused fused) (zip [0..] args)
29+ logLvl 1 $ show n ++ " unused args: " ++ show (args, unusedpos)
30+ addToCG n (CGInfo args calls usedns unusedpos) -- updates
33+ getUnused fused (i,n) | n `elem` fused = Nothing
36+used :: [(Name, Int)] -> Name -> Int -> Idris Bool
38+ | (g, j) `elem` path = return False -- cycle, never used on the way
41+ case lookupCtxt Nothing g (idris_callgraph i) of
42+ [CGInfo args calls usedns unused] ->
43+ if (j >= length args)
44+ then -- overapplied, assume used
46+ else do let garg = getFargpos calls (args!!j, j)
47+ logLvl 5 $ show (g, j, garg)
48+ recused <- mapM (\ (argn, j, (g', j')) ->
49+ used ((g,j):path) g' j') garg
50+ -- used on any route from here, or not used recursively
51+ return (null recused || or recused)
52+ _ -> return False -- clearly...
54+getFargpos :: [(Name, [[Name]])] -> (Name, Int) -> [(Name, Int, (Name, Int))]
55+getFargpos calls (n, i) = concatMap (getCallArgpos n i) calls
56+ where getCallArgpos :: Name -> Int -> (Name, [[Name]]) ->
57+ [(Name, Int, (Name, Int))]
58+ getCallArgpos n i (g, args)
59+ = let argpos = zip [0..] args in
60+ mapMaybe (\ (j, xs) -> if n `elem` xs then Just (n, i, (g, j))