Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom hooked Map externalisation #363

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a091812
Add integration tests to try and capture the sort-forgetting issue
geo2a Nov 9, 2023
05be53c
Rename files
geo2a Nov 10, 2023
5dec4c1
Add another wasm integration test
geo2a Nov 10, 2023
c6d3ec2
Rename test case files
geo2a Nov 10, 2023
c794d51
Add response files
geo2a Nov 10, 2023
9c0dc9d
Include argument sorts when externalizing map elements
geo2a Nov 10, 2023
9e27050
Format with fourmolu
invalid-email-address Nov 10, 2023
2eb6ecf
Add profiling scripts (#357)
goodlyrottenapple Nov 8, 2023
18ebc9a
Further profiling scripts improvements (#359)
geo2a Nov 8, 2023
439ff76
271 simplifier cache (per request) (#358)
jberthold Nov 8, 2023
acb6f19
Improvements to map unification (#360)
goodlyrottenapple Nov 9, 2023
444d2fd
Do not simplify before calling kore-rpc (#362)
jberthold Nov 9, 2023
0a85137
Add LLVM and Cache simplification tracing (#365)
jberthold Nov 12, 2023
bac937d
Create more focused integration tests
geo2a Nov 13, 2023
62f87f0
Merge branch 'main' into georgy/better-map-internalisation
geo2a Nov 13, 2023
30e8ee7
Output arguments' and result's sorts for symbols in summary
geo2a Nov 14, 2023
4b53a03
Drop MapInt2Int
geo2a Nov 14, 2023
d38e79e
Construct minimised wasm configuration
geo2a Nov 14, 2023
3ee5724
Drop simplify request/responses
geo2a Nov 14, 2023
26d8851
Add execute request, demonstrating correct sorts
geo2a Nov 14, 2023
db01a14
Implelemt Map.update for MapInt2Val
geo2a Nov 14, 2023
4b9cb7d
Format with fourmolu
invalid-email-address Nov 14, 2023
981a45e
Force evaluation to happen in the LLVM backend
geo2a Nov 14, 2023
c4608e8
Add definition of a customized hooked map
geo2a Nov 14, 2023
b50af99
Add int-to-int Map to the LLVM integration test definition
geo2a Nov 14, 2023
3003462
Format with fourmolu
invalid-email-address Nov 14, 2023
68f1598
add prim update test
goodlyrottenapple Nov 15, 2023
566487d
Format with fourmolu
invalid-email-address Nov 15, 2023
1d5cc6b
Chnages to wasm-map.k
geo2a Nov 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions library/Booster/Definition/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Data.ByteString.Char8 (ByteString)
import Data.ByteString.Char8 qualified as BS
import Data.List.Extra (sortOn)
import Data.Map qualified as Map
import Data.Maybe (fromMaybe)
import Data.Maybe (catMaybes, fromMaybe)
import Data.Set qualified as Set
import Data.Text (Text)
import GHC.Generics (Generic)
Expand All @@ -34,13 +34,15 @@ import Prettyprinter.Render.String qualified as Pretty (renderString)

import Booster.Definition.Attributes.Base
import Booster.Definition.Base
import Booster.Pattern.Base (Symbol (..), sortName)
import Booster.Pattern.Index (TermIndex (..))
import Booster.Prettyprinter
import Booster.Util

data Summary = Summary
{ file :: FilePath
, modNames, sortNames, symbolNames :: [ByteString]
, modNames, sortNames :: [ByteString]
, symbolSignatures :: [(ByteString, [ByteString], Maybe ByteString)]
, subSorts :: Map.Map ByteString [ByteString]
, axiomCount, preserveDefinednessCount, containAcSymbolsCount :: Int
, functionRuleCount, simplificationCount, predicateSimplificationCount :: Int
Expand All @@ -58,7 +60,9 @@ mkSummary file def =
{ file
, modNames = Map.keys def.modules
, sortNames = Map.keys def.sorts
, symbolNames = Map.keys def.symbols
, symbolSignatures =
map (\symbol -> (symbol.name, catMaybes (map sortName symbol.argSorts), sortName symbol.resultSort)) $
Map.elems def.symbols
, subSorts = Map.map (Set.toList . snd) def.sorts
, axiomCount = length $ concat $ concatMap Map.elems (Map.elems def.rewriteTheory)
, preserveDefinednessCount =
Expand Down Expand Up @@ -94,7 +98,7 @@ instance Pretty Summary where
Pretty.vsep $
[ list prettyLabel "Modules" summary.modNames
, list prettyLabel "Sorts" summary.sortNames
, list prettyLabel "Symbols" summary.symbolNames
, list prettySymbolSignature "Symbols" summary.symbolSignatures
, "Axioms: " <> pretty summary.axiomCount
, "Axioms preserving definedness: " <> pretty summary.preserveDefinednessCount
, "Axioms containing AC symbols: " <> pretty summary.containAcSymbolsCount
Expand Down Expand Up @@ -132,6 +136,11 @@ instance Pretty Summary where

prettyLabel = either error (pretty . BS.unpack) . decodeLabel

prettySymbolSignature (name, argSortNames, resultSortName) =
let prettyResultSortName = pretty . BS.unpack $ maybe "" ("->" <>) resultSortName
prettyArgSortNames = pretty . BS.unpack $ "{" <> BS.intercalate "," argSortNames <> "}"
in prettyLabel name <> prettyArgSortNames <> prettyResultSortName

prettyTermIndex Anything = "Anything"
prettyTermIndex (TopSymbol sym) = prettyLabel sym
prettyTermIndex None = "None"
Expand Down
23 changes: 20 additions & 3 deletions library/Booster/Pattern/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ data Sort
pattern SortBool :: Sort
pattern SortBool = SortApp "SortBool" []

sortName :: Sort -> Maybe SortName
sortName = \case
SortApp name _args -> Just name
SortVar _ -> Nothing

-- | A variable for symbolic execution or for terms in a rule.
data Variable = Variable
{ variableSort :: Sort
Expand Down Expand Up @@ -271,9 +276,21 @@ externaliseKmapUnsafe def keyVals rest =
s
keyVals
where
unit = SymbolApplication (stripCollectionMetadata $ unitSymbol $ KMapMeta def) [] []
k |-> v = SymbolApplication (stripCollectionMetadata $ kmapElementSymbol def) [] [k, v]
a `con` b = SymbolApplication (stripCollectionMetadata $ concatSymbol $ KMapMeta def) [] [a, b]
-- unit = SymbolApplication (stripCollectionMetadata $ unitSymbol $ KMapMeta def) [] []
unit = Term mempty $ SymbolApplicationF (unitSymbol $ KMapMeta def) [] []
-- k |-> v =
-- SymbolApplication
-- (stripCollectionMetadata $ kmapElementSymbol def)
-- []
-- [k, v]
k |-> v =
Term mempty $
SymbolApplicationF
(kmapElementSymbol def)
[]
[k, v]
-- a `con` b = SymbolApplication (stripCollectionMetadata $ concatSymbol $ KMapMeta def) [] [a, b]
a `con` b = Term mempty $ SymbolApplicationF (concatSymbol $ KMapMeta def) [] [a, b]
{-# INLINE externaliseKmapUnsafe #-}

stripCollectionMetadata :: Symbol -> Symbol
Expand Down
146 changes: 146 additions & 0 deletions test/llvm-integration/LLVM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ llvmSpec =
it "should work with latin-1strings" $
hedgehog . propertyTest . latin1Prop

describe "LLVM hooked Map simplifications" $
it "should preserve singleton maps" $
hedgehog . propertyTest . mapKItemInjProp

--------------------------------------------------
-- individual hedgehog property tests and helpers

Expand Down Expand Up @@ -147,6 +151,37 @@ latin1Prop api = property $ do
| otherwise -> error $ "Unexpected sort " <> show s
otherTerm -> error $ "Unexpected term " <> show otherTerm

mapKItemInjProp :: Internal.API -> Property
mapKItemInjProp api = property $ do
let k = wrapIntTerm 1
let kPrim = intTerm 1
let v = wrapIntTerm 2
LLVM.simplifyTerm api testDef (update kPrim v) (SortApp "SortMapInt2Int" []) === elem k v
where
update k v =
SymbolApplication
(fromMaybe (error "missing symbol") $ Map.lookup "LblMapInt2Val'Coln'primitiveUpdate" defSymbols)
[]
[ SymbolApplication
(fromMaybe (error "missing symbol") $ Map.lookup "Lbl'Stop'MapInt2Int" defSymbols)
[]
[]
, k
, v
]

elem k v =
SymbolApplication
(kmapElementSymbol sortMapInt2Int)
[]
[k, v]

wrapIntTerm i =
SymbolApplication
(fromMaybe (error "missing symbol") $ Map.lookup "LblwrapInt" defSymbols)
[]
[intTerm i]

------------------------------------------------------------

runKompile :: IO ()
Expand Down Expand Up @@ -268,6 +303,20 @@ sortMapKmap =
, mapSortName = "SortMap"
}

sortMapInt2Int :: KMapDefinition
sortMapInt2Int =
KMapDefinition
{ symbolNames =
KCollectionSymbolNames
{ unitSymbolName = "Lbl'Stop'MapInt2Int"
, elementSymbolName = "Lbl'Unds'Int2Int'Pipe'-'-GT-Unds'"
, concatSymbolName = "Lbl'Unds'MapInt2Int'Unds'"
}
, keySortName = "SortWrappedInt"
, elementSortName = "SortInt"
, mapSortName = "SortMapInt2Int"
}

sortListKList :: KListDefinition
sortListKList =
KListDefinition
Expand Down Expand Up @@ -390,6 +439,13 @@ defSorts =
, Set.fromList ["SortMap"]
)
)
,
( "SortMapInt2Int"
,
( SortAttributes{collectionAttributes = Just (sortMapInt2Int.symbolNames, KMapTag), argCount = 0}
, Set.fromList ["SortMapInt2Int"]
)
)
,
( "SortNum"
,
Expand Down Expand Up @@ -563,6 +619,24 @@ defSymbols =
}
}
)
,
( "Lbl'Stop'MapInt2Int"
, Symbol
{ name = "Lbl'Stop'MapInt2Int"
, sortVars = []
, argSorts = []
, resultSort = SortApp "SortMapInt2Int" []
, attributes =
SymbolAttributes
{ collectionMetadata = Just $ KMapMeta sortMapInt2Int
, symbolType = TotalFunction
, isIdem = IsNotIdem
, isAssoc = IsNotAssoc
, isMacroOrAlias = IsNotMacroOrAlias
, hasEvaluators = CanBeEvaluated
}
}
)
,
( "Lbl'Stop'Set"
, Symbol
Expand Down Expand Up @@ -671,6 +745,24 @@ defSymbols =
}
}
)
,
( "Lbl'Unds'MapInt2Int'Unds'"
, Symbol
{ name = "Lbl'Unds'MapInt2Int'Unds'"
, sortVars = []
, argSorts = [SortApp "SortMapInt2Int" [], SortApp "SortMapInt2Int" []]
, resultSort = SortApp "SortMapInt2Int" []
, attributes =
SymbolAttributes
{ collectionMetadata = Just $ KMapMeta sortMapInt2Int
, symbolType = PartialFunction
, isIdem = IsNotIdem
, isAssoc = IsAssoc
, isMacroOrAlias = IsNotMacroOrAlias
, hasEvaluators = CanBeEvaluated
}
}
)
,
( "Lbl'Unds'Set'Unds'"
, Symbol
Expand Down Expand Up @@ -1301,6 +1393,60 @@ defSymbols =
}
}
)
,
( "Lbl'Unds'Int2Int'Pipe'-'-GT-Unds'"
, Symbol
{ name = "Lbl'Unds'Int2Int'Pipe'-'-GT-Unds'"
, sortVars = []
, argSorts = [SortApp "SortWrappedInt" [], SortApp "SortInt" []]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geo2a I don't follow why the second argument has sort Int here; in the corresponding definition the second argument has sort WrappedInt? I might be missing something though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, and it indeed makes the test I constructed to pass. We have been able to pin-point the problem to the MAP.update hook in the LLVM backend. I'll update the integration tests and also open an issue in the LLVm backend with the somewhat minimized definition and input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remarkable timing; I had also just managed to build and get the same test to pass with the value sort as WrappedInt! Let's take a look at your new minimized example in our meeting this afternoon.

, resultSort = SortApp "SortMapInt2Int" []
, attributes =
SymbolAttributes
{ collectionMetadata = Just $ KMapMeta sortMapInt2Int
, symbolType = TotalFunction
, isIdem = IsNotIdem
, isAssoc = IsNotAssoc
, isMacroOrAlias = IsNotMacroOrAlias
, hasEvaluators = CanBeEvaluated
}
}
)
,
( "LblwrapInt"
, Symbol
{ name = "LblwrapInt"
, sortVars = []
, argSorts = [SortApp "SortInt" []]
, resultSort = SortApp "SortWrappedInt" []
, attributes =
SymbolAttributes
{ collectionMetadata = Nothing
, symbolType = TotalFunction
, isIdem = IsNotIdem
, isAssoc = IsNotAssoc
, isMacroOrAlias = IsNotMacroOrAlias
, hasEvaluators = CanBeEvaluated
}
}
)
,
( "LblMapInt2Val'Coln'primitiveUpdate"
, Symbol
{ name = "LblMapInt2Val'Coln'primitiveUpdate"
, sortVars = []
, argSorts = [SortApp "MapInt2Int" [], SortApp "SortInt" [], SortApp "SortWrappedInt" []]
, resultSort = SortApp "MapInt2Int" []
, attributes =
SymbolAttributes
{ collectionMetadata = Nothing
, symbolType = TotalFunction
, isIdem = IsNotIdem
, isAssoc = IsNotAssoc
, isMacroOrAlias = IsNotMacroOrAlias
, hasEvaluators = CanBeEvaluated
}
}
)
,
( "Lbl'UndsPipe'Int'Unds'"
, Symbol
Expand Down
38 changes: 38 additions & 0 deletions test/llvm-integration/definition/llvm.k
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module LLVM
imports MAP
imports SET
imports K-EQUAL
imports MAP-INT2INT

syntax Num ::= Even | Odd
syntax Even ::= Zero() | Two() | Four() | Six() | Eight() | Ten()
Expand Down Expand Up @@ -39,3 +40,40 @@ module LLVM
rule div2(Ten()) => Five()

endmodule

module MAP-INT2INT
imports INT

syntax WrappedInt

syntax WrappedInt ::= wrap(Int) [symbol, klabel(wrapInt)]
syntax Int ::= unwrap(WrappedInt) [function, total, injective, symbol, klabel(unwrapInt)]
rule unwrap(wrap(A:Int)) => A

syntax MapInt2Int [hook(MAP.Map)]
syntax MapInt2Int ::= MapInt2Int MapInt2Int
[ left, function, hook(MAP.concat), klabel(_MapInt2Int_),
symbol, assoc, comm, unit(.MapInt2Int), element(_Int2Int|->_),
index(0), format(%1%n%2)
]
syntax MapInt2Int ::= ".MapInt2Int"
[ function, total, hook(MAP.unit),
klabel(.MapInt2Int), symbol, latex(\dotCt{MapInt2Int})
]
syntax MapInt2Int ::= WrappedInt "Int2Int|->" WrappedInt
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the production I believe corresponds to the above comment @geo2a

[ function, total, hook(MAP.element),
klabel(_Int2Int|->_), symbol,
latex({#1}\mapsto{#2}), injective
]

syntax MapInt2Int ::= MapInt2Int "[" key: WrappedInt "<-" value: WrappedInt "]"
[function, total, klabel(MapInt2Val:update), symbol, hook(MAP.update), prefer]


syntax MapInt2Int ::= MapInt2Int "{{" key: Int "<-" value: WrappedInt "}}"
[ function, total, klabel(MapInt2Val:primitiveUpdate), symbol,
prefer
]
rule M:MapInt2Int {{ Key:Int <- Value:WrappedInt }}
=> M[wrap(Key) <- Value]
endmodule
56 changes: 56 additions & 0 deletions test/rpc-integration/resources/wasm-maps.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module WASM-MAPS
imports MAP-VAL-TO-VAL

configuration
<wasm>
<instrs> $PGM </instrs>
<locals> .MapValToVal </locals>
</wasm>

syntax Instr ::= "init_local" Int Int
// -----------------------------------
rule <instrs> init_local INDEX VALUE => . ... </instrs>
<locals> LOCALS => LOCALS {{ wrap(INDEX) <- wrap(VALUE) }} </locals>

endmodule

module MAP-VAL-TO-VAL
imports WRAPPED-INT

syntax Val ::= WrappedInt
// -----------------------

syntax MapValToVal [hook(MAP.Map)]
syntax MapValToVal ::= MapValToVal MapValToVal
[ left, function, hook(MAP.concat), klabel(_MapValToVal_),
symbol, assoc, comm, unit(.MapValToVal), element(_Val2Val|->_)
]
syntax MapValToVal ::= ".MapValToVal"
[function, total, hook(MAP.unit),klabel(.MapValToVal), symbol]
syntax MapValToVal ::= Val "Val2Val|->" Val
[function, total, hook(MAP.element), klabel(_Val2Val|->_), symbol]

syntax MapValToVal ::= MapValToVal "[" key: Val "<-" value: Val "]" [function, total, klabel(MapVal2Val:update), symbol, hook(MAP.update), prefer]

syntax priorities _Val2Val|->_ > _MapValToVal_ .MapValToVal
syntax non-assoc _Val2Val|->_

syntax MapValToVal ::= MapValToVal "{{" key: Val "<-" value: Val "}}"
[ function, total, klabel(MapValToVal:primitiveUpdate), symbol,
prefer
]
rule M:MapValToVal {{ Key:Val <- Value:Val }}
=> M[Key <- Value]

endmodule

module WRAPPED-INT
imports INT

syntax WrappedInt ::= wrap(Int) [symbol, klabel(wrapInt)]
// -------------------------------------------------------

syntax Int ::= unwrap(WrappedInt) [function, total, injective, symbol, klabel(unwrapInt)]
// ---------------------------------------------------------------------------------------
rule unwrap(wrap(A:Int)) => A
endmodule
Loading
Loading