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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
module Verify.Helpers where
import Data.Char ( isDigit )
import Data.IORef
import Data.List
import Analysis.ProgInfo
import Analysis.Types
import CASS.Server ( analyzeGeneric, analyzePublic )
import Data.Time ( ClockTime )
import FlatCurry.Goodies
import FlatCurry.Types
import System.CurryPath ( lookupModuleSourceInLoadPath )
import System.Directory ( getModificationTime )
import Verify.Options ( Options, printWhenStatus )
data AnalysisStore a = AnaStore [(String, ProgInfo a)]
loadAnalysisWithImports :: (Read a, Show a) =>
IORef (AnalysisStore a) -> Analysis a -> Options -> Prog -> IO (QName -> a)
loadAnalysisWithImports anastore analysis opts prog = do
maininfo <- getOrAnalyze (progName prog)
impinfos <- mapM getOrAnalyze (progImports prog)
return $ progInfo2Map $
foldr combineProgInfo maininfo (map publicProgInfo impinfos)
where
getOrAnalyze mname = do
AnaStore minfos <- readIORef anastore
maybe (do printWhenStatus opts $ "Getting " ++ analysisName analysis ++
" for '" ++ mname ++ "' via CASS..."
minfo <- fmap (either id error) $ analyzeGeneric analysis mname
writeIORef anastore (AnaStore ((mname,minfo) : minfos))
return minfo)
return
(lookup mname minfos)
progInfo2Map :: ProgInfo a -> (QName -> a)
progInfo2Map proginfo qf =
maybe (error $ "Analysis information of '" ++ snd qf ++ "'' not found!")
id
(lookupProgInfo qf proginfo)
sortFunResults :: [(QName,a)] -> [(QName,a)]
sortFunResults = sortBy (\ct1 ct2 -> fst ct1 <= fst ct2)
showFunResults :: (a -> String) -> [(QName,a)] -> [String]
showFunResults showf = map (\ (qf,r) -> snd qf ++ ": " ++ showf r)
getModuleModTime :: String -> IO ClockTime
getModuleModTime mname =
lookupModuleSourceInLoadPath mname >>=
maybe (error $ "Source file of module '" ++ mname ++ "' not found!")
(\ (_,fn) -> getModificationTime fn)
transformChoiceInProg :: Prog -> Prog
transformChoiceInProg = updProg id id id (map transChoiceInFunc) id
where
transChoiceInFunc = updFunc id id id id transChoiceInRule
transChoiceInRule = updRule id transChoiceInExpr id
transChoiceInExpr = updCombs updChoiceComb
where
updChoiceComb ct qf es =
if ct == FuncCall && qf == pre "?" && length es == 2
then Or (es!!0) (es!!1)
else Comb ct qf es
patternArgs :: Pattern -> [Int]
patternArgs (Pattern _ vs) = vs
patternArgs (LPattern _) = []
allConsOfTypes :: [TypeDecl] -> [[(QName,Int)]]
allConsOfTypes tdecls = filter (not . null) (map toConss tdecls)
where
toConss (Type _ _ _ cdecls) = map (\ (Cons qc ar _ _) -> (qc,ar)) cdecls
toConss (TypeSyn _ _ _ _) = []
toConss (TypeNew _ _ _ (NewCons qc _ _)) = [(qc,1)]
readQC :: String -> QName
readQC = readMQC []
where
readMQC ms s = let (s1,s2) = break (=='.') s
in case s2 of
"" -> (toMod ms, s1)
[_] -> (toMod ms, "")
_:c:cs -> if isAlpha c && '.' `elem` cs
then readMQC (ms ++ [s1]) (c:cs)
else (toMod (ms ++ [s1]), c:cs)
toMod = intercalate "."
funcsInExpr :: Expr -> [QName]
funcsInExpr e =
trExpr (const id) (const id) comb lt fr (.) cas branch const e []
where
comb ct qn = foldr (.) (combtype ct qn)
combtype ct qn = case ct of FuncCall -> (qn:)
FuncPartCall _ -> (qn:)
_ -> id
lt bs exp = exp . foldr (.) id (map (\ (_,ns) -> ns) bs)
fr _ exp = exp
cas _ exp bs = exp . foldr (.) id bs
branch _ exp = exp
type Pos = [Int]
freshVarPos :: Pos
freshVarPos = []
isFreshVarPos :: Pos -> Bool
isFreshVarPos = null
pre :: String -> QName
pre f = ("Prelude",f)
getSiblingsOf :: [[(QName,Int)]] -> QName -> Maybe [(QName,Int)]
getSiblingsOf allcons qc =
maybe Nothing
(\qcs -> Just $ deleteBy (\x y -> fst x == fst y) (qc,0) qcs)
(find ((qc `elem`) . map fst) allcons)
arityOfCons :: [[(QName,Int)]] -> QName -> Int
arityOfCons allcons qc@(mn,cn)
| null mn
= 0
| otherwise
= maybe (error $ "Arity of constructor '" ++ mn ++ "." ++ cn ++ "' not found")
id
(lookup qc (concat allcons))
isCompleteConstructorList :: [[(QName,Int)]] -> [QName] -> Bool
isCompleteConstructorList _ [] = False
isCompleteConstructorList allcons (c:cs) =
maybe False
(\siblings -> all (`elem` cs) (map fst siblings))
(getSiblingsOf allcons c)
stdConstructors :: [[QName]]
stdConstructors =
[ [pre "False", pre "True"]
, [pre "[]", pre ":"]
, [pre "Nothing", pre "Just"]
, [pre "Left", pre "Right"]
, [pre "LT", pre "EQ", pre "GT"]
, [pre "IOError", pre "UserError", pre "FailError", pre "NondetError"]
] ++
map (\n -> [pre $ "(" ++ take n (repeat ',') ++ ")"]) [0 .. 8]
isEncSearchOp :: QName -> Bool
isEncSearchOp qf@(mn,_) =
mn `elem` ["Control.Search.Unsafe", "Control.Search.AllValues"] ||
qf `elem` map (\n -> ("Control.AllValues",n))
["allValues", "oneValue", "isFail"]
isSetFunOp :: QName -> Bool
isSetFunOp (mn,fn) =
(mn == "Control.Search.SetFunctions" || mn == "Control.SetFunctions") &&
take 3 fn == "set" &&
all isDigit (drop 3 fn)
|