Skip to content

Commit a7b2d28

Browse files
jbertholdgithub-actions
andauthored
add cases for unevaluated keys to MAP hooks (#3964)
Some of the `MAP` hooks were missing cases for an unevaluated key argument (they were assuming that the argument would already be fully evaluated when the hook is called). In these cases, the hooks should typically return `Nothing` instead of returning a result. --------- Co-authored-by: github-actions <[email protected]>
1 parent e98b8a6 commit a7b2d28

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

booster/library/Booster/Builtin/MAP.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ mapUpdateHook args
5858
pure Nothing -- have opaque part, no result
5959
| any (not . isConstructorLike_ . fst) pairs ->
6060
pure Nothing -- have unevaluated keys, no result
61+
| not $ isConstructorLike_ key ->
62+
pure Nothing -- unevaluated update key, no result
6163
| otherwise -> -- key certain to be absent, no rest: add pair
6264
pure $ Just $ KMap def ((key, newValue) : pairs) Nothing
6365
| [_other, _, _] <- args =
@@ -126,6 +128,8 @@ mapRemoveHook args
126128
pure Nothing -- have opaque part, no result
127129
| any (not . isConstructorLike_ . fst) pairs ->
128130
pure Nothing -- have unevaluated keys, no result
131+
| not $ isConstructorLike_ key ->
132+
pure Nothing -- remove key unevaluated, no result
129133
| otherwise -> -- key certain to be absent, no rest: map unchanged
130134
pure $ Just m
131135
| [_other, _] <- args =
@@ -166,6 +170,8 @@ mapLookupOrDefaultHook args
166170
pure Nothing -- have opaque part, no result
167171
| any (not . isConstructorLike_ . fst) pairs ->
168172
pure Nothing -- have unevaluated keys, no result
173+
| not $ isConstructorLike_ key ->
174+
pure Nothing -- lookup key unevaluated, no result
169175
| otherwise -> -- certain that the key is not in the map
170176
pure $ Just defaultValue
171177
| [_other, _, _] <- args =
@@ -188,6 +194,7 @@ mapInKeysHook args
188194
pure $ Just $ boolTerm True
189195
(False, False)
190196
| Nothing <- mbRest -- no opaque rest
197+
, isConstructorLike_ key -- key to search is evaluated
191198
, null uneval'edKeys -> -- no keys unevaluated
192199
pure $ Just $ boolTerm False
193200
| otherwise -> -- key could be present once evaluated

booster/unit-tests/Test/Booster/Builtin.hs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ testMapUpdateHook =
260260
result <- runUpdate [Fixture.functionKMapWithOneItemAndRest, keyG, value2]
261261
let expected = mapWith [(keyG, value2)] (Just restVar)
262262
Just expected @=? result
263+
, testCase "cannot update map at unevaluated key if key not syntactically present" $ do
264+
let keyG = [trm| g{}() |]
265+
result <- runUpdate [Fixture.concreteKMapWithTwoItems, keyG, value2]
266+
Nothing @=? result
263267
, testCase "cannot update map with symbolic rest if key not present" $ do
264268
result <- runUpdate [Fixture.concreteKMapWithOneItemAndRest, key2, value2]
265269
Nothing @=? result
@@ -376,6 +380,9 @@ testMapRemoveHook =
376380
Just Fixture.emptyKMap @=? result
377381
result2 <- runRemove [Fixture.functionKMapWithOneItemAndRest, [trm| g{}() |]]
378382
Just restVar @=? result2
383+
, testCase "no result if removing non-concrete keys not syntactically equal" $ do
384+
result <- runRemove [Fixture.concreteKMapWithTwoItems, [trm| g{}() |]]
385+
Nothing @=? result
379386
, testCase "no result when map has non-concrete syntactically different keys" $ do
380387
result <- runRemove [Fixture.functionKMapWithOneItem, key]
381388
Nothing @=? result
@@ -449,6 +456,10 @@ testMapLookupHook =
449456
, testCase "returns item for a non-evaluated key when present" $ do
450457
result <- runLookup [Fixture.functionKMapWithOneItemAndRest, [trm| g{}() |]]
451458
Just [trm| \dv{SortTestKMapItem{}}("value") |] @=? result
459+
, testProperty "no result for an unevaluated key not syntactically present" . property $ do
460+
assocs <- forAll $ genAssocs (Range.linear 0 10)
461+
result <- runLookup [mapWith assocs Nothing, [trm| g{}() |]]
462+
Nothing === result
452463
, testCase "no result if map has non-evaluated keys when key not found" $ do
453464
result <- runLookup [Fixture.functionKMapWithOneItem, notAKey]
454465
Nothing @=? result
@@ -494,6 +505,10 @@ testMapLookupOrDefaultHook =
494505
, testCase "returns item for a non-evaluated key when present" $ do
495506
result <- runLookup [Fixture.functionKMapWithOneItemAndRest, [trm| g{}() |], defItem]
496507
Just [trm| \dv{SortTestKMapItem{}}("value") |] @=? result
508+
, testProperty "no result for an unevaluated key not syntactically present" . property $ do
509+
assocs <- forAll $ genAssocs (Range.linear 0 10)
510+
result <- runLookup [mapWith assocs Nothing, [trm| g{}() |], defItem]
511+
Nothing === result
497512
, testCase "no result if map has non-evaluated keys and key not found" $ do
498513
result <- runLookup [Fixture.functionKMapWithOneItemAndRest, notAKey, defItem]
499514
Nothing @=? result
@@ -532,11 +547,20 @@ testMapInKeysHook =
532547
Just (Builtin.boolTerm True) === result
533548
result2 <- runInKeys [key, mapWith assocs (Just restVar)]
534549
Just (Builtin.boolTerm True) === result2
550+
, testCase "returns true when key syntactically present" $ do
551+
result <- runInKeys [[trm| g{}() |], Fixture.functionKMapWithOneItem]
552+
Just (Builtin.boolTerm True) @=? result
553+
result2 <- runInKeys [[trm| g{}() |], Fixture.functionKMapWithOneItemAndRest]
554+
Just (Builtin.boolTerm True) @=? result2
535555
, testCase "no result if unevaluated map keys present" $ do
536556
result <- runInKeys [notAKey, Fixture.functionKMapWithOneItem]
537557
Nothing @=? result
538558
result2 <- runInKeys [notAKey, Fixture.functionKMapWithOneItemAndRest]
539559
Nothing @=? result2
560+
, testProperty "no result for an unevaluated key not present" . property $ do
561+
assocs <- forAll $ genAssocs (Range.linear 0 42)
562+
result <- runInKeys [[trm| g{}() |], mapWith assocs Nothing]
563+
Nothing === result
540564
]
541565
where
542566
runInKeys :: MonadFail m => [Term] -> m (Maybe Term)

0 commit comments

Comments
 (0)