Skip to content

Commit 0aabe16

Browse files
committed
add MAP.updateAll hook to booster and docs
1 parent 1439f94 commit 0aabe16

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

booster/library/Booster/Builtin.hs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE MultiWayIf #-}
12
{- |
23
Copyright : (c) Runtime Verification, 2023
34
License : BSD-3-Clause
@@ -24,12 +25,14 @@ import Data.Map (Map)
2425
import Data.Map qualified as Map
2526
import Data.Set qualified as Set
2627
import Data.Text (Text)
28+
import Data.Text qualified as Text
2729
import Prettyprinter (pretty, vsep)
2830
import Text.Read (readMaybe)
2931

3032
import Booster.Definition.Attributes.Base (
3133
KCollectionSymbolNames (..),
3234
KListDefinition (..),
35+
KMapDefinition (..),
3336
)
3437
import Booster.Pattern.Base
3538
import Booster.Pattern.Bool
@@ -206,6 +209,7 @@ builtinsMAP =
206209
Map.mapKeys ("MAP." <>) $
207210
Map.fromList
208211
[ "update" ~~> mapUpdateHook
212+
, "updateAll" ~~> mapUpdateAllHook
209213
, "remove" ~~> mapRemoveHook
210214
, -- removeAll: requires a Set argument
211215
"size" ~~> mapSizeHook
@@ -238,6 +242,45 @@ mapUpdateHook args
238242
| otherwise =
239243
throwE . renderText $ "MAP.update: wrong arity " <> pretty (length args)
240244

245+
mapUpdateAllHook :: BuiltinFunction
246+
mapUpdateAllHook [KMap def1 _ _, KMap def2 _ _]
247+
| def1 /= def2 =
248+
throwE $
249+
"MAP.updateAll: incompatible maps " <>
250+
Text.pack (show (def1.mapSortName, def2.mapSortName))
251+
mapUpdateAllHook [original, KMap _ [] Nothing] =
252+
-- updates map is empty, result is original map
253+
pure $ Just original
254+
mapUpdateAllHook [KMap _ [] Nothing, updates] =
255+
-- original map is empty, result is updates map
256+
pure $ Just updates
257+
mapUpdateAllHook [KMap _ _ (Just _), _updates] =
258+
-- indeterminate part in original map, leave unevaluated
259+
pure Nothing
260+
mapUpdateAllHook [KMap def pairs1 Nothing, KMap _ pairs2 mbRest2]
261+
-- performing the update requires all keys to be fully evaluated
262+
-- (constructor-like) or syntactically equal.
263+
| Set.null origKeys = -- all keys in the original map were updated (syntactically)
264+
pure $ Just $ KMap def updated mbRest2
265+
| Set.null updateKeys
266+
, Nothing <- mbRest2 = -- all update keys were (syntactically) present
267+
pure $ Just $ KMap def updated Nothing
268+
| all isConstructorLike_ (updateKeys <> origKeys)
269+
, Nothing <- mbRest2 = -- all untouched or added keys are fully evaluated
270+
pure $ Just $ KMap def updated Nothing
271+
| otherwise = -- uncertain whether all keys updated, leave unevaluated
272+
pure Nothing
273+
where
274+
orig = Map.fromList pairs1
275+
update = Map.fromList pairs2
276+
updated = Map.assocs $ Map.unionWith (\_ u -> u) orig update
277+
origKeys = Set.difference (Map.keysSet orig) (Map.keysSet update)
278+
updateKeys = Set.difference (Map.keysSet update) (Map.keysSet orig)
279+
mapUpdateAllHook [_, _] =
280+
pure Nothing -- at least one argument not an internalised map, leave unevaluated
281+
mapUpdateAllHook args =
282+
throwE . renderText $ "MAP.update: wrong arity " <> pretty (length args)
283+
241284
mapRemoveHook :: BuiltinFunction
242285
mapRemoveHook args
243286
| [m@(KMap def pairs mbRest), key] <- args = do

docs/hooks.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,16 @@ present, replace the associated value with the new value provided.
536536
[hook{}("MAP.update")]
537537
~~~
538538

539+
### MAP.updateAll
540+
541+
Insert all associations from the second map into the first map. If any key
542+
is already present in the first map, the associated value is replaced with
543+
the new value from the second map.
544+
545+
~~~
546+
hooked-symbol updateMap{}(Map{}, Map{}) : Map{}
547+
[hook{}("MAP.updateAll")]
548+
~~~
539549
### MAP.remove
540550

541551
Remove the key and the value associated with it from the map. If the key

0 commit comments

Comments
 (0)