grisette-0.4.0.0: src/Grisette/IR/SymPrim/Data/SymPrim.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- |
-- Module : Grisette.IR.SymPrim.Data.SymPrim
-- Copyright : (c) Sirui Lu 2021-2023
-- License : BSD-3-Clause (see the LICENSE file)
--
-- Maintainer : siruilu@cs.washington.edu
-- Stability : Experimental
-- Portability : GHC only
module Grisette.IR.SymPrim.Data.SymPrim
( SymBool (..),
SymInteger (..),
SymWordN (..),
SymIntN (..),
SomeSymWordN (..),
SomeSymIntN (..),
type (=~>) (..),
type (-~>) (..),
(-->),
ModelSymPair (..),
symSize,
symsSize,
SomeSym (..),
AllSyms (..),
allSymsSize,
unarySomeSymIntN,
unarySomeSymIntNR1,
binSomeSymIntN,
binSomeSymIntNR1,
binSomeSymIntNR2,
unarySomeSymWordN,
unarySomeSymWordNR1,
binSomeSymWordN,
binSomeSymWordNR1,
binSomeSymWordNR2,
)
where
import Control.DeepSeq (NFData (rnf))
import Control.Monad.Except (ExceptT (ExceptT))
import Control.Monad.Identity
( Identity (Identity),
IdentityT (IdentityT),
)
import Control.Monad.Trans.Maybe (MaybeT (MaybeT))
import qualified Control.Monad.Writer.Lazy as WriterLazy
import qualified Control.Monad.Writer.Strict as WriterStrict
import Data.Bits
( Bits
( bit,
bitSize,
bitSizeMaybe,
clearBit,
complement,
complementBit,
isSigned,
popCount,
rotate,
rotateL,
rotateR,
setBit,
shift,
shiftL,
shiftR,
testBit,
unsafeShiftL,
unsafeShiftR,
xor,
zeroBits,
(.&.),
(.|.)
),
FiniteBits (finiteBitSize),
)
import qualified Data.ByteString as B
import Data.Functor.Sum (Sum)
import Data.Hashable (Hashable (hashWithSalt))
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Proxy (Proxy (Proxy))
import Data.String (IsString (fromString))
import qualified Data.Text as T
import Data.Typeable (typeRep, type (:~:) (Refl))
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.Generics
( Generic (Rep, from),
K1 (K1),
M1 (M1),
U1,
type (:*:) ((:*:)),
type (:+:) (L1, R1),
)
import GHC.TypeNats
( KnownNat,
Nat,
natVal,
sameNat,
type (+),
type (<=),
)
import Generics.Deriving (Default (Default, unDefault))
import Grisette.Core.Control.Exception
( AssertionError,
VerificationConditions,
)
import Grisette.Core.Data.BV
( IntN,
WordN,
)
import Grisette.Core.Data.Class.BitVector
( BV (bvConcat, bvExt, bvSelect, bvSext, bvZext),
SizedBV (sizedBVConcat, sizedBVExt, sizedBVSelect, sizedBVSext, sizedBVZext),
)
import Grisette.Core.Data.Class.Function (Apply (FunType, apply), Function (Arg, Ret, (#)))
import Grisette.Core.Data.Class.ModelOps
( ModelOps (emptyModel, insertValue),
ModelRep (buildModel),
)
import Grisette.Core.Data.Class.SignConversion (SignConversion (toSigned, toUnsigned))
import Grisette.Core.Data.Class.Solvable
( Solvable (con, conView, iinfosym, isym, sinfosym, ssym),
pattern Con,
)
import Grisette.Core.Data.Class.SymRotate (SymRotate (symRotate))
import Grisette.Core.Data.Class.SymShift (SymShift (symShift))
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.InternedCtors (conTerm, iinfosymTerm, isymTerm, sinfosymTerm, ssymTerm, symTerm)
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.SomeTerm
( SomeTerm (SomeTerm),
)
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
( ConRep (ConType),
LinkedRep (underlyingTerm, wrapTerm),
SupportedPrim,
SymRep (SymType),
Term (ConTerm, SymTerm),
TypedSymbol (WithInfo),
type (-->) (GeneralFun),
)
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermSubstitution
( substTerm,
)
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermUtils
( pformat,
someTermsSize,
termSize,
termsSize,
)
import Grisette.IR.SymPrim.Data.Prim.Model
( Model,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.BV
( pevalBVConcatTerm,
pevalBVExtendTerm,
pevalBVSelectTerm,
pevalToSignedTerm,
pevalToUnsignedTerm,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.Bits
( pevalAndBitsTerm,
pevalComplementBitsTerm,
pevalOrBitsTerm,
pevalRotateLeftTerm,
pevalRotateRightTerm,
pevalShiftLeftTerm,
pevalShiftRightTerm,
pevalXorBitsTerm,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.Bool
( pevalEqvTerm,
pevalITETerm,
pevalOrTerm,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.GeneralFun
( pevalGeneralFunApplyTerm,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.Integral (pevalModBoundedIntegralTerm)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.Num
( pevalAbsNumTerm,
pevalAddNumTerm,
pevalGeNumTerm,
pevalLeNumTerm,
pevalMinusNumTerm,
pevalSignumNumTerm,
pevalTimesNumTerm,
pevalUMinusNumTerm,
)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.TabularFun
( pevalTabularFunApplyTerm,
)
import Grisette.IR.SymPrim.Data.TabularFun (type (=->))
import Grisette.Utils.Parameterized
( KnownProof (KnownProof),
LeqProof (LeqProof),
knownAdd,
leqAddPos,
leqTrans,
unsafeKnownProof,
unsafeLeqProof,
)
import Language.Haskell.TH.Syntax (Lift)
-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.IR.SymPrim
-- >>> import Grisette.Backend.SBV
-- >>> import Data.Proxy
-- | Symbolic Boolean type.
--
-- >>> :set -XOverloadedStrings
-- >>> "a" :: SymBool
-- a
-- >>> "a" .&& "b" :: SymBool
-- (&& a b)
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
newtype SymBool = SymBool {underlyingBoolTerm :: Term Bool}
deriving (Lift, NFData, Generic)
-- | Symbolic (unbounded, mathematical) integer type.
--
-- >>> "a" + 1 :: SymInteger
-- (+ 1 a)
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
newtype SymInteger = SymInteger {underlyingIntegerTerm :: Term Integer}
deriving (Lift, NFData, Generic)
#define QUOTE() '
#define QID(a) a
#define QRIGHT(a) QID(a)'
-- | Symbolic signed bit vector type. Indexed with the bit width.
-- Signedness affects the semantics of the operations, including
-- comparison/extension, etc.
--
-- >>> :set -XOverloadedStrings -XDataKinds -XBinaryLiterals
-- >>> "a" + 5 :: SymIntN 5
-- (+ 0b00101 a)
-- >>> sizedBVConcat (con 0b101 :: SymIntN 3) (con 0b110 :: SymIntN 3)
-- 0b101110
-- >>> sizedBVExt (Proxy @6) (con 0b101 :: SymIntN 3)
-- 0b111101
-- >>> (8 :: SymIntN 4) .< (7 :: SymIntN 4)
-- true
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
newtype SymIntN (n :: Nat) = SymIntN {underlyingIntNTerm :: Term (IntN n)}
deriving (Lift, NFData, Generic)
-- | Symbolic signed bit vector type. Not indexed, but the bit width is
-- fixed at the creation time.
--
-- A 'SomeSymIntN' must be created by wrapping a 'SymIntN' with the
-- 'SomeSymIntN' constructor to fix the bit width:
--
-- >>> (SomeSymIntN ("a" :: SymIntN 5))
-- a
--
-- >>> :set -XOverloadedStrings -XDataKinds -XBinaryLiterals
-- >>> (SomeSymIntN ("a" :: SymIntN 5)) + (SomeSymIntN (5 :: SymIntN 5))
-- (+ 0b00101 a)
-- >>> bvConcat (SomeSymIntN (con 0b101 :: SymIntN 3)) (SomeSymIntN (con 0b110 :: SymIntN 3))
-- 0b101110
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
data SomeSymIntN where
SomeSymIntN :: (KnownNat n, 1 <= n) => SymIntN n -> SomeSymIntN
unarySomeSymIntN :: (forall n. (KnownNat n, 1 <= n) => SymIntN n -> r) -> String -> SomeSymIntN -> r
unarySomeSymIntN op _ (SomeSymIntN (w :: SymIntN w)) = op w
{-# INLINE unarySomeSymIntN #-}
unarySomeSymIntNR1 :: (forall n. (KnownNat n, 1 <= n) => SymIntN n -> SymIntN n) -> String -> SomeSymIntN -> SomeSymIntN
unarySomeSymIntNR1 op _ (SomeSymIntN (w :: SymIntN w)) = SomeSymIntN $ op w
{-# INLINE unarySomeSymIntNR1 #-}
binSomeSymIntN :: (forall n. (KnownNat n, 1 <= n) => SymIntN n -> SymIntN n -> r) -> String -> SomeSymIntN -> SomeSymIntN -> r
binSomeSymIntN op str (SomeSymIntN (l :: SymIntN l)) (SomeSymIntN (r :: SymIntN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl -> op l r
Nothing -> error $ "Operation " ++ str ++ " on SymIntN with different bitwidth"
{-# INLINE binSomeSymIntN #-}
binSomeSymIntNR1 :: (forall n. (KnownNat n, 1 <= n) => SymIntN n -> SymIntN n -> SymIntN n) -> String -> SomeSymIntN -> SomeSymIntN -> SomeSymIntN
binSomeSymIntNR1 op str (SomeSymIntN (l :: SymIntN l)) (SomeSymIntN (r :: SymIntN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl -> SomeSymIntN $ op l r
Nothing -> error $ "Operation " ++ str ++ " on SymIntN with different bitwidth"
{-# INLINE binSomeSymIntNR1 #-}
binSomeSymIntNR2 :: (forall n. (KnownNat n, 1 <= n) => SymIntN n -> SymIntN n -> (SymIntN n, SymIntN n)) -> String -> SomeSymIntN -> SomeSymIntN -> (SomeSymIntN, SomeSymIntN)
binSomeSymIntNR2 op str (SomeSymIntN (l :: SymIntN l)) (SomeSymIntN (r :: SymIntN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl ->
case op l r of
(a, b) -> (SomeSymIntN a, SomeSymIntN b)
Nothing -> error $ "Operation " ++ str ++ " on SymIntN with different bitwidth"
{-# INLINE binSomeSymIntNR2 #-}
-- | Symbolic unsigned bit vector type. Indexed with the bit width.
-- Signedness affects the semantics of the operations, including
-- comparison/extension, etc.
--
-- >>> :set -XOverloadedStrings -XDataKinds -XBinaryLiterals
-- >>> "a" + 5 :: SymWordN 5
-- (+ 0b00101 a)
-- >>> sizedBVConcat (con 0b101 :: SymWordN 3) (con 0b110 :: SymWordN 3)
-- 0b101110
-- >>> sizedBVExt (Proxy @6) (con 0b101 :: SymWordN 3)
-- 0b000101
-- >>> (8 :: SymWordN 4) .< (7 :: SymWordN 4)
-- false
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
newtype SymWordN (n :: Nat) = SymWordN {underlyingWordNTerm :: Term (WordN n)}
deriving (Lift, NFData, Generic)
-- | Symbolic unsigned bit vector type. Not indexed, but the bit width is
-- fixed at the creation time.
--
-- A 'SomeSymWordN' must be created by wrapping a 'SymWordN' with the
-- 'SomeSymWordN' constructor to fix the bit width:
--
-- >>> (SomeSymWordN ("a" :: SymWordN 5))
-- a
--
-- >>> :set -XOverloadedStrings -XDataKinds -XBinaryLiterals
-- >>> (SomeSymWordN ("a" :: SymWordN 5)) + (SomeSymWordN (5 :: SymWordN 5))
-- (+ 0b00101 a)
-- >>> bvConcat (SomeSymWordN (con 0b101 :: SymWordN 3)) (SomeSymWordN (con 0b110 :: SymWordN 3))
-- 0b101110
--
-- More symbolic operations are available. Please refer to the documentation
-- for the type class instances.
data SomeSymWordN where
SomeSymWordN :: (KnownNat n, 1 <= n) => SymWordN n -> SomeSymWordN
unarySomeSymWordN :: (forall n. (KnownNat n, 1 <= n) => SymWordN n -> r) -> String -> SomeSymWordN -> r
unarySomeSymWordN op _ (SomeSymWordN (w :: SymWordN w)) = op w
{-# INLINE unarySomeSymWordN #-}
unarySomeSymWordNR1 :: (forall n. (KnownNat n, 1 <= n) => SymWordN n -> SymWordN n) -> String -> SomeSymWordN -> SomeSymWordN
unarySomeSymWordNR1 op _ (SomeSymWordN (w :: SymWordN w)) = SomeSymWordN $ op w
{-# INLINE unarySomeSymWordNR1 #-}
binSomeSymWordN :: (forall n. (KnownNat n, 1 <= n) => SymWordN n -> SymWordN n -> r) -> String -> SomeSymWordN -> SomeSymWordN -> r
binSomeSymWordN op str (SomeSymWordN (l :: SymWordN l)) (SomeSymWordN (r :: SymWordN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl -> op l r
Nothing -> error $ "Operation " ++ str ++ " on SymWordN with different bitwidth"
{-# INLINE binSomeSymWordN #-}
binSomeSymWordNR1 :: (forall n. (KnownNat n, 1 <= n) => SymWordN n -> SymWordN n -> SymWordN n) -> String -> SomeSymWordN -> SomeSymWordN -> SomeSymWordN
binSomeSymWordNR1 op str (SomeSymWordN (l :: SymWordN l)) (SomeSymWordN (r :: SymWordN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl -> SomeSymWordN $ op l r
Nothing -> error $ "Operation " ++ str ++ " on SymWordN with different bitwidth"
{-# INLINE binSomeSymWordNR1 #-}
binSomeSymWordNR2 :: (forall n. (KnownNat n, 1 <= n) => SymWordN n -> SymWordN n -> (SymWordN n, SymWordN n)) -> String -> SomeSymWordN -> SomeSymWordN -> (SomeSymWordN, SomeSymWordN)
binSomeSymWordNR2 op str (SomeSymWordN (l :: SymWordN l)) (SomeSymWordN (r :: SymWordN r)) =
case sameNat (Proxy @l) (Proxy @r) of
Just Refl ->
case op l r of
(a, b) -> (SomeSymWordN a, SomeSymWordN b)
Nothing -> error $ "Operation " ++ str ++ " on SymWordN with different bitwidth"
{-# INLINE binSomeSymWordNR2 #-}
instance ConRep SymBool where
type ConType SymBool = Bool
instance SymRep Bool where
type SymType Bool = SymBool
instance LinkedRep Bool SymBool where
underlyingTerm (SymBool a) = a
wrapTerm = SymBool
instance ConRep SymInteger where
type ConType SymInteger = Integer
instance SymRep Integer where
type SymType Integer = SymInteger
instance LinkedRep Integer SymInteger where
underlyingTerm (SymInteger a) = a
wrapTerm = SymInteger
instance (KnownNat n, 1 <= n) => ConRep (SymIntN n) where
type ConType (SymIntN n) = IntN n
instance (KnownNat n, 1 <= n) => SymRep (IntN n) where
type SymType (IntN n) = SymIntN n
instance (KnownNat n, 1 <= n) => LinkedRep (IntN n) (SymIntN n) where
underlyingTerm (SymIntN a) = a
wrapTerm = SymIntN
instance (KnownNat n, 1 <= n) => ConRep (SymWordN n) where
type ConType (SymWordN n) = WordN n
instance (KnownNat n, 1 <= n) => SymRep (WordN n) where
type SymType (WordN n) = SymWordN n
instance (KnownNat n, 1 <= n) => LinkedRep (WordN n) (SymWordN n) where
underlyingTerm (SymWordN a) = a
wrapTerm = SymWordN
-- | Symbolic tabular function type.
--
-- >>> :set -XTypeOperators -XOverloadedStrings
-- >>> f' = "f" :: SymInteger =~> SymInteger
-- >>> f = (f' #)
-- >>> f 1
-- (apply f 1)
--
-- >>> f' = con (TabularFun [(1, 2), (2, 3)] 4) :: SymInteger =~> SymInteger
-- >>> f = (f' #)
-- >>> f 1
-- 2
-- >>> f 2
-- 3
-- >>> f 3
-- 4
-- >>> f "b"
-- (ite (= b 1) 2 (ite (= b 2) 3 4))
data sa =~> sb where
SymTabularFun :: (LinkedRep ca sa, LinkedRep cb sb) => Term (ca =-> cb) -> sa =~> sb
infixr 0 =~>
instance (ConRep a, ConRep b) => ConRep (a =~> b) where
type ConType (a =~> b) = ConType a =-> ConType b
instance (SymRep a, SymRep b) => SymRep (a =-> b) where
type SymType (a =-> b) = SymType a =~> SymType b
instance (LinkedRep ca sa, LinkedRep cb sb) => LinkedRep (ca =-> cb) (sa =~> sb) where
underlyingTerm (SymTabularFun a) = a
wrapTerm = SymTabularFun
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => Function (sa =~> sb) where
type Arg (sa =~> sb) = sa
type Ret (sa =~> sb) = sb
(SymTabularFun f) # t = wrapTerm $ pevalTabularFunApplyTerm f (underlyingTerm t)
instance (LinkedRep ca sa, LinkedRep ct st, Apply st) => Apply (sa =~> st) where
type FunType (sa =~> st) = sa -> FunType st
apply uf a = apply (uf # a)
-- |
-- Symbolic general function type.
--
-- >>> :set -XTypeOperators -XOverloadedStrings
-- >>> f' = "f" :: SymInteger -~> SymInteger
-- >>> f = (f' #)
-- >>> f 1
-- (apply f 1)
--
-- >>> f' = con ("a" --> "a" + 1) :: SymInteger -~> SymInteger
-- >>> f'
-- \(a:ARG :: Integer) -> (+ 1 a:ARG)
-- >>> f = (f' #)
-- >>> f 1
-- 2
-- >>> f 2
-- 3
-- >>> f 3
-- 4
-- >>> f "b"
-- (+ 1 b)
data sa -~> sb where
SymGeneralFun :: (LinkedRep ca sa, LinkedRep cb sb) => Term (ca --> cb) -> sa -~> sb
infixr 0 -~>
instance (ConRep a, ConRep b) => ConRep (a -~> b) where
type ConType (a -~> b) = ConType a --> ConType b
instance (SymRep ca, SymRep cb) => SymRep (ca --> cb) where
type SymType (ca --> cb) = SymType ca -~> SymType cb
instance (LinkedRep ca sa, LinkedRep cb sb) => LinkedRep (ca --> cb) (sa -~> sb) where
underlyingTerm (SymGeneralFun a) = a
wrapTerm = SymGeneralFun
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => Function (sa -~> sb) where
type Arg (sa -~> sb) = sa
type Ret (sa -~> sb) = sb
(SymGeneralFun f) # t = wrapTerm $ pevalGeneralFunApplyTerm f (underlyingTerm t)
instance (LinkedRep ca sa, LinkedRep ct st, Apply st) => Apply (sa -~> st) where
type FunType (sa -~> st) = sa -> FunType st
apply uf a = apply (uf # a)
-- | Construction of general symbolic functions.
--
-- >>> f = "a" --> "a" + 1 :: Integer --> Integer
-- >>> f
-- \(a:ARG :: Integer) -> (+ 1 a:ARG)
--
-- This general symbolic function needs to be applied to symbolic values:
-- >>> f # ("a" :: SymInteger)
-- (+ 1 a)
(-->) :: (SupportedPrim ca, SupportedPrim cb, LinkedRep cb sb) => TypedSymbol ca -> sb -> ca --> cb
(-->) arg v = GeneralFun newarg (substTerm arg (symTerm newarg) (underlyingTerm v))
where
newarg = WithInfo arg ARG
infixr 0 -->
data ARG = ARG
deriving (Eq, Ord, Lift, Show, Generic)
instance NFData ARG where
rnf ARG = ()
instance Hashable ARG where
hashWithSalt s ARG = s `hashWithSalt` (0 :: Int)
-- Aggregate instances
instance Apply SymBool where
type FunType SymBool = SymBool
apply = id
instance Apply SymInteger where
type FunType SymInteger = SymInteger
apply = id
instance (KnownNat n, 1 <= n) => Apply (SymIntN n) where
type FunType (SymIntN n) = SymIntN n
apply = id
instance (KnownNat n, 1 <= n) => Apply (SymWordN n) where
type FunType (SymWordN n) = SymWordN n
apply = id
#define SOLVABLE_SIMPLE(contype, symtype) \
instance Solvable contype symtype where \
con = symtype . conTerm; \
ssym = symtype . ssymTerm; \
isym str i = symtype $ isymTerm str i; \
sinfosym str info = symtype $ sinfosymTerm str info; \
iinfosym str i info = symtype $ iinfosymTerm str i info; \
conView (symtype (ConTerm _ t)) = Just t; \
conView _ = Nothing
#define SOLVABLE_BV(contype, symtype) \
instance (KnownNat n, 1 <= n) => Solvable (contype n) (symtype n) where \
con = symtype . conTerm; \
ssym = symtype . ssymTerm; \
isym str i = symtype $ isymTerm str i; \
sinfosym str info = symtype $ sinfosymTerm str info; \
iinfosym str i info = symtype $ iinfosymTerm str i info; \
conView (symtype (ConTerm _ t)) = Just t; \
conView _ = Nothing
#define SOLVABLE_FUN(symop, conop, symcons) \
instance \
(SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => \
Solvable (conop ca cb) (symop sa sb) where \
con = symcons . conTerm; \
ssym = symcons . ssymTerm; \
isym str i = symcons $ isymTerm str i; \
sinfosym str info = symcons $ sinfosymTerm str info; \
iinfosym str i info = symcons $ iinfosymTerm str i info; \
conView (symcons (ConTerm _ t)) = Just t; \
conView _ = Nothing
#if 1
SOLVABLE_SIMPLE(Bool, SymBool)
SOLVABLE_SIMPLE(Integer, SymInteger)
SOLVABLE_BV(IntN, SymIntN)
SOLVABLE_BV(WordN, SymWordN)
SOLVABLE_FUN((=~>), (=->), SymTabularFun)
SOLVABLE_FUN((-~>), (-->), SymGeneralFun)
#endif
-- Num
#define NUM_BV(symtype) \
instance (KnownNat n, 1 <= n) => Num (symtype n) where \
(symtype l) + (symtype r) = symtype $ pevalAddNumTerm l r; \
(symtype l) - (symtype r) = symtype $ pevalMinusNumTerm l r; \
(symtype l) * (symtype r) = symtype $ pevalTimesNumTerm l r; \
negate (symtype v) = symtype $ pevalUMinusNumTerm v; \
abs (symtype v) = symtype $ pevalAbsNumTerm v; \
signum (symtype v) = symtype $ pevalSignumNumTerm v; \
fromInteger i = con $ fromInteger i
#define NUM_SOME_BV(somety, br1, ur1) \
instance Num somety where \
(+) = br1 (+) "+"; \
{-# INLINE (+) #-}; \
(-) = br1 (-) "-"; \
{-# INLINE (-) #-}; \
(*) = br1 (*) "*"; \
{-# INLINE (*) #-}; \
negate = ur1 negate "negate"; \
{-# INLINE negate #-}; \
abs = ur1 abs "abs"; \
{-# INLINE abs #-}; \
signum = ur1 signum "signum"; \
{-# INLINE signum #-}; \
fromInteger = error "fromInteger is not defined for SomeSymWordN as no bitwidth is known"; \
{-# INLINE fromInteger #-}
#if 1
NUM_BV(SymIntN)
NUM_BV(SymWordN)
NUM_SOME_BV(SomeSymWordN, binSomeSymWordNR1, unarySomeSymWordNR1)
NUM_SOME_BV(SomeSymIntN, binSomeSymIntNR1, unarySomeSymIntNR1)
#endif
instance Num SymInteger where
(SymInteger l) + (SymInteger r) = SymInteger $ pevalAddNumTerm l r
(SymInteger l) - (SymInteger r) = SymInteger $ pevalMinusNumTerm l r
(SymInteger l) * (SymInteger r) = SymInteger $ pevalTimesNumTerm l r
negate (SymInteger v) = SymInteger $ pevalUMinusNumTerm v
abs (SymInteger v) = SymInteger $ pevalAbsNumTerm v
signum (SymInteger v) = SymInteger $ pevalSignumNumTerm v
fromInteger = con
-- Bits
#define BITS_BV(symtype, signed) \
instance (KnownNat n, 1 <= n) => Bits (symtype n) where \
symtype l .&. symtype r = symtype $ pevalAndBitsTerm l r; \
{-# INLINE (.&.) #-}; \
symtype l .|. symtype r = symtype $ pevalOrBitsTerm l r; \
{-# INLINE (.|.) #-}; \
symtype l `xor` symtype r = symtype $ pevalXorBitsTerm l r; \
{-# INLINE xor #-}; \
complement (symtype n) = symtype $ pevalComplementBitsTerm n; \
{-# INLINE complement #-}; \
shift (symtype n) i | i > 0 = symtype $ pevalShiftLeftTerm n (conTerm $ fromIntegral i); \
shift (symtype n) i | i < 0 = symtype $ pevalShiftRightTerm n (conTerm $ fromIntegral (-i)); \
shift (symtype n) _ = symtype n; \
{-# INLINE shift #-}; \
rotate (symtype n) i | i > 0 = symtype $ pevalRotateLeftTerm n (conTerm $ fromIntegral i); \
rotate (symtype n) i | i < 0 = symtype $ pevalRotateRightTerm n (conTerm $ fromIntegral (-i)); \
rotate (symtype n) _ = symtype n; \
{-# INLINE rotate #-}; \
bitSize = finiteBitSize; \
{-# INLINE bitSize #-}; \
bitSizeMaybe = Just . finiteBitSize; \
{-# INLINE bitSizeMaybe #-}; \
isSigned _ = signed; \
{-# INLINE isSigned #-}; \
testBit (Con n) = testBit n; \
testBit _ = error "You cannot call testBit on symbolic variables"; \
{-# INLINE testBit #-}; \
bit = con . bit; \
{-# INLINE bit #-}; \
popCount (Con n) = popCount n; \
popCount _ = error "You cannot call popCount on symbolic variables"; \
{-# INLINE popCount #-}
#define BITS_BV_SOME(somety, origty, br1, uf, ur1) \
instance Bits somety where \
(.&.) = br1 (.&.) ".&."; \
{-# INLINE (.&.) #-}; \
(.|.) = br1 (.|.) ".|."; \
{-# INLINE (.|.) #-}; \
xor = br1 xor "xor"; \
{-# INLINE xor #-}; \
complement = ur1 complement "complement"; \
{-# INLINE complement #-}; \
shift s i = ur1 (`shift` i) "shift" s; \
{-# INLINE shift #-}; \
rotate s i = ur1 (`rotate` i) "rotate" s; \
{-# INLINE rotate #-}; \
zeroBits = error ("zeroBits is not defined for " ++ show (typeRep (Proxy @somety)) ++ " as no bitwidth is known"); \
{-# INLINE zeroBits #-}; \
bit = error ("bit is not defined for " ++ show (typeRep (Proxy @somety)) ++ " as no bitwidth is known"); \
{-# INLINE bit #-}; \
setBit s i = ur1 (`setBit` i) "setBit" s; \
{-# INLINE setBit #-}; \
clearBit s i = ur1 (`clearBit` i) "clearBit" s; \
{-# INLINE clearBit #-}; \
complementBit s i = ur1 (`complementBit` i) "complementBit" s; \
{-# INLINE complementBit #-}; \
testBit s i = uf (`testBit` i) "testBit" s; \
{-# INLINE testBit #-}; \
bitSizeMaybe = Just . finiteBitSize; \
{-# INLINE bitSizeMaybe #-}; \
bitSize = finiteBitSize; \
{-# INLINE bitSize #-}; \
isSigned _ = False; \
{-# INLINE isSigned #-}; \
shiftL s i = ur1 (`shiftL` i) "shiftL" s; \
{-# INLINE shiftL #-}; \
unsafeShiftL s i = ur1 (`unsafeShiftL` i) "unsafeShiftL" s; \
{-# INLINE unsafeShiftL #-}; \
shiftR s i = ur1 (`shiftR` i) "shiftR" s; \
{-# INLINE shiftR #-}; \
unsafeShiftR s i = ur1 (`unsafeShiftR` i) "unsafeShiftR" s; \
{-# INLINE unsafeShiftR #-}; \
rotateL s i = ur1 (`rotateL` i) "rotateL" s; \
{-# INLINE rotateL #-}; \
rotateR s i = ur1 (`rotateR` i) "rotateR" s; \
{-# INLINE rotateR #-}; \
popCount = uf popCount "popCount"; \
{-# INLINE popCount #-}
#if 1
BITS_BV(SymIntN, True)
BITS_BV(SymWordN, False)
BITS_BV_SOME(SomeSymIntN, SymIntN, binSomeSymIntNR1, unarySomeSymIntN, unarySomeSymIntNR1)
BITS_BV_SOME(SomeSymWordN, SymWordN, binSomeSymWordNR1, unarySomeSymWordN, unarySomeSymWordNR1)
#endif
-- FiniteBits
#define FINITE_BITS_BV(symtype) \
instance (KnownNat n, 1 <= n) => FiniteBits (symtype n) where \
finiteBitSize _ = fromIntegral $ natVal (Proxy @n); \
{-# INLINE finiteBitSize #-}; \
#define FINITE_BITS_BV_SOME(somety, origty) \
instance FiniteBits somety where \
finiteBitSize (somety (n :: origty n)) = fromIntegral $ natVal n; \
{-# INLINE finiteBitSize #-}
#if 1
FINITE_BITS_BV(SymIntN)
FINITE_BITS_BV(SymWordN)
FINITE_BITS_BV_SOME(SomeSymIntN, SymIntN)
FINITE_BITS_BV_SOME(SomeSymWordN, SymWordN)
#endif
-- Show
#define SHOW_SIMPLE(symtype) \
instance Show symtype where \
show (symtype t) = pformat t
#define SHOW_BV(symtype) \
instance (KnownNat n, 1 <= n) => Show (symtype n) where \
show (symtype t) = pformat t
#define SHOW_FUN(op, cons) \
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => Show (sa op sb) where \
show (cons t) = pformat t
#define SHOW_BV_SOME(somety) \
instance Show somety where \
show (somety t) = show t
#if 1
SHOW_SIMPLE(SymBool)
SHOW_SIMPLE(SymInteger)
SHOW_BV(SymIntN)
SHOW_BV(SymWordN)
SHOW_FUN(=~>, SymTabularFun)
SHOW_FUN(-~>, SymGeneralFun)
SHOW_BV_SOME(SomeSymIntN)
SHOW_BV_SOME(SomeSymWordN)
#endif
-- Hashable
#define HASHABLE_SIMPLE(symtype) \
instance Hashable symtype where \
hashWithSalt s (symtype v) = s `hashWithSalt` v
#define HASHABLE_BV(symtype) \
instance (KnownNat n, 1 <= n) => Hashable (symtype n) where \
hashWithSalt s (symtype v) = s `hashWithSalt` v
#define HASHABLE_FUN(op, cons) \
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => Hashable (sa op sb) where \
hashWithSalt s (cons v) = s `hashWithSalt` v
#define HASHABLE_BV_SOME(somety, origty) \
instance Hashable somety where \
s `hashWithSalt` (somety (w :: origty n)) = s `hashWithSalt` natVal (Proxy @n) `hashWithSalt` w
#if 1
HASHABLE_SIMPLE(SymBool)
HASHABLE_SIMPLE(SymInteger)
HASHABLE_BV(SymIntN)
HASHABLE_BV(SymWordN)
HASHABLE_FUN(=~>, SymTabularFun)
HASHABLE_FUN(-~>, SymGeneralFun)
HASHABLE_BV_SOME(SomeSymIntN, SymIntN)
HASHABLE_BV_SOME(SomeSymWordN, SymWordN)
#endif
-- Eq
#define EQ_SIMPLE(symtype) \
instance Eq symtype where \
(symtype l) == (symtype r) = l == r
#define EQ_BV(symtype) \
instance (KnownNat n, 1 <= n) => Eq (symtype n) where \
(symtype l) == (symtype r) = l == r
#define EQ_BV_SOME(symtype, bf) \
instance Eq symtype where; \
(==) = bf (==) "=="; \
{-# INLINE (==) #-}; \
(/=) = bf (/=) "/="; \
{-# INLINE (/=) #-}
#define EQ_FUN(op, cons) \
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => Eq (sa op sb) where \
(cons l) == (cons r) = l == r
#if 1
EQ_SIMPLE(SymBool)
EQ_SIMPLE(SymInteger)
EQ_BV(SymIntN)
EQ_BV(SymWordN)
EQ_FUN(=~>, SymTabularFun)
EQ_FUN(-~>, SymGeneralFun)
EQ_BV_SOME(SomeSymIntN, binSomeSymIntN)
EQ_BV_SOME(SomeSymWordN, binSomeSymWordN)
#endif
-- IsString
#define IS_STRING_SIMPLE(symtype) \
instance IsString symtype where \
fromString = ssym . fromString
#define IS_STRING_BV(symtype) \
instance (KnownNat n, 1 <= n) => IsString (symtype n) where \
fromString = ssym . fromString
#define IS_STRING_FUN(op, cons) \
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => IsString (sa op sb) where \
fromString = ssym . fromString
#if 1
IS_STRING_SIMPLE(SymBool)
IS_STRING_SIMPLE(SymInteger)
IS_STRING_BV(SymIntN)
IS_STRING_BV(SymWordN)
IS_STRING_FUN(=~>, SymTabularFunc)
IS_STRING_FUN(-~>, SymGeneralFun)
#endif
-- SizedBV
#define BVCONCAT_SIZED(symtype) \
sizedBVConcat :: forall l r. (KnownNat l, KnownNat r, 1 <= l, 1 <= r) => symtype l -> symtype r -> symtype (l + r); \
sizedBVConcat (symtype l) (symtype r) = \
case (leqAddPos pl pr, knownAdd (KnownProof @l) (KnownProof @r)) of \
(LeqProof, KnownProof) -> \
symtype (pevalBVConcatTerm l r); \
where; \
pl = Proxy :: Proxy l; \
pr = Proxy :: Proxy r
#define BVZEXT_SIZED(symtype) \
sizedBVZext :: forall l r proxy. (KnownNat l, KnownNat r, 1 <= l, KnownNat r, l <= r) => proxy r -> symtype l -> symtype r; \
sizedBVZext _ (symtype v) = \
case leqTrans (LeqProof @1 @l) (LeqProof @l @r) of \
LeqProof -> symtype $ pevalBVExtendTerm False (Proxy @r) v
#define BVSEXT_SIZED(symtype) \
sizedBVSext :: forall l r proxy. (KnownNat l, KnownNat r, 1 <= l, KnownNat r, l <= r) => proxy r -> symtype l -> symtype r; \
sizedBVSext _ (symtype v) = \
case leqTrans (LeqProof @1 @l) (LeqProof @l @r) of \
LeqProof -> symtype $ pevalBVExtendTerm True (Proxy @r) v
#define BVSELECT_SIZED(symtype) \
sizedBVSelect :: forall n ix w p q. (KnownNat n, KnownNat ix, KnownNat w, 1 <= n, 1 <= w, ix + w <= n) => \
p ix -> q w -> symtype n -> symtype w; \
sizedBVSelect pix pw (symtype v) = symtype $ pevalBVSelectTerm pix pw v
#if 1
instance SizedBV SymIntN where
BVCONCAT_SIZED(SymIntN)
BVZEXT_SIZED(SymIntN)
BVSEXT_SIZED(SymIntN)
sizedBVExt = sizedBVSext
BVSELECT_SIZED(SymIntN)
instance SizedBV SymWordN where
BVCONCAT_SIZED(SymWordN)
BVZEXT_SIZED(SymWordN)
BVSEXT_SIZED(SymWordN)
sizedBVExt = sizedBVZext
BVSELECT_SIZED(SymWordN)
#endif
-- BV
#define BVCONCAT(somety, origty) \
bvConcat (somety (a :: origty l)) (somety (b :: origty r)) = \
case (leqAddPos (Proxy @l) (Proxy @r), knownAdd @l @r KnownProof KnownProof) of \
(LeqProof, KnownProof) -> \
somety $ sizedBVConcat a b
#define BVZEXT(somety, origty) \
bvZext l (somety (a :: origty n)) \
| l < n = error "bvZext: trying to zero extend a value to a smaller size" \
| otherwise = res (Proxy @n) \
where \
n = fromIntegral $ natVal (Proxy @n); \
res :: forall (l :: Nat). Proxy l -> somety; \
res p = \
case (unsafeKnownProof @l (fromIntegral l), unsafeLeqProof @1 @l, unsafeLeqProof @n @l) of \
(KnownProof, LeqProof, LeqProof) -> somety $ sizedBVZext p a
#define BVSEXT(somety, origty) \
bvSext l (somety (a :: origty n)) \
| l < n = error "bvZext: trying to zero extend a value to a smaller size" \
| otherwise = res (Proxy @n) \
where \
n = fromIntegral $ natVal (Proxy @n); \
res :: forall (l :: Nat). Proxy l -> somety; \
res p = \
case (unsafeKnownProof @l (fromIntegral l), unsafeLeqProof @1 @l, unsafeLeqProof @n @l) of \
(KnownProof, LeqProof, LeqProof) -> somety $ sizedBVSext p a
#define BVSELECT(somety, origty) \
bvSelect ix w (somety (a :: origty n)) \
| ix + w > n = error "bvSelect: trying to select a bitvector outside the bounds of the input" \
| w == 0 = error "bvSelect: trying to select a bitvector of size 0" \
| otherwise = res (Proxy @n) (Proxy @n) \
where \
n = fromIntegral $ natVal (Proxy @n); \
res :: forall (w :: Nat) (ix :: Nat). Proxy w -> Proxy ix -> somety; \
res _ _ = \
case ( unsafeKnownProof @ix (fromIntegral ix), \
unsafeKnownProof @w (fromIntegral w), \
unsafeLeqProof @1 @w, \
unsafeLeqProof @(ix + w) @n \
) of \
(KnownProof, KnownProof, LeqProof, LeqProof) -> \
somety $ sizedBVSelect (Proxy @ix) (Proxy @w) a
#if 1
instance BV SomeSymIntN where
BVCONCAT(SomeSymIntN, SymIntN)
{-# INLINE bvConcat #-}
BVZEXT(SomeSymIntN, SymIntN)
{-# INLINE bvZext #-}
BVSEXT(SomeSymIntN, SymIntN)
{-# INLINE bvSext #-}
bvExt = bvSext
{-# INLINE bvExt #-}
BVSELECT(SomeSymIntN, SymIntN)
{-# INLINE bvSelect #-}
instance BV SomeSymWordN where
BVCONCAT(SomeSymWordN, SymWordN)
{-# INLINE bvConcat #-}
BVZEXT(SomeSymWordN, SymWordN)
{-# INLINE bvZext #-}
BVSEXT(SomeSymWordN, SymWordN)
{-# INLINE bvSext #-}
bvExt = bvZext
{-# INLINE bvExt #-}
BVSELECT(SomeSymWordN, SymWordN)
{-# INLINE bvSelect #-}
#endif
-- BVSignConversion
instance (KnownNat n, 1 <= n) => SignConversion (SymWordN n) (SymIntN n) where
toSigned (SymWordN n) = SymIntN $ pevalToSignedTerm n
toUnsigned (SymIntN n) = SymWordN $ pevalToUnsignedTerm n
instance SignConversion SomeSymWordN SomeSymIntN where
toSigned (SomeSymWordN n) = SomeSymIntN $ toSigned n
toUnsigned (SomeSymIntN n) = SomeSymWordN $ toUnsigned n
-- SymShift
instance (KnownNat n, 1 <= n) => SymShift (SymWordN n) where
symShift (SymWordN a) (SymWordN s) = SymWordN $ pevalShiftLeftTerm a s
instance (KnownNat n, 1 <= n) => SymShift (SymIntN n) where
symShift a _ | finiteBitSize a == 1 = a
symShift as@(SymIntN a) (SymIntN s)
| finiteBitSize as == 2 =
SymIntN $
pevalITETerm
(pevalGeNumTerm s (conTerm 0))
(pevalShiftLeftTerm a s)
( pevalITETerm
(pevalEqvTerm s (conTerm (-2)))
( pevalITETerm
(pevalGeNumTerm a (conTerm 0))
(conTerm 0)
(conTerm (-1))
)
(pevalShiftRightTerm a (pevalUMinusNumTerm s))
)
symShift (SymIntN a) (SymIntN s) =
SymIntN $
pevalITETerm
(pevalGeNumTerm s (conTerm 0))
(pevalShiftLeftTerm a s)
( pevalITETerm
(pevalLeNumTerm s (conTerm (-bs)))
(pevalShiftRightTerm a (conTerm bs))
(pevalShiftRightTerm a (pevalUMinusNumTerm s))
)
where
bs = fromIntegral (finiteBitSize (0 :: IntN n)) :: IntN n
-- SymRotate
instance (KnownNat n, 1 <= n) => SymRotate (SymWordN n) where
symRotate (SymWordN a) (SymWordN s) = SymWordN (pevalRotateLeftTerm a s)
instance (KnownNat n, 1 <= n) => SymRotate (SymIntN n) where
symRotate a _ | finiteBitSize a == 1 = a
symRotate as@(SymIntN a) (SymIntN s)
| finiteBitSize as == 2 =
SymIntN $
pevalITETerm
( pevalOrTerm
(pevalEqvTerm s (conTerm 0))
(pevalEqvTerm s (conTerm (-2)))
)
a
(pevalRotateLeftTerm a (conTerm 1))
symRotate as@(SymIntN a) (SymIntN s) =
SymIntN $
pevalRotateLeftTerm
a
( pevalModBoundedIntegralTerm
s
(conTerm (fromIntegral $ finiteBitSize as))
)
-- ModelRep
-- | A pair of a symbolic constant and its value.
-- This is used to build a model from a list of symbolic constants and their values.
--
-- >>> buildModel ("a" := (1 :: Integer), "b" := True) :: Model
-- Model {a -> 1 :: Integer, b -> True :: Bool}
data ModelSymPair ct st where
(:=) :: (LinkedRep ct st) => st -> ct -> ModelSymPair ct st
instance ModelRep (ModelSymPair ct st) Model where
buildModel (sym := val) =
case underlyingTerm sym of
SymTerm _ symbol -> insertValue symbol val emptyModel
_ -> error "buildModel: should only use symbolic constants"
-- | Get the sum of the sizes of a list of symbolic terms.
-- Duplicate sub-terms are counted for only once.
--
-- >>> symsSize [1, "a" :: SymInteger, "a" + 1 :: SymInteger]
-- 3
symsSize :: forall con sym. (LinkedRep con sym) => [sym] -> Int
symsSize = termsSize . fmap (underlyingTerm @con)
{-# INLINE symsSize #-}
-- | Get the size of a symbolic term.
-- Duplicate sub-terms are counted for only once.
--
-- >>> symSize (1 :: SymInteger)
-- 1
-- >>> symSize ("a" :: SymInteger)
-- 1
-- >>> symSize ("a" + 1 :: SymInteger)
-- 3
-- >>> symSize (("a" + 1) * ("a" + 1) :: SymInteger)
-- 4
symSize :: forall con sym. (LinkedRep con sym) => sym -> Int
symSize = termSize . underlyingTerm @con
{-# INLINE symSize #-}
-- | Some symbolic value with 'LinkedRep' constraint.
data SomeSym where
SomeSym :: (LinkedRep con sym) => sym -> SomeSym
someUnderlyingTerm :: SomeSym -> SomeTerm
someUnderlyingTerm (SomeSym s) = SomeTerm $ underlyingTerm s
someSymsSize :: [SomeSym] -> Int
someSymsSize = someTermsSize . fmap someUnderlyingTerm
{-# INLINE someSymsSize #-}
-- | Extract all symbolic primitive values that are represented as SMT terms.
--
-- __Note:__ This type class can be derived for algebraic data types. You may
-- need the @DerivingVia@ and @DerivingStrategies@ extenstions.
--
-- > data X = ... deriving Generic deriving AllSyms via (Default X)
class AllSyms a where
-- | Convert a value to a list of symbolic primitive values. It should
-- prepend to an existing list of symbolic primitive values.
allSymsS :: a -> [SomeSym] -> [SomeSym]
allSymsS a l = allSyms a ++ l
-- | Specialized 'allSymsS' that prepends to an empty list.
allSyms :: a -> [SomeSym]
allSyms a = allSymsS a []
{-# MINIMAL allSymsS | allSyms #-}
-- | Get the total size of symbolic terms in a value.
-- Duplicate sub-terms are counted for only once.
--
-- >>> allSymsSize ("a" :: SymInteger, "a" + "b" :: SymInteger, ("a" + "b") * "c" :: SymInteger)
-- 5
allSymsSize :: (AllSyms a) => a -> Int
allSymsSize = someSymsSize . allSyms
class AllSyms' a where
allSymsS' :: a c -> [SomeSym] -> [SomeSym]
instance (Generic a, AllSyms' (Rep a)) => AllSyms (Default a) where
allSymsS = allSymsS' . from . unDefault
instance AllSyms' U1 where
allSymsS' _ = id
instance (AllSyms c) => AllSyms' (K1 i c) where
allSymsS' (K1 v) = allSymsS v
instance (AllSyms' a) => AllSyms' (M1 i c a) where
allSymsS' (M1 v) = allSymsS' v
instance (AllSyms' a, AllSyms' b) => AllSyms' (a :+: b) where
allSymsS' (L1 l) = allSymsS' l
allSymsS' (R1 r) = allSymsS' r
instance (AllSyms' a, AllSyms' b) => AllSyms' (a :*: b) where
allSymsS' (a :*: b) = allSymsS' a . allSymsS' b
#define CONCRETE_ALLSYMS(type) \
instance AllSyms type where \
allSymsS _ = id
#define ALLSYMS_SIMPLE(t) \
instance AllSyms t where \
allSymsS v = (SomeSym v :)
#define ALLSYMS_BV(t) \
instance (KnownNat n, 1 <= n) => AllSyms (t n) where \
allSymsS v = (SomeSym v :)
#define ALLSYMS_SOME_BV(t) \
instance AllSyms t where \
allSymsS (t v) = (SomeSym v :)
#define ALLSYMS_FUN(op) \
instance (SupportedPrim ca, SupportedPrim cb, LinkedRep ca sa, LinkedRep cb sb) => AllSyms (sa op sb) where \
allSymsS v = (SomeSym v :)
#if 1
CONCRETE_ALLSYMS(Bool)
CONCRETE_ALLSYMS(Integer)
CONCRETE_ALLSYMS(Char)
CONCRETE_ALLSYMS(Int)
CONCRETE_ALLSYMS(Int8)
CONCRETE_ALLSYMS(Int16)
CONCRETE_ALLSYMS(Int32)
CONCRETE_ALLSYMS(Int64)
CONCRETE_ALLSYMS(Word)
CONCRETE_ALLSYMS(Word8)
CONCRETE_ALLSYMS(Word16)
CONCRETE_ALLSYMS(Word32)
CONCRETE_ALLSYMS(Word64)
CONCRETE_ALLSYMS(B.ByteString)
CONCRETE_ALLSYMS(T.Text)
ALLSYMS_SIMPLE(SymBool)
ALLSYMS_SIMPLE(SymInteger)
ALLSYMS_BV(SymIntN)
ALLSYMS_BV(SymWordN)
ALLSYMS_SOME_BV(SomeSymIntN)
ALLSYMS_SOME_BV(SomeSymWordN)
ALLSYMS_FUN(=~>)
ALLSYMS_FUN(-~>)
#endif
instance AllSyms () where
allSymsS _ = id
-- Either
deriving via
(Default (Either a b))
instance
( AllSyms a,
AllSyms b
) =>
AllSyms (Either a b)
-- Maybe
deriving via (Default (Maybe a)) instance (AllSyms a) => AllSyms (Maybe a)
-- List
deriving via (Default [a]) instance (AllSyms a) => AllSyms [a]
-- (,)
deriving via
(Default (a, b))
instance
(AllSyms a, AllSyms b) =>
AllSyms (a, b)
-- (,,)
deriving via
(Default (a, b, c))
instance
( AllSyms a,
AllSyms b,
AllSyms c
) =>
AllSyms (a, b, c)
-- (,,,)
deriving via
(Default (a, b, c, d))
instance
( AllSyms a,
AllSyms b,
AllSyms c,
AllSyms d
) =>
AllSyms (a, b, c, d)
-- (,,,,)
deriving via
(Default (a, b, c, d, e))
instance
( AllSyms a,
AllSyms b,
AllSyms c,
AllSyms d,
AllSyms e
) =>
AllSyms (a, b, c, d, e)
-- (,,,,,)
deriving via
(Default (a, b, c, d, e, f))
instance
( AllSyms a,
AllSyms b,
AllSyms c,
AllSyms d,
AllSyms e,
AllSyms f
) =>
AllSyms (a, b, c, d, e, f)
-- (,,,,,,)
deriving via
(Default (a, b, c, d, e, f, g))
instance
( AllSyms a,
AllSyms b,
AllSyms c,
AllSyms d,
AllSyms e,
AllSyms f,
AllSyms g
) =>
AllSyms (a, b, c, d, e, f, g)
-- (,,,,,,,)
deriving via
(Default (a, b, c, d, e, f, g, h))
instance
( AllSyms a,
AllSyms b,
AllSyms c,
AllSyms d,
AllSyms e,
AllSyms f,
AllSyms g,
AllSyms h
) =>
AllSyms ((,,,,,,,) a b c d e f g h)
-- MaybeT
instance
(AllSyms (m (Maybe a))) =>
AllSyms (MaybeT m a)
where
allSymsS (MaybeT v) = allSymsS v
-- ExceptT
instance
(AllSyms (m (Either e a))) =>
AllSyms (ExceptT e m a)
where
allSymsS (ExceptT v) = allSymsS v
-- Sum
deriving via
(Default (Sum f g a))
instance
(AllSyms (f a), AllSyms (g a)) =>
AllSyms (Sum f g a)
-- WriterT
instance
(AllSyms (m (a, s))) =>
AllSyms (WriterLazy.WriterT s m a)
where
allSymsS (WriterLazy.WriterT v) = allSymsS v
instance
(AllSyms (m (a, s))) =>
AllSyms (WriterStrict.WriterT s m a)
where
allSymsS (WriterStrict.WriterT v) = allSymsS v
-- Identity
instance (AllSyms a) => AllSyms (Identity a) where
allSymsS (Identity a) = allSymsS a
-- IdentityT
instance (AllSyms (m a)) => AllSyms (IdentityT m a) where
allSymsS (IdentityT a) = allSymsS a
-- VerificationConditions
deriving via (Default VerificationConditions) instance AllSyms VerificationConditions
-- AssertionError
deriving via (Default AssertionError) instance AllSyms AssertionError