1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
module CurryBrowseAnalysis.Dependency
(analyseWithDependencies, indirectlyDependent,
funcsInExpr, callsDirectly, externalDependent,
dependencyGraphs, localDependencyGraphs) where
import Prelude hiding ( empty )
import Data.Maybe ( fromJust )
import FlatCurry.Types
import Data.Set.RBTree ( SetRBT, member, empty, insert, toList, union )
analyseWithDependencies :: (FuncDecl->a) -> ([a]->a) -> [FuncDecl] -> [(QName,a)]
analyseWithDependencies funproperty combine funs = map anaFun alldeps
where
anaFun (name,depfuns) = (name, combine (map (lookupProp funprops) (name:depfuns)))
funprops = map (\f->(funcName f, funproperty f)) funs
alldeps = indirectlyDependent funs
lookupProp :: [(QName,a)] -> QName -> a
lookupProp fprops fun = fromJust (lookup fun fprops)
funcName (Func fname _ _ _ _) = fname
externalDependent :: [FuncDecl] -> [(QName,[QName])]
externalDependent funcs =
map (\ (f,fs)->(f,filter (`elem` externalFuncs) fs))
(indirectlyDependent funcs)
where
externalFuncs = concatMap getExternal funcs
getExternal (Func _ _ _ _ (Rule _ _)) = []
getExternal (Func f _ _ _ (External _)) = [f]
indirectlyDependent :: [FuncDecl] -> [(QName,[QName])]
indirectlyDependent funs = map (\ (f,ds) -> (f,toList ds))
(depsClosure (map directlyDependent funs))
callsDirectly :: FuncDecl -> [QName]
callsDirectly fun = toList (snd (directlyDependent fun))
directlyDependent :: FuncDecl -> (QName,SetRBT QName)
directlyDependent (Func f _ _ _ (Rule _ e)) = (f,funcSetOfExpr e)
directlyDependent (Func f _ _ _ (External _)) = (f,emptySet)
depsClosure :: [(QName,SetRBT QName)] -> [(QName,SetRBT QName)]
depsClosure directdeps = map (\(f,ds)->(f,closure ds (toList ds)))
directdeps
where
closure olddeps [] = olddeps
closure olddeps (f:fs) =
let newdeps = filter (\e->not (member e olddeps))
(toList (maybe emptySet id (lookup f directdeps)))
in closure (foldr insert olddeps newdeps) (newdeps++fs)
dependencyGraphs :: [FuncDecl] -> [(QName,[(QName,[QName])])]
dependencyGraphs funs =
let directdeps = map directlyDependent funs
in map (\(f,ds) -> (f,map (\g->(g,toList (fromJust (lookup g directdeps))))
(toList (insert f ds))))
(depsClosure directdeps)
localDependencyGraphs :: [FuncDecl] -> [(QName,[(QName,[QName])])]
localDependencyGraphs funs =
let directdeps = map directlyDependent funs
in map (\(f,ds) -> (f,map (\g->(g,if fst f == fst g
then toList (fromJust (lookup g directdeps))
else []))
(toList (insert f ds))))
(localDepsClosure directdeps)
localDepsClosure :: [(QName,SetRBT QName)] -> [(QName,SetRBT QName)]
localDepsClosure directdeps =
map (\(f,ds)->(f,closure (fst f) ds (toList ds))) directdeps
where
closure _ olddeps [] = olddeps
closure mod olddeps (f:fs)
| mod == fst f
= let newdeps = filter (\e->not (member e olddeps))
(toList (maybe emptySet id (lookup f directdeps)))
in closure mod (foldr insert olddeps newdeps) (newdeps++fs)
| otherwise = closure mod olddeps fs
funcsInExpr :: Expr -> [QName]
funcsInExpr e = toList (funcSetOfExpr e)
funcSetOfExpr :: Expr -> SetRBT QName
funcSetOfExpr (Var _) = emptySet
funcSetOfExpr (Lit _) = emptySet
funcSetOfExpr (Comb ct f es) =
if isConstructorComb ct then unionMap funcSetOfExpr es
else insert f (unionMap funcSetOfExpr es)
funcSetOfExpr (Free _ e) = funcSetOfExpr e
funcSetOfExpr (Let bs e) = union (unionMap (funcSetOfExpr . snd) bs) (funcSetOfExpr e)
funcSetOfExpr (Or e1 e2) = union (funcSetOfExpr e1) (funcSetOfExpr e2)
funcSetOfExpr (Case _ e bs) = union (funcSetOfExpr e) (unionMap funcSetOfBranch bs)
where funcSetOfBranch (Branch _ be) = funcSetOfExpr be
funcSetOfExpr (Typed e _) = funcSetOfExpr e
isConstructorComb :: CombType -> Bool
isConstructorComb ct = case ct of
ConsCall -> True
ConsPartCall _ -> True
_ -> False
unionMap :: (a -> SetRBT QName) -> [a] -> SetRBT QName
unionMap f = foldr union emptySet . map f
emptySet :: SetRBT QName
emptySet = empty leqQName
leqQName :: QName -> QName -> Bool
leqQName (m1,n1) (m2,n2) = m1 ++ ('.':n1) <= m2 ++ ('.':n2)
|