@@ -5,21 +5,54 @@ module Idris.Erasure
7import Idris.AbsSyntax
7import Idris.AbsSyntax
9import Idris.Core.CaseTree
8import Idris.Core.CaseTree
10import Idris.Core.TT
9import Idris.Core.TT
10+import Idris.Core.Evaluate
12import Control.Applicative
12import Control.Applicative
13import Control.Monad.State
13import Control.Monad.State
14import Data.Maybe
14import Data.Maybe
15import Data.List
15import Data.List
16−import qualified Data.Set as S
16+import qualified Data.IntSet as S
17+import qualified Data.Map as M
18+import Data.IntSet (IntSet)
21+findUsed :: Context -> Ctxt CGInfo -> [Name] -> Map Name IntSet
22+findUsed ctx cg ns = union $ map (findUsedDef cg . getDef ctx) ns
24+ union :: [Map Name IntSet] -> Map Name IntSet
25+ union = M.unionsWith S.union
27+ getDef :: Context -> Name -> Def
28+ getDef ctx n = case lookupDef n ctx of
30+ [] -> error $ "erasure checker: unknown name: " ++ show n -- TODO: fix this
31+ _ -> error $ "erasure checker: ambiguous name: " ++ show n -- TODO: fix this
33+ findUsedDef :: Ctxt CGInfo -> Def -> Map Name IntSet
34+ findUsedDef cg (Function ty t ) = M.empty
35+ findUsedDef cg (TyDecl ty t ) = M.empty
36+ findUsedDef cg (Operator ty n f) = M.empty
37+ -- ^- non-pattern-matching definitions don't contribute to usage of data
39+ findUsedDef cg (CaseOp ci ty def tot cdefs)
40+ -- the fst component is the list of pattern variables, which we don't use
41+ = findUsedSC cg M.empty (snd $ cases_compiletime cdefs) -- TODO: or cases_runtime?
43+ findUsedSC :: Ctxt CGInfo -> Map Name (Name, Int) -> SC -> Map Name IntSet
44+ findUsedSC cg vars ImpossibleCase = M.empty
45+ findUsedSC cg vars (UnmatchedCase msg) = M.empty
46+ findUsedSC cg vars (Case n alts) = undefined
47+ findUsedSC cg vars (ProjCase t alts) = undefined
48+ findUsedSC cg vars (STerm t) = undefined
18findUnusedArgs :: [Name] -> Idris ()
50findUnusedArgs :: [Name] -> Idris ()
19findUnusedArgs names = do
51findUnusedArgs names = do
20 cg <- idris_callgraph <$> getIState
52 cg <- idris_callgraph <$> getIState
21 mapM_ (process cg) names
53 mapM_ (process cg) names
55+ process :: Ctxt CGInfo -> Name -> Idris ()
23 process cg n = case lookupCtxt n cg of
56 process cg n = case lookupCtxt n cg of
25 let unused = traceUnused cg n x
58 let unused = traceUnused cg n x
@@ -27,38 +60,38 @@ findUnusedArgs names = do
27 addToCG n $ x{ unusedpos = unused }
60 addToCG n $ x{ unusedpos = unused }
28 _ -> return ()
61 _ -> return ()
30−traceUnused :: Ctxt CGInfo -> Name -> CGInfo -> [Int]
63+ traceUnused :: Ctxt CGInfo -> Name -> CGInfo -> [Int]
31−traceUnused cg n (CGInfo args calls _ usedns _)
64+ traceUnused cg n (CGInfo args calls _ usedns _)
32− = findIndices (not . (`elem` fused)) args
65+ = findIndices (not . (`elem` fused)) args
34− fargs = concatMap (getFargpos calls) (zip args [0..])
67+ fargs = concatMap (getFargpos calls) (zip args [0..])
35− recused = [n | (n, i, (g,j)) <- fargs, used cg [(n,i)] g j]
68+ recused = [n | (n, i, (g,j)) <- fargs, used cg [(n,i)] g j]
36− fused = nub $ usedns ++ recused
69+ fused = nub $ usedns ++ recused
38−used :: Ctxt CGInfo -> [(Name, Int)] -> Name -> Int -> Bool
71+ used :: Ctxt CGInfo -> [(Name, Int)] -> Name -> Int -> Bool
39−used cg path g j
72+ used cg path g j
40− | (g, j) `elem` path = False -- cycle, never used on the way
73+ | (g, j) `elem` path = False -- cycle, never used on the way
42− | [CGInfo args calls _ usedns _] <- lookupCtxt g cg
75+ | [CGInfo args calls _ usedns _] <- lookupCtxt g cg
43− , j < length args -- not overapplied
76+ , j < length args -- not overapplied
44− = let directuse = args!!j `elem` usedns
77+ = let directuse = args!!j `elem` usedns
45− garg = getFargpos calls (args!!j, j)
78+ garg = getFargpos calls (args!!j, j)
46− recused = map getUsed garg
79+ recused = map getUsed garg
47− in directuse || null recused || or recused
80+ in directuse || null recused || or recused
48− -- used on any route from here, or not used recursively
81+ -- used on any route from here, or not used recursively
50− | otherwise = True
83+ | otherwise = True
52− getUsed (argn, j, (g', j')) = used cg ((g,j):path) g' j'
85+ getUsed (argn, j, (g', j')) = used cg ((g,j):path) g' j'
54−getFargpos :: [(Name, [[Name]])] -> (Name, Int) -> [(Name, Int, (Name, Int))]
87+ getFargpos :: [(Name, [[Name]])] -> (Name, Int) -> [(Name, Int, (Name, Int))]
55−getFargpos calls (n, i) = concatMap (getCallArgpos n i) calls
88+ getFargpos calls (n, i) = concatMap (getCallArgpos n i) calls
57− getCallArgpos :: Name -> Int -> (Name, [[Name]]) -> [(Name, Int, (Name, Int))]
90+ getCallArgpos :: Name -> Int -> (Name, [[Name]]) -> [(Name, Int, (Name, Int))]
58− getCallArgpos n i (g, args) = mapMaybe (getOne g) (zip [0..] args)
91+ getCallArgpos n i (g, args) = mapMaybe (getOne g) (zip [0..] args)
60− getOne :: Name -> (Int, [Name]) -> Maybe (Name, Int, (Name, Int))
93+ getOne :: Name -> (Int, [Name]) -> Maybe (Name, Int, (Name, Int))
61− getOne g (j, xs)
94+ getOne g (j, xs)
62− | n `elem` xs = Just (n, i, (g, j))
95+ | n `elem` xs = Just (n, i, (g, j))
63− | otherwise = Nothing
96+ | otherwise = Nothing