Skip to content

Commit 283ff26

Browse files
Hook: LIST.updateAll (#2275)
1 parent 8a1c1df commit 283ff26

File tree

5 files changed

+84
-0
lines changed

5 files changed

+84
-0
lines changed

docs/hooks.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,21 @@ The number of elements in the given list.
704704
[hook{}("LIST.size")]
705705
~~~
706706

707+
## LIST.updateAll
708+
709+
`LIST.updateAll(L1, index, L2)` creates a new list using a list `L2` of size `N`
710+
where the `N` elements of `L1` starting at `index` are replaced with the
711+
contents of `L2`.
712+
The result is `\bottom` in these cases:
713+
714+
- `index` is negative
715+
- `L2` is non-empty and `index + N` exeeds the length of `L1`
716+
717+
~~~
718+
hooked-symbol updateAll{}(List{}, Int{}, List{}) : List{}
719+
[hook{}("LIST.updateAll")]
720+
~~~
721+
707722
## SET
708723

709724
Depends on `BOOL`.

kore/src/Kore/Builtin/List.hs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ symbolVerifiers =
194194
, ( sizeKey
195195
, Builtin.verifySymbol Int.assertSort [assertSort]
196196
)
197+
, ( updateAllKey
198+
, Builtin.verifySymbol assertSort [assertSort, Int.assertSort, assertSort]
199+
)
197200
]
198201

199202
{- | Abort function evaluation if the argument is not a List domain value.
@@ -324,6 +327,24 @@ evalSize resultSort [_list] = do
324327
& return
325328
evalSize _ _ = Builtin.wrongArity sizeKey
326329

330+
evalUpdateAll :: Builtin.Function
331+
evalUpdateAll resultSort [_list1, _ix, _list2] = do
332+
_list1 <- expectBuiltinList getKey _list1
333+
_list2 <- expectBuiltinList getKey _list2
334+
_ix <- fromInteger <$> Int.expectBuiltinInt getKey _ix
335+
let len1 = Seq.length _list1
336+
len2 = Seq.length _list2
337+
result
338+
| _ix < 0 = return (Pattern.bottomOf resultSort)
339+
| len2 == 0 = returnList resultSort _list1
340+
| _ix + len2 > len1 = return (Pattern.bottomOf resultSort)
341+
| otherwise =
342+
let unchanged1 = Seq.take _ix _list1
343+
unchanged2 = Seq.drop (_ix + length _list2) _list1
344+
in returnList resultSort (unchanged1 <> _list2 <> unchanged2)
345+
result
346+
evalUpdateAll _ _ = Builtin.wrongArity updateKey
347+
327348
{- | Implement builtin function evaluation.
328349
-}
329350
builtinFunctions :: Map Text BuiltinAndAxiomSimplifier
@@ -336,6 +357,7 @@ builtinFunctions =
336357
, (updateKey, Builtin.functionEvaluator evalUpdate)
337358
, (inKey, Builtin.functionEvaluator evalIn)
338359
, (sizeKey, Builtin.functionEvaluator evalSize)
360+
, (updateAllKey, Builtin.functionEvaluator evalUpdateAll)
339361
]
340362

341363
{- | Simplify the conjunction or equality of two concrete List domain values.

kore/src/Kore/Builtin/List/List.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module Kore.Builtin.List.List
2424
, updateKey
2525
, inKey
2626
, sizeKey
27+
, updateAllKey
2728
) where
2829

2930
import Prelude.Kore
@@ -197,3 +198,6 @@ inKey = "LIST.in"
197198

198199
sizeKey :: IsString s => s
199200
sizeKey = "LIST.size"
201+
202+
updateAllKey :: IsString s => s
203+
updateAllKey = "LIST.updateAll"

kore/test/Test/Kore/Builtin/Definition.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,11 @@ updateListSymbol = builtinSymbol "updateList" listSort
391391
inListSymbol :: Internal.Symbol
392392
inListSymbol = builtinSymbol "inList" boolSort [intSort, listSort] & hook "LIST.in"
393393

394+
updateAllListSymbol :: Internal.Symbol
395+
updateAllListSymbol =
396+
builtinSymbol "updateAllList" listSort [listSort, intSort, listSort]
397+
& hook "LIST.updateAll"
398+
394399
unitList :: TermLike VariableName
395400
unitList = mkApplySymbol unitListSymbol []
396401

@@ -419,6 +424,13 @@ inList
419424
-> TermLike VariableName
420425
inList x list = mkApplySymbol inListSymbol [x, list]
421426

427+
updateAllList
428+
:: TermLike VariableName
429+
-> TermLike VariableName
430+
-> TermLike VariableName
431+
-> TermLike VariableName
432+
updateAllList l1 ix l2 = mkApplySymbol updateAllListSymbol [l1, ix, l2]
433+
422434
-- ** Map
423435

424436
unitMapSymbol :: Internal.Symbol
@@ -1518,6 +1530,7 @@ listModule =
15181530
, hookedSymbolDecl updateListSymbol
15191531
, hookedSymbolDecl inListSymbol
15201532
, hookedSymbolDecl sizeListSymbol
1533+
, hookedSymbolDecl updateAllListSymbol
15211534
-- A second builtin List sort, to confuse 'asPattern'.
15221535
, listSortDecl2
15231536
, hookedSymbolDecl unitList2Symbol

kore/test/Test/Kore/Builtin/List.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Test.Kore.Builtin.List
1313
, test_inUnit
1414
, test_inElement
1515
, test_inConcat
16+
, test_updateAll
1617
, hprop_unparse
1718
, test_size
1819
--
@@ -417,6 +418,35 @@ test_size =
417418
(===) Pattern.top =<< evaluateT predicate
418419
]
419420

421+
test_updateAll :: [TestTree]
422+
test_updateAll =
423+
[ testCaseWithoutSMT "updateAll([1, 2, 3], -1, [5]) === \\bottom" $ do
424+
result <-
425+
evaluate
426+
$ updateAllList original (mkInt (-1)) (elementList $ mkInt 5)
427+
assertEqual' "" Pattern.bottom result
428+
, testCaseWithoutSMT "updateAll([1, 2, 3], 10, []) === [1, 2, 3]" $ do
429+
result <-
430+
evaluate
431+
$ updateAllList original (mkInt 10) unitList
432+
assertEqual' "" (Pattern.fromTermLike original) result
433+
, testCaseWithoutSMT "updateAll([1, 2, 3], 1, [5]) === [1, 5, 3]" $ do
434+
result <-
435+
evaluate
436+
$ updateAllList original (mkInt 1) (elementList $ mkInt 5)
437+
let expect = asInternal . fmap mkInt $ Seq.fromList [1, 5, 3]
438+
assertEqual' "" (Pattern.fromTermLike expect) result
439+
, testCaseWithoutSMT "updateAll([1, 2, 3], 0, [1, 2, 3, 4] === \\bottom"
440+
$ do
441+
let new = asInternal . fmap mkInt $ Seq.fromList [1, 2, 3, 4]
442+
result <-
443+
evaluate
444+
$ updateAllList original (mkInt 0) new
445+
assertEqual' "" Pattern.bottom result
446+
]
447+
where
448+
original = asInternal . fmap mkInt $ Seq.fromList [1, 2, 3]
449+
420450
mkInt :: Integer -> TermLike VariableName
421451
mkInt = Test.Int.asInternal
422452

0 commit comments

Comments
 (0)