@@ -78,13 +78,20 @@ data FirstOrderType
78
78
-- The type argument of FOVArray is the key type; the value type is
79
79
-- derivable from the default value, which is the second argument. The third
80
80
-- argument is an assignment for all the entries that have non-default values.
81
+ --
82
+ -- FOVOpaqueArray is for arrays we get back from the solver only as a
83
+ -- function call that one can use for lookups. We can't do anything
84
+ -- with that (see Note [FOVArray] below) so we just treat it as an
85
+ -- opaque blob. The arguments are the key and value types, since we
86
+ -- do at least have that info.
81
87
data FirstOrderValue
82
88
= FOVBit Bool
83
89
| FOVInt Integer
84
90
| FOVIntMod Natural Integer
85
91
| FOVWord Natural Integer -- ^ a more efficient special case for 'FOVVec FOTBit _'.
86
92
| FOVVec FirstOrderType [FirstOrderValue ]
87
93
| FOVArray FirstOrderType FirstOrderValue (Map FirstOrderValue FirstOrderValue )
94
+ | FOVOpaqueArray FirstOrderType FirstOrderType
88
95
| FOVTuple [FirstOrderValue ]
89
96
| FOVRec (Map FieldName FirstOrderValue )
90
97
deriving (Eq , Ord , Generic )
@@ -107,11 +114,49 @@ data FirstOrderValue
107
114
-- clear how we'd use this, since the primary thing we do with array
108
115
-- values that come back from the solver is print them as part of
109
116
-- models and without a way to know what keys are present a function
110
- -- that just extracts values is fairly useless. For the moment, if one
111
- -- of these pops up, it fails during conversion to FOVArray.
112
- --
113
- -- Furthermore, restrictions in What4 mean that array values coming
114
- -- back from the solver via that interface are indexed only by
117
+ -- that just extracts values is fairly useless. If one of these pops
118
+ -- up, it comes back as FOVOpaqueArray and we treat it as an opaque
119
+ -- blob. Unfortuately this does happen (maybe we can improve What4 so
120
+ -- it happens less or maybe not at all, but that's not happening right
121
+ -- away) so we need to be able to handle it rather than erroring out
122
+ -- or crashing.
123
+ --
124
+ -- Note that trying to retain the function at this level is
125
+ -- problematic for a number of reasons:
126
+ --
127
+ -- 1. It's not actually a first-order value, and calling it one is
128
+ -- borrowing trouble.
129
+ --
130
+ -- 2. We need ToJSON and FromJSON instances for solver caching, and
131
+ -- there's no way to do that. Now, trying to stick one of these
132
+ -- objects in the solver cache is just not going to work no
133
+ -- matter how we handle it; but things are not structured so
134
+ -- that we can e.g. decline to cache values that contain
135
+ -- function-based arrays so that it's safe to stub out the
136
+ -- ToJSON and FromJSON instances with an error invocation. That
137
+ -- could doubtless be arranged, but it'll take work, possibly a
138
+ -- lot of work. As things stand, we _can_ stuff FOVOpaqueArray
139
+ -- into the solver cache, and it won't do anything useful when
140
+ -- we unstuff it later, but it won't crash.
141
+ --
142
+ -- 3. FirstOrderValue needs Eq and Ord instances, at least but not
143
+ -- necessarily only for use by maps. At least one of those maps
144
+ -- (the one used in FOVArray) is restricted to not have array
145
+ -- values as keys; however, that's not an _explicit_ restriction
146
+ -- (e.g. in typechecking), it's a consequence of the things
147
+ -- What4 allows as array keys. To be halfway safe we'd need to
148
+ -- make it an explicit restriction, and in the current state of
149
+ -- SAW maintenance it's not really clear enough where we'd need
150
+ -- to enforce that to keep it safe. Also, there may be other
151
+ -- such maps about where arrays _can_ be keys, or for that
152
+ -- matter other comparisons. In principle you could have the
153
+ -- compiler find you all the uses by disabling the Eq and Ord
154
+ -- instances. But that doesn't work because the ToJSON and
155
+ -- FromJSON classes need them. The compiler then just fails on
156
+ -- those before telling you anything else.
157
+ --
158
+ -- Besides all the above, restrictions in What4 mean that array values
159
+ -- coming back from the solver via that interface are indexed only by
115
160
-- integers or bitvectors. At this layer, though, we can support any
116
161
-- FirstOrderValue.
117
162
--
@@ -159,6 +204,8 @@ instance Show FirstOrderValue where
159
204
d' = showEntry (" <default>" , d)
160
205
in
161
206
showString " [" . commaSep (vs' ++ [d']) . showString " ]"
207
+ FOVOpaqueArray _kty _vty ->
208
+ showString " [ opaque array, sorry ]"
162
209
FOVTuple vs -> showString " (" . commaSep (map shows vs) . showString " )"
163
210
FOVRec vm -> showString " {" . commaSep (map showField (Map. assocs vm)) . showString " }"
164
211
where
@@ -187,6 +234,8 @@ ppFirstOrderValue opts = loop
187
234
vs' = map ppEntry $ Map. toAscList vs
188
235
in
189
236
brackets (nest 4 (sep (punctuate comma (vs' ++ [d']))))
237
+ FOVOpaqueArray _kty _vty ->
238
+ pretty " [ opaque array, sorry ]"
190
239
FOVTuple xs -> parens (nest 4 (sep (punctuate comma (map loop xs))))
191
240
FOVRec xs -> braces (sep (punctuate comma (map ppField (Map. toList xs))))
192
241
where ppField (f,x) = pretty f <+> pretty ' =' <+> loop x
@@ -264,6 +313,7 @@ firstOrderTypeOf fv =
264
313
FOVWord n _ -> FOTVec n FOTBit
265
314
FOVVec t vs -> FOTVec (fromIntegral (length vs)) t
266
315
FOVArray tk d _vs -> FOTArray tk (firstOrderTypeOf d)
316
+ FOVOpaqueArray tk tv -> FOTArray tk tv
267
317
FOVTuple vs -> FOTTuple (map firstOrderTypeOf vs)
268
318
FOVRec vm -> FOTRec (fmap firstOrderTypeOf vm)
269
319
@@ -391,6 +441,8 @@ scFirstOrderValue sc fv =
391
441
v' <- scFirstOrderValue sc v
392
442
scArrayUpdate sc tk' tv' arr k' v'
393
443
ifoldrM visit arr0 vs
444
+ FOVOpaqueArray _tk _tv -> do
445
+ fail " Cannot convert opaque array to SharedTerm"
394
446
FOVTuple vs -> scTuple sc =<< traverse (scFirstOrderValue sc) vs
395
447
FOVRec vm -> scRecord sc =<< traverse (scFirstOrderValue sc) vm
396
448
0 commit comments