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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
module Symbolic where
import FlatCurry.Annotated.Pretty (ppLiteral, ppQName, ppTypeExp, ppVarIndex)
import FlatCurry.Annotated.Types
import List (nub)
import Text.Pretty
import FlatCurryGoodies (boolType, charType, floatType, intType, isBoolType, prel)
import Language.SMTLIB (Term)
import Utils (mapFst)
data SymObj = SymCons QName TypeExpr
| SymLit LConstr Literal
deriving Show
prelSymCons :: String -> TypeExpr -> SymObj
prelSymCons c ty = SymCons (prel c) ty
soType :: SymObj -> TypeExpr
soType (SymCons _ ty) = ty
soType (SymLit _ l) = case l of
Intc _ -> intType
Floatc _ -> floatType
Charc _ -> charType
data LConstr = E | NE | L | LE | G | GE
deriving (Eq, Ord)
instance Show LConstr where
show E = "=%"
show NE = "/=%"
show L = "<%"
show LE = "<=%"
show G = ">%"
show GE = ">=%"
lcNeg :: LConstr -> LConstr
lcNeg E = NE
lcNeg NE = E
lcNeg L = GE
lcNeg LE = G
lcNeg G = LE
lcNeg GE = L
lcMirror :: LConstr -> LConstr
lcMirror lc = case lc of
L -> G
G -> L
LE -> GE
GE -> LE
_ -> lc
instance Pretty SymObj where
pretty (SymCons qn ty) = ppQName qn <+> doubleColon <+> ppTypeExp ty
pretty (SymLit lcs l) = pretty lcs <+> ppLiteral l
instance Pretty LConstr where
pretty E = text "=="
pretty NE = text "/="
pretty L = text "<"
pretty LE = text "<="
pretty G = text ">"
pretty GE = text ">="
instance Eq SymObj where
o1 == o2 = case (o1, o2) of
(SymCons qn1 _ , SymCons qn2 _) -> qn1 == qn2
(SymLit lcs1 l1, SymLit lcs2 l2) -> lcs1 == lcs2 && l1 == l2
_ -> False
instance Ord SymObj where
compare c1 c2 = case (c1, c2) of
(SymCons qn1 _, SymCons qn2 _) -> compare qn1 qn2
(SymLit _ l1, SymLit _ l2) -> compare l1 l2
getLConstr :: QName -> AExpr TypeExpr -> Maybe (VarIndex, SymObj)
getLConstr qn e = case (rmvApplies e) of
AComb ty _ (fn, _) es
| isBoolType ty -> do
lc <- fmap (if snd qn == "False" then lcNeg else id) (lookup fn litConstrs)
case es of
[ALit _ l, AVar _ v] -> return (v, SymLit (lcMirror lc) l)
[AVar _ v, ALit _ l] -> return (v, SymLit lc l)
_ -> Nothing
_ -> Nothing
rmvApplies :: AExpr TypeExpr -> AExpr TypeExpr
rmvApplies = rmvApplies' []
where
rmvApplies' args e = case e of
AComb _ ct qn es
| isApplyCall e -> case es of
[f,arg] -> rmvApplies' (arg:args) f
_ -> error "IdentifyCases.rmvApplies"
| not (null args) -> AComb boolType ct qn args
_ -> e
isApplyCall :: AExpr a -> Bool
isApplyCall e = case e of
AComb _ FuncCall qn _ -> snd (fst qn) == "apply"
_ -> False
litConstrs :: [(QName, LConstr)]
litConstrs = map (mapFst prel)
[("prim_eqInt", E), ("prim_ltEqInt", LE)]
type Trace = [Decision]
data Decision = Decision CaseID BranchNr VarIndex SymObj [VarIndex]
deriving Show
type CaseID = VarIndex
data BranchNr = BNr Int Int
deriving Show
instance Pretty BranchNr where
pretty (BNr m n) = int m <> text "/" <> int n
instance Pretty Decision where
pretty (Decision cid bnr v sobj args)
= text "caseID" <+> ppVarIndex cid <> colon
<+> tupledSpaced [ text "Branch" <+> pretty bnr, ppVarIndex v, pretty sobj
, list (map ppVarIndex args)
]
ppTrace :: Trace -> Doc
ppTrace = listSpaced . map pretty
getSVars :: Decision -> [VarIndex]
getSVars (Decision _ _ sv _ args) = sv : args
rnmTrace :: [VarIndex] -> Trace -> ([Trace],VarIndex) -> ([Trace],VarIndex)
rnmTrace sargs ds (ts, v) =
let svars = filter (`notElem` sargs) $ nub $ concatMap getSVars ds
sub = zip svars [v, v-1 ..]
in (map (appSub sub) ds : ts, v - length svars)
where
appSub sub' (Decision cid bnr sv scon args) =
let repl x = case lookup x sub' of
Nothing -> x
Just y -> y
in Decision cid bnr (repl sv) scon (map repl args)
type PathConstr = (VarIndex, SymObj, [VarIndex])
data SymNode = SymNode
{ depth :: Depth
, context :: Context
, constants :: [VarIndex]
, pcs :: [PathConstr]
, dvars :: [VarIndex]
, dvar :: VarIndex
}
deriving (Eq, Show)
type Depth = Int
type Context = [VarIndex]
data CoverInfo = CoverInfo
{ uncovered :: [Int]
, coveredCs :: CoveredCs
}
deriving Show
data CoveredCs = CCons [(SymObj, [VarIndex])]
| CConstr LConstr Literal
mkCoveredCs :: SymObj -> [VarIndex] -> CoveredCs
mkCoveredCs sobj@(SymCons qn _) args = CCons [(sobj, args)]
mkCoveredCs (SymLit lc l) _ = CConstr lc l
instance Show CoveredCs where
show (CCons cs) = show cs
show (CConstr lc l) = show lc ++ show l
|