@@ -0,0 +1,93 @@
1+module Idris.WhoCalls (whoCalls, callsWho) where
2+
3+import Idris.AbsSyntax
4+
5+import Idris.Core.CaseTree
6+import Idris.Core.Evaluate
7+import Idris.Core.TT
8+
9+import Data.List (nub)
10+
11+
12+occurs :: Name -> Term -> Bool
13+occurs n (P Bound _ _) = False
14+occurs n (P _ n' _) = n == n'
15+occurs n (Bind _ b sc) = occursBinder n b || occurs n sc
16+occurs n (App t1 t2) = occurs n t1 || occurs n t2
17+occurs n (Proj t _) = occurs n t
18+occurs n _ = False
19+
20+names :: Term -> [Name]
21+names (P Bound _ _) = []
22+names (P _ n _) = [n]
23+names (Bind _ b sc) = namesBinder b ++ names sc
24+names (App t1 t2) = names t1 ++ names t2
25+names (Proj t _) = names t
26+names _ = []
27+
28+occursBinder :: Name -> Binder Term -> Bool
29+occursBinder n (Let ty val) = occurs n ty || occurs n val
30+occursBinder n (NLet ty val) = occurs n ty || occurs n val
31+occursBinder n b = occurs n (binderTy b)
32+
33+namesBinder :: Binder Term -> [Name]
34+namesBinder (Let ty val) = names ty ++ names val
35+namesBinder (NLet ty val) = names ty ++ names val
36+namesBinder b = names (binderTy b)
37+
38+occursSC :: Name -> SC -> Bool
39+occursSC n (Case _ alts) = any (occursCaseAlt n) alts
40+occursSC n (ProjCase t alts) = occurs n t || any (occursCaseAlt n) alts
41+occursSC n (STerm t) = occurs n t
42+occursSC n _ = False
43+
44+namesSC :: SC -> [Name]
45+namesSC (Case _ alts) = concatMap namesCaseAlt alts
46+namesSC (ProjCase t alts) = names t ++ concatMap namesCaseAlt alts
47+namesSC (STerm t) = names t
48+namesSC _ = []
49+
50+occursCaseAlt :: Name -> CaseAlt -> Bool
51+occursCaseAlt n (ConCase n' _ _ sc) = n == n' || occursSC n sc
52+occursCaseAlt n (FnCase n' _ sc) = n == n' || occursSC n sc
53+occursCaseAlt n (ConstCase _ sc) = occursSC n sc
54+occursCaseAlt n (SucCase _ sc) = occursSC n sc
55+occursCaseAlt n (DefaultCase sc) = occursSC n sc
56+
57+namesCaseAlt :: CaseAlt -> [Name]
58+namesCaseAlt (ConCase n' _ _ sc) = n' : namesSC sc
59+namesCaseAlt (FnCase n' _ sc) = n' : namesSC sc
60+namesCaseAlt (ConstCase _ sc) = namesSC sc
61+namesCaseAlt (SucCase _ sc) = namesSC sc
62+namesCaseAlt (DefaultCase sc) = namesSC sc
63+
64+occursDef :: Name -> Def -> Bool
65+occursDef n (Function ty tm) = occurs n ty || occurs n tm
66+occursDef n (TyDecl _ ty) = occurs n ty
67+occursDef n (Operator ty _ _) = occurs n ty
68+occursDef n (CaseOp _ ty _ _ _ defs) = occurs n ty || occursSC n (snd (cases_compiletime defs))
69+
70+namesDef :: Def -> [Name]
71+namesDef (Function ty tm) = names ty ++ names tm
72+namesDef (TyDecl _ ty) = names ty
73+namesDef (Operator ty _ _) = names ty
74+namesDef (CaseOp _ ty _ _ _ defs) = names ty ++ namesSC (snd (cases_compiletime defs))
75+
76+findOccurs :: Name -> Idris [Name]
77+findOccurs n = do ctxt <- getContext
78+ -- A definition calls a function if the function is in the type or RHS of the definition
79+ let defs = (map fst . filter (\(n', def) -> n /= n' && occursDef n def) . ctxtAlist) ctxt
80+ -- A datatype calls its
81+ return defs
82+
83+whoCalls :: Name -> Idris [(Name, [Name])]
84+whoCalls n = do ctxt <- getContext
85+ let names = lookupNames n ctxt
86+ find nm = do ns <- findOccurs nm
87+ return (nm, nub ns)
88+ mapM find names
89+
90+callsWho :: Name -> Idris [(Name, [Name])]
91+callsWho n = do ctxt <- getContext
92+ let defs = lookupNameDef n ctxt
93+ return $ map (\ (n, def) -> (n, nub $ namesDef def)) defs