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
|
module CurryBrowseAnalysis.Dependency
(analyseWithDependencies, indirectlyDependent,
funcsInExpr, callsDirectly, externalDependent,
dependencyGraphs, localDependencyGraphs) where
import FlatCurry.Types
import List
import SetRBT
import Sort(leqString)
import Maybe(fromJust)
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,setRBT2list ds))
(depsClosure (map directlyDependent funs))
callsDirectly :: FuncDecl -> [QName]
callsDirectly fun = setRBT2list (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 (setRBT2list ds)))
directdeps
where
closure olddeps [] = olddeps
closure olddeps (f:fs) =
let newdeps = filter (\e->not (elemRBT e olddeps))
(setRBT2list (maybe emptySet id (lookup f directdeps)))
in closure (foldr insertRBT olddeps newdeps) (newdeps++fs)
dependencyGraphs :: [FuncDecl] -> [(QName,[(QName,[QName])])]
dependencyGraphs funs =
let directdeps = map directlyDependent funs
in map (\(f,ds) -> (f,map (\g->(g,setRBT2list (fromJust (lookup g directdeps))))
(setRBT2list (insertRBT 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 setRBT2list (fromJust (lookup g directdeps))
else []))
(setRBT2list (insertRBT f ds))))
(localDepsClosure directdeps)
localDepsClosure :: [(QName,SetRBT QName)] -> [(QName,SetRBT QName)]
localDepsClosure directdeps =
map (\(f,ds)->(f,closure (fst f) ds (setRBT2list ds))) directdeps
where
closure _ olddeps [] = olddeps
closure mod olddeps (f:fs)
| mod == fst f
= let newdeps = filter (\e->not (elemRBT e olddeps))
(setRBT2list (maybe emptySet id (lookup f directdeps)))
in closure mod (foldr insertRBT olddeps newdeps) (newdeps++fs)
| otherwise = closure mod olddeps fs
funcsInExpr :: Expr -> [QName]
funcsInExpr e = setRBT2list (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 insertRBT f (unionMap funcSetOfExpr es)
funcSetOfExpr (Free _ e) = funcSetOfExpr e
funcSetOfExpr (Let bs e) = unionRBT (unionMap (funcSetOfExpr . snd) bs) (funcSetOfExpr e)
funcSetOfExpr (Or e1 e2) = unionRBT (funcSetOfExpr e1) (funcSetOfExpr e2)
funcSetOfExpr (Case _ e bs) = unionRBT (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 unionRBT emptySet . map f
emptySet :: SetRBT QName
emptySet = emptySetRBT leqQName
leqQName :: QName -> QName -> Bool
leqQName (m1,n1) (m2,n2) = leqString (m1++('.':n1)) (m2++('.':n2))
|