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

Remove SBV from the SMT backend #93

Merged
merged 63 commits into from
Apr 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6225b15
smt: init
d-xo Mar 9, 2021
6c1d54e
SMT: add expToSMT2
d-xo Mar 9, 2021
4440635
remove unused When argument in local functions
kjekac Mar 9, 2021
d1519c2
implement SMT array lookup
kjekac Mar 9, 2021
29230db
start rerouting Main to use new SMT backend
kjekac Mar 10, 2021
8af0633
simplify SMT.addToStore
kjekac Mar 10, 2021
28985d9
add clarifying comment
kjekac Mar 10, 2021
24156c1
smt: add show instance for SMTExp
d-xo Mar 10, 2021
4428910
smt: initial sketch of solver communication
d-xo Mar 10, 2021
86d8588
smt: first working solver interactions
d-xo Mar 10, 2021
c0d3e84
test: add test for well typedness of smt expressions
d-xo Mar 10, 2021
d0fabf7
smt: declare calldata args
d-xo Mar 10, 2021
d908447
tests generate with/without exponentiation according to compatibility
kjekac Mar 11, 2021
8986aa5
smt: start generating postcondition queries
d-xo Mar 11, 2021
b07a1b5
smt: fix existing code
d-xo Mar 11, 2021
8e9b8c5
tests compile
kjekac Mar 11, 2021
046c87a
tests work, runSMT checks for timeouts
kjekac Mar 11, 2021
4694eed
implement mkPostconditionQueries
kjekac Mar 11, 2021
c3f4d4c
fix bug with too many parentheses in generated SMT code
kjekac Mar 12, 2021
0de0d0b
smt: only take calldata decls and asserts from the interface
kjekac Mar 12, 2021
ea88cd3
smt: postcondition semantics is consistent with sbv backend (storage …
kjekac Mar 12, 2021
09acb0f
smt backend generates queries for constructors
kjekac Mar 17, 2021
ca7bf48
SMT: remove Var type
d-xo Apr 20, 2021
ce6867e
SMT: add query abstraction, implement postcondition checking
d-xo Apr 21, 2021
00cc5a6
SMT: rough draft support for invariant checking
d-xo Apr 21, 2021
5227526
SMT: handle implicit storage locations
d-xo Apr 21, 2021
3897d7f
Main: exit fail if anything cannot be proven
d-xo Apr 21, 2021
4d38d6a
SMT: deduplicate all the things
d-xo Apr 21, 2021
135ba48
SMT: allow some very simplistic exponentiation expressions
d-xo Apr 21, 2021
32a160b
AST: seperate fields for invariant preconditions
d-xo Apr 22, 2021
765bd24
SMT: fix encoding for mapping updates
d-xo Apr 22, 2021
fdf139f
AST: update invariant serialization
d-xo Apr 22, 2021
fc6e73f
SMT: fix storage encoding
d-xo Apr 22, 2021
92fa6b4
tests: indirect constructor assignment is working with the new backend
d-xo Apr 22, 2021
6a09912
nix: add z3 and cvc4 to the shell
d-xo Apr 22, 2021
e9e50ff
Prove: rm module
d-xo Apr 22, 2021
e2842f7
test: fixup smt fuzz tests
d-xo Apr 22, 2021
23c9448
test: optimize smt fuzz tests
d-xo Apr 22, 2021
2c148f2
Main: parse command line flags for prove
d-xo Apr 22, 2021
239b2d8
SMT: initial support for cvc4
d-xo Apr 26, 2021
c0e10c9
SMT: more cvc4 support
d-xo Apr 27, 2021
93c47a8
SMT: refactor runSMT to clean test code
d-xo Apr 27, 2021
63c3fe6
SMT: tidyup and docs
d-xo Apr 27, 2021
9b0907b
nix: skip tests when building
d-xo Apr 27, 2021
b22100c
SMT: formatting
d-xo Apr 28, 2021
3d7c83c
SMT: fix z3 invocation
d-xo Apr 28, 2021
51910ad
SMT: fix encoding of implicit storage locations
d-xo Apr 28, 2021
7fc9f97
remove redundant parentheses
kjekac Apr 28, 2021
bbb08a9
missed one parenthesis :)
kjekac Apr 28, 2021
3d1eec9
remove some more redundant syntax
kjekac Apr 28, 2021
1eb1e88
Update src/Main.hs
xwvvvvwx Apr 28, 2021
7efa9e9
Update src/Enrich.hs
xwvvvvwx Apr 28, 2021
2098ac7
SMT: formatting
d-xo Apr 28, 2021
1634fe8
tests: add failing test for duplicated arg names
d-xo Apr 28, 2021
ffb2cf9
SMT: disambiguate calldata vars for invariant queries
d-xo Apr 28, 2021
c643399
tests: duplicated arg name test fails now (as it should...)
d-xo Apr 28, 2021
5e5e2e1
Apply suggestions from code review
xwvvvvwx Apr 28, 2021
844876a
tests: add test for mapping encoding
d-xo Apr 28, 2021
db446dc
SMT: general cleanup & code review comments
d-xo Apr 28, 2021
f93fce3
SMT: clearer debug output
d-xo Apr 28, 2021
3a734fd
unlines <3
d-xo Apr 28, 2021
9ef24ba
SMT: minor typos
d-xo Apr 28, 2021
5ae6777
SMT: documentation typo
d-xo Apr 29, 2021
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
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ test-parse: parser compiler $(parser_pass:=.parse.pass) $(parser_fail:=.parse.fa
test-type: parser compiler $(typing_pass:=.type.pass) $(typing_fail:=.type.fail)
test-invariant: parser compiler $(invariant_pass:=.invariant.pass) $(invariant_fail:=.invariant.fail)
test-hevm: parser compiler $(hevm_pass:=.hevm.pass) $(hevm_fail:=.hevm.fail)

test-cabal: src/*.hs
cd src && cabal v2-run test

# Just checks parsing
tests/%.parse.pass:
Expand Down Expand Up @@ -91,4 +92,4 @@ tests/hevm/fail/%.act.hevm.fail:
./bin/act hevm --spec tests/hevm/fail/$*.act --soljson tests/hevm/fail/$*.sol.json && exit 1 || echo 0
rm tests/hevm/fail/$*.sol.json

test: test-parse test-type test-invariant test-coq test-hevm
test: test-parse test-type test-invariant test-coq test-hevm test-cabal
6 changes: 4 additions & 2 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ let
hevm = dapptools.haskellPackages.hevm;
sbv = dapptools.haskellPackages.sbv;
act =
hself.callCabal2nixWithOptions
pkgs.haskell.lib.dontCheck (hself.callCabal2nixWithOptions
"act"
(gitignore ./src)
"-fci"
{};
{});
};
};

Expand All @@ -27,6 +27,8 @@ let
buildInputs = with pkgs.haskellPackages; [
cabal-install
pkgs.jq
pkgs.z3
pkgs.cvc4
pkgs.coq_8_10
dapptools.solc
];
Expand Down
33 changes: 17 additions & 16 deletions src/Enrich.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import EVM.ABI (AbiType(..))
import EVM.Solidity (SlotType(..))

import RefinedAst
import Type (bound, defaultStore, metaType)
import Type (bound, defaultStore)
import Syntax (EthEnv(..), Id, Decl(..), Interface(..))
import Extract

Expand All @@ -21,41 +21,42 @@ enrich claims = [S store]
<> (C <$> (enrichConstructor store <$> constructors))
<> (B <$> (enrichBehaviour store <$> behaviours))
where
store = head $ [s | S s <- claims]
store = head [s | S s <- claims]
behaviours = [b | B b <- claims]
invariants = [i | I i <- claims]
constructors = [c | C c <- claims]
definition (Invariant c _ _) = head $ filter (\b -> Pass == _cmode b && _cname b == c) [c' | C c' <- claims]
definition (Invariant c _ _ _) = head [c' | c' <- constructors, _cmode c' == Pass, _cname c' == c]

-- |Adds type bounds for calldata , environment vars, and external storage vars as preconditions
enrichConstructor :: Store -> Constructor -> Constructor
enrichConstructor store ctor@(Constructor _ _ (Interface _ decls) pre _ _ storageUpdates) =
ctor { _cpreconditions = pre' }
where
pre' = pre
<> (mkCallDataBounds decls)
<> (mkStorageBounds store storageUpdates)
<> (mkEthEnvBounds $ ethEnvFromConstructor ctor)
<> mkCallDataBounds decls
<> mkStorageBounds store storageUpdates
<> mkEthEnvBounds (ethEnvFromConstructor ctor)

-- | Adds type bounds for calldata, environment vars, and storage vars as preconditions
enrichBehaviour :: Store -> Behaviour -> Behaviour
enrichBehaviour store behv@(Behaviour _ _ _ (Interface _ decls) pre _ stateUpdates _) =
behv { _preconditions = pre' }
where
pre' = pre
<> (mkCallDataBounds decls)
<> (mkStorageBounds store stateUpdates)
<> (mkEthEnvBounds $ ethEnvFromBehaviour behv)
<> mkCallDataBounds decls
<> mkStorageBounds store stateUpdates
<> mkEthEnvBounds (ethEnvFromBehaviour behv)

-- | Adds type bounds for calldata, environment vars, and storage vars as preconditions
-- | Adds type bounds for calldata, environment vars, and storage vars
enrichInvariant :: Store -> Constructor -> Invariant -> Invariant
enrichInvariant store (Constructor _ _ (Interface _ decls) _ _ _ _) inv@(Invariant _ conds predicate) =
inv { _ipreconditions = conds' }
enrichInvariant store (Constructor _ _ (Interface _ decls) _ _ _ _) inv@(Invariant _ preconds storagebounds predicate) =
inv { _ipreconditions = preconds', _istoragebounds = storagebounds' }
where
conds' = conds
<> (mkCallDataBounds decls)
<> (mkStorageBounds store (Left <$> locsFromExp predicate))
<> (mkEthEnvBounds $ ethEnvFromExp predicate)
preconds' = preconds
<> mkCallDataBounds decls
<> mkEthEnvBounds (ethEnvFromExp predicate)
storagebounds' = storagebounds
<> mkStorageBounds store (Left <$> locsFromExp predicate)

mkEthEnvBounds :: [EthEnv] -> [Exp Bool]
mkEthEnvBounds vars = catMaybes $ mkBound <$> nub vars
Expand Down
18 changes: 16 additions & 2 deletions src/Extract.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import qualified Data.List.NonEmpty as NonEmpty

import RefinedAst
import Syntax
import EVM.ABI (AbiType(..))

locsFromReturnExp :: ReturnExp -> [StorageLocation]
locsFromReturnExp (ExpInt e) = locsFromExp e
Expand Down Expand Up @@ -43,10 +44,10 @@ locsFromExp e = case e of
IntVar _ -> []
LitBool _ -> []
BoolVar _ -> []
NewAddr _ _ -> error "TODO: handle new addr in SMT expressions"
NewAddr a b -> locsFromExp a <> locsFromExp b
IntEnv _ -> []
ByEnv _ -> []
ITE x y z -> (locsFromExp x) <> (locsFromExp y) <> (locsFromExp z)
ITE x y z -> locsFromExp x <> locsFromExp y <> locsFromExp z
TEntry a -> case a of
DirectInt contract name -> [IntLoc $ DirectInt contract name]
DirectBool contract slot -> [BoolLoc $ DirectBool contract slot]
Expand Down Expand Up @@ -138,6 +139,19 @@ mkLoc (IntUpdate item _) = IntLoc item
mkLoc (BoolUpdate item _) = BoolLoc item
mkLoc (BytesUpdate item _) = BytesLoc item

metaType :: AbiType -> MType
metaType (AbiUIntType _) = Integer
metaType (AbiIntType _) = Integer
metaType AbiAddressType = Integer
metaType AbiBoolType = Boolean
metaType (AbiBytesType _) = ByteStr
metaType AbiBytesDynamicType = ByteStr
metaType AbiStringType = ByteStr
--metaType (AbiArrayDynamicType a) =
--metaType (AbiArrayType Int AbiType
--metaType (AbiTupleType (Vector AbiType)
metaType _ = error "Extract.metaType: TODO"

nameFromStorage :: Syntax.Storage -> Id
nameFromStorage (Rewrite (Entry _ name _) _) = name
nameFromStorage (Constant (Entry _ name _)) = name
Expand Down
214 changes: 209 additions & 5 deletions src/HEVM.hs
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
{-# Language RecordWildCards #-}
{-# Language TypeApplications #-}
{-# Language OverloadedStrings #-}
{-# Language ScopedTypeVariables #-}
{-# Language DataKinds #-}
{-# Language GADTs #-}

module HEVM where

import Prelude hiding (lookup)
import Syntax
import Syntax hiding (Post)
import RefinedAst hiding (S)
import Extract

import Data.ByteString (ByteString)
import Data.ByteString.UTF8 (toString)
import Data.Text (Text, pack, splitOn)
import Data.Maybe
import Data.Either
import Data.List hiding (lookup)
import Data.Map hiding (drop, null, findIndex, splitAt, foldl, filter)
import qualified Data.List.NonEmpty as NonEmpty (toList)
import Data.Map hiding (drop, null, findIndex, splitAt, foldl, foldr, filter)
import qualified Data.Map as Map
import Control.Monad.State.Strict (execState)
import Data.SBV.Control
import Data.SBV
import Control.Lens hiding (pre)
import Data.SBV.String ((.++), subStr)
import Control.Lens hiding (pre, (.>))
import Control.Monad
import qualified Data.Vector as Vec
import Data.Type.Equality
import Data.Typeable

import Prove
import Type
import Print

import EVM hiding (Query)
import EVM.VMTest
Expand Down Expand Up @@ -283,3 +289,201 @@ keccak' (SymbolicBuffer bytes) = case maybeLitBytes bytes of
Nothing -> symkeccak' bytes
Just bs -> keccak' (ConcreteBuffer bs)
keccak' (ConcreteBuffer bytes) = literal $ toSizzle $ wordValue $ keccakBlob bytes

--- Symbolic Expression Generation ---

data Ctx = Ctx ContractName Method Args HEVM.Storage HEVM.Env
deriving (Show)

data SMType
= SymInteger (SBV Integer)
| SymBool (SBV Bool)
| SymBytes (SBV String)
deriving (Show)

type ContractName = Id
type Method = Id
type Args = Map Id SMType
type Storage = Map Id (SMType, SMType)
type Env = Map Id SMType
data When = Pre | Post

symExp :: Ctx -> When -> ReturnExp -> SMType
symExp ctx whn ret = case ret of
ExpInt e -> SymInteger $ symExpInt ctx whn e
ExpBool e -> SymBool $ symExpBool ctx whn e
ExpBytes e -> SymBytes $ symExpBytes ctx whn e

symExpBool :: Ctx -> When -> Exp Bool -> SBV Bool
symExpBool ctx@(Ctx c m args store _) w e = case e of
And a b -> symExpBool ctx w a .&& symExpBool ctx w b
Or a b -> symExpBool ctx w a .|| symExpBool ctx w b
Impl a b -> symExpBool ctx w a .=> symExpBool ctx w b
LE a b -> symExpInt ctx w a .< symExpInt ctx w b
LEQ a b -> symExpInt ctx w a .<= symExpInt ctx w b
GE a b -> symExpInt ctx w a .> symExpInt ctx w b
GEQ a b -> symExpInt ctx w a .>= symExpInt ctx w b
NEq a b -> sNot (symExpBool ctx w (Eq a b))
Neg a -> sNot (symExpBool ctx w a)
LitBool a -> literal a
BoolVar a -> get (nameFromArg c m a) (catBools args)
TEntry a -> get (nameFromItem m a) (catBools store')
ITE x y z -> ite (symExpBool ctx w x) (symExpBool ctx w y) (symExpBool ctx w z)
Eq (a :: Exp t) (b :: Exp t) -> case eqT @t @Integer of
Just Refl -> symExpInt ctx w a .== symExpInt ctx w b
Nothing -> case eqT @t @Bool of
Just Refl -> symExpBool ctx w a .== symExpBool ctx w b
Nothing -> case eqT @t @ByteString of
Just Refl -> symExpBytes ctx w a .== symExpBytes ctx w b
Nothing -> error "Internal Error: invalid expression type"
where store' = case w of
Pre -> fst <$> store
Post -> snd <$> store

symExpInt :: Ctx -> When -> Exp Integer -> SBV Integer
symExpInt ctx@(Ctx c m args store environment) w e = case e of
Add a b -> symExpInt ctx w a + symExpInt ctx w b
Sub a b -> symExpInt ctx w a - symExpInt ctx w b
Mul a b -> symExpInt ctx w a * symExpInt ctx w b
Div a b -> symExpInt ctx w a `sDiv` symExpInt ctx w b
Mod a b -> symExpInt ctx w a `sMod` symExpInt ctx w b
Exp a b -> symExpInt ctx w a .^ symExpInt ctx w b
LitInt a -> literal a
IntMin a -> literal $ intmin a
IntMax a -> literal $ intmax a
UIntMin a -> literal $ uintmin a
UIntMax a -> literal $ uintmax a
IntVar a -> get (nameFromArg c m a) (catInts args)
TEntry a -> get (nameFromItem m a) (catInts store')
IntEnv a -> get (nameFromEnv c m a) (catInts environment)
NewAddr _ _ -> error "TODO: handle new addr in SMT expressions"
ITE x y z -> ite (symExpBool ctx w x) (symExpInt ctx w y) (symExpInt ctx w z)
where store' = case w of
Pre -> fst <$> store
Post -> snd <$> store

symExpBytes :: Ctx -> When -> Exp ByteString -> SBV String
symExpBytes ctx@(Ctx c m args store environment) w e = case e of
Cat a b -> symExpBytes ctx w a .++ symExpBytes ctx w b
ByVar a -> get (nameFromArg c m a) (catBytes args)
ByStr a -> literal a
ByLit a -> literal $ toString a
TEntry a -> get (nameFromItem m a) (catBytes store')
Slice a x y -> subStr (symExpBytes ctx w a) (symExpInt ctx w x) (symExpInt ctx w y)
ByEnv a -> get (nameFromEnv c m a) (catBytes environment)
ITE x y z -> ite (symExpBool ctx w x) (symExpBytes ctx w y) (symExpBytes ctx w z)
where store' = case w of
Pre -> fst <$> store
Post -> snd <$> store


-- *** SMT Variable Names *** --


nameFromItem :: Method -> TStorageItem a -> Id
nameFromItem method item = case item of
DirectInt c name -> c @@ method @@ name
DirectBool c name -> c @@ method @@ name
DirectBytes c name -> c @@ method @@ name
MappedInt c name ixs -> c @@ method @@ name >< showIxs c ixs
MappedBool c name ixs -> c @@ method @@ name >< showIxs c ixs
MappedBytes c name ixs -> c @@ method @@ name >< showIxs c ixs
where
x >< y = x <> "-" <> y
showIxs c ixs = intercalate "-" (NonEmpty.toList $ nameFromExp c method <$> ixs)

nameFromExp :: ContractName -> Method -> ReturnExp -> Id
nameFromExp c method e = case e of
ExpInt e' -> nameFromExpInt c method e'
ExpBool e' -> nameFromExpBool c method e'
ExpBytes e' -> nameFromExpBytes c method e'

nameFromExpInt :: ContractName -> Method -> Exp Integer -> Id
nameFromExpInt c m e = case e of
Add a b -> nameFromExpInt c m a <> "+" <> nameFromExpInt c m b
Sub a b -> nameFromExpInt c m a <> "-" <> nameFromExpInt c m b
Mul a b -> nameFromExpInt c m a <> "*" <> nameFromExpInt c m b
Div a b -> nameFromExpInt c m a <> "/" <> nameFromExpInt c m b
Mod a b -> nameFromExpInt c m a <> "%" <> nameFromExpInt c m b
Exp a b -> nameFromExpInt c m a <> "^" <> nameFromExpInt c m b
LitInt a -> show a
IntMin a -> show $ intmin a
IntMax a -> show $ intmax a
UIntMin a -> show $ uintmin a
UIntMax a -> show $ uintmax a
IntVar a -> a
TEntry a -> nameFromItem m a
IntEnv a -> nameFromEnv c m a
NewAddr _ _ -> error "TODO: handle new addr in SMT expressions"
ITE x y z -> "if-" <> nameFromExpBool c m x <> "-then-" <> nameFromExpInt c m y <> "-else-" <> nameFromExpInt c m z

nameFromExpBool :: ContractName -> Method -> Exp Bool -> Id
nameFromExpBool c m e = case e of
And a b -> nameFromExpBool c m a <> "&&" <> nameFromExpBool c m b
Or a b -> nameFromExpBool c m a <> "|" <> nameFromExpBool c m b
Impl a b -> nameFromExpBool c m a <> "=>" <> nameFromExpBool c m b
LE a b -> nameFromExpInt c m a <> "<" <> nameFromExpInt c m b
LEQ a b -> nameFromExpInt c m a <> "<=" <> nameFromExpInt c m b
GE a b -> nameFromExpInt c m a <> ">" <> nameFromExpInt c m b
GEQ a b -> nameFromExpInt c m a <> ">=" <> nameFromExpInt c m b
Neg a -> "~" <> nameFromExpBool c m a
LitBool a -> show a
BoolVar a -> nameFromArg c m a
TEntry a -> nameFromItem m a
ITE x y z -> "if-" <> nameFromExpBool c m x <> "-then-" <> nameFromExpBool c m y <> "-else-" <> nameFromExpBool c m z
Eq (a :: Exp t) (b :: Exp t) -> case eqT @t @Integer of
Just Refl -> nameFromExpInt c m a <> "==" <> nameFromExpInt c m b
Nothing -> case eqT @t @Bool of
Just Refl -> nameFromExpBool c m a <> "==" <> nameFromExpBool c m b
Nothing -> case eqT @t @ByteString of
Just Refl -> nameFromExpBytes c m a <> "==" <> nameFromExpBytes c m b
Nothing -> error "Internal Error: invalid expression type"
NEq (a :: Exp t) (b :: Exp t) -> case eqT @t @Integer of
Just Refl -> nameFromExpInt c m a <> "=/=" <> nameFromExpInt c m b
Nothing -> case eqT @t @Bool of
Just Refl -> nameFromExpBool c m a <> "=/=" <> nameFromExpBool c m b
Nothing -> case eqT @t @ByteString of
Just Refl -> nameFromExpBytes c m a <> "=/=" <> nameFromExpBytes c m b
Nothing -> error "Internal Error: invalid expression type"

nameFromExpBytes :: ContractName -> Method -> Exp ByteString -> Id
nameFromExpBytes c m e = case e of
Cat a b -> nameFromExpBytes c m a <> "++" <> nameFromExpBytes c m b
ByVar a -> nameFromArg c m a
ByStr a -> show a
ByLit a -> show a
TEntry a -> nameFromItem m a
Slice a x y -> nameFromExpBytes c m a <> "[" <> show x <> ":" <> show y <> "]"
ByEnv a -> nameFromEnv c m a
ITE x y z -> "if-" <> nameFromExpBool c m x <> "-then-" <> nameFromExpBytes c m y <> "-else-" <> nameFromExpBytes c m z

nameFromDecl :: ContractName -> Method -> Decl -> Id
nameFromDecl c m (Decl _ name) = nameFromArg c m name

nameFromArg :: ContractName -> Method -> Id -> Id
nameFromArg c method name = c @@ method @@ name

nameFromEnv :: ContractName -> Method -> EthEnv -> Id
nameFromEnv c method e = c @@ method @@ (prettyEnv e)

(@@) :: Id -> Id -> Id
x @@ y = x <> "_" <> y


-- *** Utils *** --


get :: (Show a, Ord a, Show b) => a -> Map a b -> b
get name vars = fromMaybe (error (show name <> " not found in " <> show vars)) $ Map.lookup name vars

catInts :: Map Id SMType -> Map Id (SBV Integer)
catInts m = Map.fromList [(name, i) | (name, SymInteger i) <- Map.toList m]

catBools :: Map Id SMType -> Map Id (SBV Bool)
catBools m = Map.fromList [(name, i) | (name, SymBool i) <- Map.toList m]

catBytes :: Map Id SMType -> Map Id (SBV String)
catBytes m = Map.fromList [(name, i) | (name, SymBytes i) <- Map.toList m]

concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
concatMapM f xs = liftM concat (mapM f xs)
Loading