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
|
module Verify.ProgInfo
where
import Data.IORef
import Data.List ( (\\), find )
import qualified Data.Map as Map
import FlatCurry.Build ( fcFailed, pre )
import FlatCurry.Files ( readFlatCurry )
import FlatCurry.Goodies
import FlatCurry.Names ( anonCons )
import FlatCurry.Types
import Verify.Helpers ( fst3, trd3 )
readTransFlatCurry :: String -> IO Prog
readTransFlatCurry mname = do
readFlatCurry mname >>= return . transformChoiceInProg . removeTopForallType
transformChoiceInProg :: Prog -> Prog
transformChoiceInProg = updProgExps (updCombs replaceChoiceCall)
where
replaceChoiceCall ct qf es =
if ct == FuncCall && qf == pre "?" && length es == 2
then Or (es!!0) (es!!1)
else Comb ct qf es
removeTopForallType :: Prog -> Prog
removeTopForallType = updProgFuncs (map rmForallTypeInFunc)
where
rmForallTypeInFunc = updFunc id id id rmForallType id
rmForallType texp = case texp of ForallType _ te -> te
_ -> texp
completeBranchesInFunc :: [(QName,ConsInfo)] -> Bool -> FuncDecl -> FuncDecl
completeBranchesInFunc consinfos withanon = updFuncBody (updCases completeCase)
where
completeCase ct e brs = Case ct e $ case brs of
[] -> []
Branch (LPattern _) _ : _ -> brs
Branch (Pattern pc _) _ : bs -> brs ++
let otherqs = map ((\p -> (patCons p, length (patArgs p)))
. branchPattern) bs
siblings = siblingsOfCons consinfos pc
in if withanon
then if null (siblings \\ otherqs)
then []
else [Branch (Pattern anonCons []) fcFailed]
else
map (\(qc,ar) -> Branch (Pattern qc (take ar [100..])) fcFailed)
(siblings \\ otherqs)
type ConsInfo = (Int, ConsType, [(QName,Int)])
data ConsType = ConsType [TypeExpr] QName [Int]
deriving (Show, Read)
consInfoOfTypeDecls :: [TypeDecl] -> [(QName,ConsInfo)]
consInfoOfTypeDecls = concatMap consInfoOfTypeDecl
consInfoOfTypeDecl :: TypeDecl -> [(QName,ConsInfo)]
consInfoOfTypeDecl (TypeSyn _ _ _ _) = []
consInfoOfTypeDecl (TypeNew nt _ tvs (NewCons qc _ te)) =
[(qc, (1, ConsType [te] nt (map fst tvs), []))]
consInfoOfTypeDecl (Type qt _ tvs cdecls) =
map (\(Cons qc ar _ texps) ->
(qc,
(ar,
ConsType texps qt (map fst tvs),
filter ((/=qc) . fst) (map (\(Cons c car _ _) -> (c,car)) cdecls))))
cdecls
infoOfCons :: [(QName,ConsInfo)] -> QName -> ConsInfo
infoOfCons consinfos qc@(mn,cn) =
maybe (error $ "No info for constructor '" ++ mn ++ "." ++ cn ++ "' found!")
id
(lookup qc consinfos)
arityOfCons :: [(QName,ConsInfo)] -> QName -> Int
arityOfCons consinfos qc@(mn,_)
| null mn = 0
| otherwise = fst3 (infoOfCons consinfos qc)
siblingsOfCons :: [(QName,ConsInfo)] -> QName -> [(QName,Int)]
siblingsOfCons consinfos qc = trd3 (infoOfCons consinfos qc)
isCompleteConstructorList :: [(QName,ConsInfo)] -> [QName] -> Bool
isCompleteConstructorList _ [] = False
isCompleteConstructorList consinfos (c:cs)
| null (fst c) = False
| otherwise = all (`elem` cs) (map fst (siblingsOfCons consinfos c))
data ProgInfo = ProgInfo
{ progInfos :: [(String,ModInfo)]
}
emptyProgInfo :: ProgInfo
emptyProgInfo = ProgInfo []
data ModInfo = ModInfo
{ miProg :: Prog
, miFTypes :: Map.Map String TypeExpr
, miCInfos :: Map.Map String ConsInfo
}
prog2ModInfo :: Prog -> ModInfo
prog2ModInfo prog =
ModInfo prog
(Map.fromList (map (\fd -> (snd (funcName fd), funcType fd))
(progFuncs prog)))
(Map.fromList (map (\(qc, cinfo) -> (snd qc, cinfo))
(consInfoOfTypeDecls (progTypes prog))))
addModInfoFor :: IORef ProgInfo -> String -> IO ()
addModInfoFor piref mname = do
prog <- readTransFlatCurry mname
pis <- readIORef piref
writeIORef piref
(pis { progInfos = (progName prog, prog2ModInfo prog) : progInfos pis})
hasModInfoFor :: IORef ProgInfo -> String -> IO Bool
hasModInfoFor piref mn = do
pi <- readIORef piref
return $ maybe False (const True) (lookup mn (progInfos pi))
getModInfoFor :: IORef ProgInfo -> String -> IO ModInfo
getModInfoFor piref mname = do
pi <- readIORef piref
maybe (addModInfoFor piref mname >> getModInfoFor piref mname)
return
(lookup mname (progInfos pi))
getFlatProgFor :: IORef ProgInfo -> String -> IO Prog
getFlatProgFor piref mn = fmap miProg $ getModInfoFor piref mn
getTypeDeclOf :: IORef ProgInfo -> QName -> IO TypeDecl
getTypeDeclOf piref qtc@(mn,_) = do
prog <- getFlatProgFor piref mn
maybe (error $ "Type declaration for '" ++ show qtc ++ "' not found!")
return
(find (\td -> typeName td == qtc) (progTypes prog))
|