grisette-0.3.0.0: src/Grisette/IR/SymPrim/Data/Prim/InternedTerm/Term.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
-- |
-- Module : Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
-- 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.Prim.InternedTerm.Term
( SupportedPrim (..),
SymRep (..),
ConRep (..),
LinkedRep (..),
UnaryOp (..),
BinaryOp (..),
TernaryOp (..),
TypedSymbol (..),
SomeTypedSymbol (..),
showUntyped,
withSymbolSupported,
someTypedSymbol,
Term (..),
UTerm (..),
type (-->) (..),
buildGeneralFun,
)
where
import Control.DeepSeq
import Data.Bits
import Data.Function (on)
import Data.Hashable
import Data.Interned
import Data.Kind
import Data.String
import Data.Typeable (Proxy (..), cast)
import GHC.Generics
import GHC.TypeNats
import Grisette.Core.Data.BV
import Grisette.Core.Data.Class.BitVector
import Grisette.Core.Data.Class.Function
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Caches
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.Prim.InternedTerm.InternedCtors
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermSubstitution
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.Prim.InternedTerm.TermUtils
import Grisette.IR.SymPrim.Data.Prim.ModelValue
import Grisette.IR.SymPrim.Data.Prim.Utils
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.TabularFun
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Syntax.Compat
import Type.Reflection
-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.IR.SymPrim
-- | Indicates that a type is supported and can be represented as a symbolic
-- term.
class (Lift t, Typeable t, Hashable t, Eq t, Show t, NFData t) => SupportedPrim t where
type PrimConstraint t :: Constraint
type PrimConstraint t = ()
default withPrim :: (PrimConstraint t) => proxy t -> ((PrimConstraint t) => a) -> a
withPrim :: proxy t -> ((PrimConstraint t) => a) -> a
withPrim _ i = i
termCache :: Cache (Term t)
termCache = typeMemoizedCache
pformatCon :: t -> String
default pformatCon :: (Show t) => t -> String
pformatCon = show
pformatSym :: TypedSymbol t -> String
pformatSym = showUntyped
defaultValue :: t
defaultValueDynamic :: proxy t -> ModelValue
defaultValueDynamic _ = toModelValue (defaultValue @t)
-- | Type family to resolve the concrete type associated with a symbolic type.
class ConRep sym where
type ConType sym
-- | Type family to resolve the symbolic type associated with a concrete type.
class (SupportedPrim con) => SymRep con where
type SymType con
-- | One-to-one mapping between symbolic types and concrete types.
class
(ConRep sym, SymRep con, sym ~ SymType con, con ~ ConType sym) =>
LinkedRep con sym
| con -> sym,
sym -> con
where
underlyingTerm :: sym -> Term con
wrapTerm :: Term con -> sym
class
(SupportedPrim arg, SupportedPrim t, Lift tag, NFData tag, Show tag, Typeable tag, Eq tag, Hashable tag) =>
UnaryOp tag arg t
| tag arg -> t
where
partialEvalUnary :: (Typeable tag, Typeable t) => tag -> Term arg -> Term t
pformatUnary :: tag -> Term arg -> String
class
( SupportedPrim arg1,
SupportedPrim arg2,
SupportedPrim t,
Lift tag,
NFData tag,
Show tag,
Typeable tag,
Eq tag,
Hashable tag
) =>
BinaryOp tag arg1 arg2 t
| tag arg1 arg2 -> t
where
partialEvalBinary :: (Typeable tag, Typeable t) => tag -> Term arg1 -> Term arg2 -> Term t
pformatBinary :: tag -> Term arg1 -> Term arg2 -> String
class
( SupportedPrim arg1,
SupportedPrim arg2,
SupportedPrim arg3,
SupportedPrim t,
Lift tag,
NFData tag,
Show tag,
Typeable tag,
Eq tag,
Hashable tag
) =>
TernaryOp tag arg1 arg2 arg3 t
| tag arg1 arg2 arg3 -> t
where
partialEvalTernary :: (Typeable tag, Typeable t) => tag -> Term arg1 -> Term arg2 -> Term arg3 -> Term t
pformatTernary :: tag -> Term arg1 -> Term arg2 -> Term arg3 -> String
-- | A typed symbol is a symbol that is associated with a type. Note that the
-- same symbol bodies with different types are considered different symbols
-- and can coexist in a term.
--
-- Simple symbols can be created with the 'OverloadedStrings' extension:
--
-- >>> :set -XOverloadedStrings
-- >>> "a" :: TypedSymbol Bool
-- a :: Bool
data TypedSymbol t where
SimpleSymbol :: (SupportedPrim t) => String -> TypedSymbol t
IndexedSymbol :: (SupportedPrim t) => String -> Int -> TypedSymbol t
WithInfo ::
forall t a.
( SupportedPrim t,
Typeable a,
Ord a,
Lift a,
NFData a,
Show a,
Hashable a
) =>
TypedSymbol t ->
a ->
TypedSymbol t
-- deriving (Eq, Ord, Generic, Lift, NFData)
instance Eq (TypedSymbol t) where
SimpleSymbol x == SimpleSymbol y = x == y
IndexedSymbol x i == IndexedSymbol y j = i == j && x == y
WithInfo s1 (i1 :: a) == WithInfo s2 (i2 :: b) = case eqTypeRep (typeRep @a) (typeRep @b) of
Just HRefl -> i1 == i2 && s1 == s2
_ -> False
_ == _ = False
instance Ord (TypedSymbol t) where
SimpleSymbol x <= SimpleSymbol y = x <= y
IndexedSymbol x i <= IndexedSymbol y j = i < j || (i == j && x <= y)
WithInfo s1 (i1 :: a) <= WithInfo s2 (i2 :: b) = case eqTypeRep (typeRep @a) (typeRep @b) of
Just HRefl -> s1 < s2 || (s1 == s2 && i1 <= i2)
_ -> False
_ <= _ = False
instance Lift (TypedSymbol t) where
liftTyped (SimpleSymbol x) = [||SimpleSymbol x||]
liftTyped (IndexedSymbol x i) = [||IndexedSymbol x i||]
liftTyped (WithInfo s1 i1) = [||WithInfo s1 i1||]
instance Show (TypedSymbol t) where
show (SimpleSymbol str) = str ++ " :: " ++ show (typeRep @t)
show (IndexedSymbol str i) = str ++ "@" ++ show i ++ " :: " ++ show (typeRep @t)
show (WithInfo s info) = showUntyped s ++ ":" ++ show info ++ " :: " ++ show (typeRep @t)
showUntyped :: TypedSymbol t -> String
showUntyped (SimpleSymbol str) = str
showUntyped (IndexedSymbol str i) = str ++ "@" ++ show i
showUntyped (WithInfo s info) = showUntyped s ++ ":" ++ show info
instance Hashable (TypedSymbol t) where
s `hashWithSalt` SimpleSymbol x = s `hashWithSalt` x
s `hashWithSalt` IndexedSymbol x i = s `hashWithSalt` x `hashWithSalt` i
s `hashWithSalt` WithInfo sym info = s `hashWithSalt` sym `hashWithSalt` info
instance NFData (TypedSymbol t) where
rnf (SimpleSymbol str) = rnf str
rnf (IndexedSymbol str i) = rnf str `seq` rnf i
rnf (WithInfo s info) = rnf s `seq` rnf info
instance (SupportedPrim t) => IsString (TypedSymbol t) where
fromString = SimpleSymbol
withSymbolSupported :: TypedSymbol t -> ((SupportedPrim t) => a) -> a
withSymbolSupported (SimpleSymbol _) a = a
withSymbolSupported (IndexedSymbol _ _) a = a
withSymbolSupported (WithInfo _ _) a = a
{-
data TypedSymbol t where
TypedSymbol :: (SupportedPrim t) => Symbol -> TypedSymbol t
typedSymbol :: forall proxy t. (SupportedPrim t) => proxy t -> Symbol -> TypedSymbol t
typedSymbol _ = TypedSymbol
instance NFData (TypedSymbol t) where
rnf (TypedSymbol s) = rnf s
instance Eq (TypedSymbol t) where
(TypedSymbol s1) == (TypedSymbol s2) = s1 == s2
instance Ord (TypedSymbol t) where
(TypedSymbol s1) <= (TypedSymbol s2) = s1 <= s2
instance Hashable (TypedSymbol t) where
hashWithSalt s (TypedSymbol s1) = s `hashWithSalt` s1
instance Show (TypedSymbol t) where
show (TypedSymbol s) = show s ++ " :: " ++ show (typeRep @t)
instance Lift (TypedSymbol t) where
liftTyped (TypedSymbol s) = [||TypedSymbol s||]
-}
data SomeTypedSymbol where
SomeTypedSymbol :: forall t. TypeRep t -> TypedSymbol t -> SomeTypedSymbol
instance NFData SomeTypedSymbol where
rnf (SomeTypedSymbol p s) = rnf (SomeTypeRep p) `seq` rnf s
instance Eq SomeTypedSymbol where
(SomeTypedSymbol t1 s1) == (SomeTypedSymbol t2 s2) = case eqTypeRep t1 t2 of
Just HRefl -> s1 == s2
_ -> False
instance Ord SomeTypedSymbol where
(SomeTypedSymbol t1 s1) <= (SomeTypedSymbol t2 s2) =
SomeTypeRep t1 < SomeTypeRep t2
|| ( case eqTypeRep t1 t2 of
Just HRefl -> s1 <= s2
_ -> False
)
instance Hashable SomeTypedSymbol where
hashWithSalt s (SomeTypedSymbol t1 s1) = s `hashWithSalt` s1 `hashWithSalt` t1
instance Show SomeTypedSymbol where
show (SomeTypedSymbol _ s) = show s
someTypedSymbol :: forall t. TypedSymbol t -> SomeTypedSymbol
someTypedSymbol s@(SimpleSymbol _) = SomeTypedSymbol (typeRep @t) s
someTypedSymbol s@(IndexedSymbol _ _) = SomeTypedSymbol (typeRep @t) s
someTypedSymbol s@(WithInfo _ _) = SomeTypedSymbol (typeRep @t) s
data Term t where
ConTerm :: (SupportedPrim t) => {-# UNPACK #-} !Id -> !t -> Term t
SymTerm :: (SupportedPrim t) => {-# UNPACK #-} !Id -> !(TypedSymbol t) -> Term t
UnaryTerm ::
(UnaryOp tag arg t) =>
{-# UNPACK #-} !Id ->
!tag ->
!(Term arg) ->
Term t
BinaryTerm ::
(BinaryOp tag arg1 arg2 t) =>
{-# UNPACK #-} !Id ->
!tag ->
!(Term arg1) ->
!(Term arg2) ->
Term t
TernaryTerm ::
(TernaryOp tag arg1 arg2 arg3 t) =>
{-# UNPACK #-} !Id ->
!tag ->
!(Term arg1) ->
!(Term arg2) ->
!(Term arg3) ->
Term t
NotTerm :: {-# UNPACK #-} !Id -> !(Term Bool) -> Term Bool
OrTerm :: {-# UNPACK #-} !Id -> !(Term Bool) -> !(Term Bool) -> Term Bool
AndTerm :: {-# UNPACK #-} !Id -> !(Term Bool) -> !(Term Bool) -> Term Bool
EqvTerm :: (SupportedPrim t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term Bool
ITETerm :: (SupportedPrim t) => {-# UNPACK #-} !Id -> !(Term Bool) -> !(Term t) -> !(Term t) -> Term t
AddNumTerm :: (SupportedPrim t, Num t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
UMinusNumTerm :: (SupportedPrim t, Num t) => {-# UNPACK #-} !Id -> !(Term t) -> Term t
TimesNumTerm :: (SupportedPrim t, Num t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
AbsNumTerm :: (SupportedPrim t, Num t) => {-# UNPACK #-} !Id -> !(Term t) -> Term t
SignumNumTerm :: (SupportedPrim t, Num t) => {-# UNPACK #-} !Id -> !(Term t) -> Term t
LTNumTerm :: (SupportedPrim t, Num t, Ord t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term Bool
LENumTerm :: (SupportedPrim t, Num t, Ord t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term Bool
AndBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
OrBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
XorBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
ComplementBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> Term t
ShiftBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> {-# UNPACK #-} !Int -> Term t
RotateBitsTerm :: (SupportedPrim t, Bits t) => {-# UNPACK #-} !Id -> !(Term t) -> {-# UNPACK #-} !Int -> Term t
BVToSignedTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (ubv n),
forall n. (KnownNat n, 1 <= n) => SupportedPrim (sbv n),
Typeable ubv,
Typeable sbv,
KnownNat n,
1 <= n,
BVSignConversion (ubv n) (sbv n)
) =>
{-# UNPACK #-} !Id ->
!(Term (ubv n)) ->
Term (sbv n)
BVToUnsignedTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (ubv n),
forall n. (KnownNat n, 1 <= n) => SupportedPrim (sbv n),
Typeable ubv,
Typeable sbv,
KnownNat n,
1 <= n,
BVSignConversion (ubv n) (sbv n)
) =>
{-# UNPACK #-} !Id ->
!(Term (sbv n)) ->
Term (ubv n)
BVConcatTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat a,
KnownNat b,
KnownNat (a + b),
1 <= a,
1 <= b,
1 <= a + b,
SizedBV bv
) =>
{-# UNPACK #-} !Id ->
!(Term (bv a)) ->
!(Term (bv b)) ->
Term (bv (a + b))
BVSelectTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat n,
KnownNat ix,
KnownNat w,
1 <= n,
1 <= w,
ix + w <= n,
SizedBV bv
) =>
{-# UNPACK #-} !Id ->
!(TypeRep ix) ->
!(TypeRep w) ->
!(Term (bv n)) ->
Term (bv w)
BVExtendTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat l,
KnownNat r,
1 <= l,
1 <= r,
l <= r,
SizedBV bv
) =>
{-# UNPACK #-} !Id ->
!Bool ->
!(TypeRep r) ->
!(Term (bv l)) ->
Term (bv r)
TabularFunApplyTerm ::
( SupportedPrim a,
SupportedPrim b
) =>
{-# UNPACK #-} !Id ->
Term (a =-> b) ->
Term a ->
Term b
GeneralFunApplyTerm ::
( SupportedPrim a,
SupportedPrim b
) =>
{-# UNPACK #-} !Id ->
Term (a --> b) ->
Term a ->
Term b
DivIntegralTerm :: (SupportedPrim t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
ModIntegralTerm :: (SupportedPrim t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
QuotIntegralTerm :: (SupportedPrim t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
RemIntegralTerm :: (SupportedPrim t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
DivBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
ModBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
QuotBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
RemBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => {-# UNPACK #-} !Id -> !(Term t) -> !(Term t) -> Term t
instance NFData (Term a) where
rnf i = identity i `seq` ()
instance Lift (Term t) where
lift = unTypeSplice . liftTyped
liftTyped (ConTerm _ i) = [||conTerm i||]
liftTyped (SymTerm _ sym) = [||symTerm sym||]
liftTyped (UnaryTerm _ tag arg) = [||constructUnary tag arg||]
liftTyped (BinaryTerm _ tag arg1 arg2) = [||constructBinary tag arg1 arg2||]
liftTyped (TernaryTerm _ tag arg1 arg2 arg3) = [||constructTernary tag arg1 arg2 arg3||]
liftTyped (NotTerm _ arg) = [||notTerm arg||]
liftTyped (OrTerm _ arg1 arg2) = [||orTerm arg1 arg2||]
liftTyped (AndTerm _ arg1 arg2) = [||andTerm arg1 arg2||]
liftTyped (EqvTerm _ arg1 arg2) = [||eqvTerm arg1 arg2||]
liftTyped (ITETerm _ cond arg1 arg2) = [||iteTerm cond arg1 arg2||]
liftTyped (AddNumTerm _ arg1 arg2) = [||addNumTerm arg1 arg2||]
liftTyped (UMinusNumTerm _ arg) = [||uminusNumTerm arg||]
liftTyped (TimesNumTerm _ arg1 arg2) = [||timesNumTerm arg1 arg2||]
liftTyped (AbsNumTerm _ arg) = [||absNumTerm arg||]
liftTyped (SignumNumTerm _ arg) = [||signumNumTerm arg||]
liftTyped (LTNumTerm _ arg1 arg2) = [||ltNumTerm arg1 arg2||]
liftTyped (LENumTerm _ arg1 arg2) = [||leNumTerm arg1 arg2||]
liftTyped (AndBitsTerm _ arg1 arg2) = [||andBitsTerm arg1 arg2||]
liftTyped (OrBitsTerm _ arg1 arg2) = [||orBitsTerm arg1 arg2||]
liftTyped (XorBitsTerm _ arg1 arg2) = [||xorBitsTerm arg1 arg2||]
liftTyped (ComplementBitsTerm _ arg) = [||complementBitsTerm arg||]
liftTyped (ShiftBitsTerm _ arg n) = [||shiftBitsTerm arg n||]
liftTyped (RotateBitsTerm _ arg n) = [||rotateBitsTerm arg n||]
liftTyped (BVToSignedTerm _ v) = [||bvToSignedTerm v||]
liftTyped (BVToUnsignedTerm _ v) = [||bvToUnsignedTerm v||]
liftTyped (BVConcatTerm _ arg1 arg2) = [||bvconcatTerm arg1 arg2||]
liftTyped (BVSelectTerm _ (_ :: TypeRep ix) (_ :: TypeRep w) arg) = [||bvselectTerm (Proxy @ix) (Proxy @w) arg||]
liftTyped (BVExtendTerm _ signed (_ :: TypeRep n) arg) = [||bvextendTerm signed (Proxy @n) arg||]
liftTyped (TabularFunApplyTerm _ func arg) = [||tabularFunApplyTerm func arg||]
liftTyped (GeneralFunApplyTerm _ func arg) = [||generalFunApplyTerm func arg||]
liftTyped (DivIntegralTerm _ arg1 arg2) = [||divIntegralTerm arg1 arg2||]
liftTyped (ModIntegralTerm _ arg1 arg2) = [||modIntegralTerm arg1 arg2||]
liftTyped (QuotIntegralTerm _ arg1 arg2) = [||quotIntegralTerm arg1 arg2||]
liftTyped (RemIntegralTerm _ arg1 arg2) = [||remIntegralTerm arg1 arg2||]
liftTyped (DivBoundedIntegralTerm _ arg1 arg2) = [||divBoundedIntegralTerm arg1 arg2||]
liftTyped (ModBoundedIntegralTerm _ arg1 arg2) = [||modBoundedIntegralTerm arg1 arg2||]
liftTyped (QuotBoundedIntegralTerm _ arg1 arg2) = [||quotBoundedIntegralTerm arg1 arg2||]
liftTyped (RemBoundedIntegralTerm _ arg1 arg2) = [||remBoundedIntegralTerm arg1 arg2||]
instance Show (Term ty) where
show (ConTerm i v) = "ConTerm{id=" ++ show i ++ ", v=" ++ show v ++ "}"
show (SymTerm i name) =
"SymTerm{id="
++ show i
++ ", name="
++ show name
++ ", type="
++ show (typeRep @ty)
++ "}"
show (UnaryTerm i tag arg) = "Unary{id=" ++ show i ++ ", tag=" ++ show tag ++ ", arg=" ++ show arg ++ "}"
show (BinaryTerm i tag arg1 arg2) =
"Binary{id="
++ show i
++ ", tag="
++ show tag
++ ", arg1="
++ show arg1
++ ", arg2="
++ show arg2
++ "}"
show (TernaryTerm i tag arg1 arg2 arg3) =
"Ternary{id="
++ show i
++ ", tag="
++ show tag
++ ", arg1="
++ show arg1
++ ", arg2="
++ show arg2
++ ", arg3="
++ show arg3
++ "}"
show (NotTerm i arg) = "Not{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (OrTerm i arg1 arg2) = "Or{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (AndTerm i arg1 arg2) = "And{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (EqvTerm i arg1 arg2) = "Eqv{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (ITETerm i cond l r) =
"ITE{id="
++ show i
++ ", cond="
++ show cond
++ ", then="
++ show l
++ ", else="
++ show r
++ "}"
show (AddNumTerm i arg1 arg2) = "AddNum{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (UMinusNumTerm i arg) = "UMinusNum{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (TimesNumTerm i arg1 arg2) = "TimesNum{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (AbsNumTerm i arg) = "AbsNum{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (SignumNumTerm i arg) = "SignumNum{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (LTNumTerm i arg1 arg2) = "LTNum{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (LENumTerm i arg1 arg2) = "LENum{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (AndBitsTerm i arg1 arg2) = "AndBits{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (OrBitsTerm i arg1 arg2) = "OrBits{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (XorBitsTerm i arg1 arg2) = "XorBits{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (ComplementBitsTerm i arg) = "ComplementBits{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (ShiftBitsTerm i arg n) = "ShiftBits{id=" ++ show i ++ ", arg=" ++ show arg ++ ", n=" ++ show n ++ "}"
show (RotateBitsTerm i arg n) = "RotateBits{id=" ++ show i ++ ", arg=" ++ show arg ++ ", n=" ++ show n ++ "}"
show (BVToSignedTerm i arg) = "BVToSigned{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (BVToUnsignedTerm i arg) = "BVToUnsigned{id=" ++ show i ++ ", arg=" ++ show arg ++ "}"
show (BVConcatTerm i arg1 arg2) = "BVConcat{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (BVSelectTerm i ix w arg) =
"BVSelect{id=" ++ show i ++ ", ix=" ++ show ix ++ ", w=" ++ show w ++ ", arg=" ++ show arg ++ "}"
show (BVExtendTerm i signed n arg) =
"BVExtend{id=" ++ show i ++ ", signed=" ++ show signed ++ ", n=" ++ show n ++ ", arg=" ++ show arg ++ "}"
show (TabularFunApplyTerm i func arg) =
"TabularFunApply{id=" ++ show i ++ ", func=" ++ show func ++ ", arg=" ++ show arg ++ "}"
show (GeneralFunApplyTerm i func arg) =
"GeneralFunApply{id=" ++ show i ++ ", func=" ++ show func ++ ", arg=" ++ show arg ++ "}"
show (DivIntegralTerm i arg1 arg2) =
"DivIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (ModIntegralTerm i arg1 arg2) =
"ModIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (QuotIntegralTerm i arg1 arg2) =
"QuotIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (RemIntegralTerm i arg1 arg2) =
"RemIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (DivBoundedIntegralTerm i arg1 arg2) =
"DivBoundedIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (ModBoundedIntegralTerm i arg1 arg2) =
"ModBoundedIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (QuotBoundedIntegralTerm i arg1 arg2) =
"QuotBoundedIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
show (RemBoundedIntegralTerm i arg1 arg2) =
"RemBoundedIntegral{id=" ++ show i ++ ", arg1=" ++ show arg1 ++ ", arg2=" ++ show arg2 ++ "}"
instance (SupportedPrim t) => Eq (Term t) where
(==) = (==) `on` identity
instance (SupportedPrim t) => Hashable (Term t) where
hashWithSalt s t = hashWithSalt s $ identity t
data UTerm t where
UConTerm :: (SupportedPrim t) => !t -> UTerm t
USymTerm :: (SupportedPrim t) => !(TypedSymbol t) -> UTerm t
UUnaryTerm :: (UnaryOp tag arg t) => !tag -> !(Term arg) -> UTerm t
UBinaryTerm ::
(BinaryOp tag arg1 arg2 t) =>
!tag ->
!(Term arg1) ->
!(Term arg2) ->
UTerm t
UTernaryTerm ::
(TernaryOp tag arg1 arg2 arg3 t) =>
!tag ->
!(Term arg1) ->
!(Term arg2) ->
!(Term arg3) ->
UTerm t
UNotTerm :: !(Term Bool) -> UTerm Bool
UOrTerm :: !(Term Bool) -> !(Term Bool) -> UTerm Bool
UAndTerm :: !(Term Bool) -> !(Term Bool) -> UTerm Bool
UEqvTerm :: (SupportedPrim t) => !(Term t) -> !(Term t) -> UTerm Bool
UITETerm :: (SupportedPrim t) => !(Term Bool) -> !(Term t) -> !(Term t) -> UTerm t
UAddNumTerm :: (SupportedPrim t, Num t) => !(Term t) -> !(Term t) -> UTerm t
UUMinusNumTerm :: (SupportedPrim t, Num t) => !(Term t) -> UTerm t
UTimesNumTerm :: (SupportedPrim t, Num t) => !(Term t) -> !(Term t) -> UTerm t
UAbsNumTerm :: (SupportedPrim t, Num t) => !(Term t) -> UTerm t
USignumNumTerm :: (SupportedPrim t, Num t) => !(Term t) -> UTerm t
ULTNumTerm :: (SupportedPrim t, Num t, Ord t) => !(Term t) -> !(Term t) -> UTerm Bool
ULENumTerm :: (SupportedPrim t, Num t, Ord t) => !(Term t) -> !(Term t) -> UTerm Bool
UAndBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> !(Term t) -> UTerm t
UOrBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> !(Term t) -> UTerm t
UXorBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> !(Term t) -> UTerm t
UComplementBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> UTerm t
UShiftBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> {-# UNPACK #-} !Int -> UTerm t
URotateBitsTerm :: (SupportedPrim t, Bits t) => !(Term t) -> {-# UNPACK #-} !Int -> UTerm t
UBVToSignedTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (ubv n),
forall n. (KnownNat n, 1 <= n) => SupportedPrim (sbv n),
Typeable ubv,
Typeable sbv,
KnownNat n,
1 <= n,
BVSignConversion (ubv n) (sbv n)
) =>
!(Term (ubv n)) ->
UTerm (sbv n)
UBVToUnsignedTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (ubv n),
forall n. (KnownNat n, 1 <= n) => SupportedPrim (sbv n),
Typeable ubv,
Typeable sbv,
KnownNat n,
1 <= n,
BVSignConversion (ubv n) (sbv n)
) =>
!(Term (sbv n)) ->
UTerm (ubv n)
UBVConcatTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat a,
KnownNat b,
KnownNat (a + b),
1 <= a,
1 <= b,
1 <= a + b,
SizedBV bv
) =>
!(Term (bv a)) ->
!(Term (bv b)) ->
UTerm (bv (a + b))
UBVSelectTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat n,
KnownNat ix,
KnownNat w,
1 <= n,
1 <= w,
ix + w <= n,
SizedBV bv
) =>
!(TypeRep ix) ->
!(TypeRep w) ->
!(Term (bv n)) ->
UTerm (bv w)
UBVExtendTerm ::
( forall n. (KnownNat n, 1 <= n) => SupportedPrim (bv n),
Typeable bv,
KnownNat l,
KnownNat r,
1 <= l,
1 <= r,
l <= r,
SizedBV bv
) =>
!Bool ->
!(TypeRep r) ->
!(Term (bv l)) ->
UTerm (bv r)
UTabularFunApplyTerm ::
( SupportedPrim a,
SupportedPrim b
) =>
Term (a =-> b) ->
Term a ->
UTerm b
UGeneralFunApplyTerm ::
( SupportedPrim a,
SupportedPrim b
) =>
Term (a --> b) ->
Term a ->
UTerm b
UDivIntegralTerm :: (SupportedPrim t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
UModIntegralTerm :: (SupportedPrim t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
UQuotIntegralTerm :: (SupportedPrim t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
URemIntegralTerm :: (SupportedPrim t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
UDivBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
UModBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
UQuotBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
URemBoundedIntegralTerm :: (SupportedPrim t, Bounded t, Integral t) => !(Term t) -> !(Term t) -> UTerm t
eqTypedId :: (TypeRep a, Id) -> (TypeRep b, Id) -> Bool
eqTypedId (a, i1) (b, i2) = i1 == i2 && eqTypeRepBool a b
{-# INLINE eqTypedId #-}
eqHeteroTag :: (Eq a) => (TypeRep a, a) -> (TypeRep b, b) -> Bool
eqHeteroTag (tpa, taga) (tpb, tagb) = eqHeteroRep tpa tpb taga tagb
{-# INLINE eqHeteroTag #-}
instance (SupportedPrim t) => Interned (Term t) where
type Uninterned (Term t) = UTerm t
data Description (Term t) where
DConTerm :: t -> Description (Term t)
DSymTerm :: TypedSymbol t -> Description (Term t)
DUnaryTerm ::
(Eq tag, Hashable tag) =>
{-# UNPACK #-} !(TypeRep tag, tag) ->
{-# UNPACK #-} !(TypeRep arg, Id) ->
Description (Term t)
DBinaryTerm ::
(Eq tag, Hashable tag) =>
{-# UNPACK #-} !(TypeRep tag, tag) ->
{-# UNPACK #-} !(TypeRep arg1, Id) ->
{-# UNPACK #-} !(TypeRep arg2, Id) ->
Description (Term t)
DTernaryTerm ::
(Eq tag, Hashable tag) =>
{-# UNPACK #-} !(TypeRep tag, tag) ->
{-# UNPACK #-} !(TypeRep arg1, Id) ->
{-# UNPACK #-} !(TypeRep arg2, Id) ->
{-# UNPACK #-} !(TypeRep arg3, Id) ->
Description (Term t)
DNotTerm :: {-# UNPACK #-} !Id -> Description (Term Bool)
DOrTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term Bool)
DAndTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term Bool)
DEqvTerm :: TypeRep args -> {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term Bool)
DITETerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DAddNumTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DUMinusNumTerm :: {-# UNPACK #-} !Id -> Description (Term t)
DTimesNumTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DAbsNumTerm :: {-# UNPACK #-} !Id -> Description (Term t)
DSignumNumTerm :: {-# UNPACK #-} !Id -> Description (Term t)
DLTNumTerm :: TypeRep args -> {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term Bool)
DLENumTerm :: TypeRep args -> {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term Bool)
DAndBitsTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DOrBitsTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DXorBitsTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DComplementBitsTerm :: {-# UNPACK #-} !Id -> Description (Term t)
DShiftBitsTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Int -> Description (Term t)
DRotateBitsTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Int -> Description (Term t)
DBVConcatTerm :: TypeRep bv1 -> TypeRep bv2 -> {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term t)
DBVToSignedTerm ::
forall ubv sbv (n :: Nat).
!(TypeRep (ubv n), Id) ->
Description (Term (sbv n))
DBVToUnsignedTerm ::
forall sbv ubv (n :: Nat).
!(TypeRep (sbv n), Id) ->
Description (Term (ubv n))
DBVSelectTerm ::
forall bv (n :: Nat) (w :: Nat) (ix :: Nat).
!(TypeRep ix) ->
!(TypeRep (bv n), Id) ->
Description (Term (bv w))
DBVExtendTerm ::
forall bv (l :: Nat) (r :: Nat).
!Bool ->
!(TypeRep r) ->
{-# UNPACK #-} !(TypeRep (bv l), Id) ->
Description (Term (bv r))
DTabularFunApplyTerm ::
{-# UNPACK #-} !(TypeRep (a =-> b), Id) ->
{-# UNPACK #-} !(TypeRep a, Id) ->
Description (Term b)
DGeneralFunApplyTerm ::
{-# UNPACK #-} !(TypeRep (a --> b), Id) ->
{-# UNPACK #-} !(TypeRep a, Id) ->
Description (Term b)
DDivIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DModIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DQuotIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DRemIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DDivBoundedIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DModBoundedIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DQuotBoundedIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
DRemBoundedIntegralTerm :: {-# UNPACK #-} !Id -> {-# UNPACK #-} !Id -> Description (Term a)
describe (UConTerm v) = DConTerm v
describe ((USymTerm name) :: UTerm t) = DSymTerm @t name
describe ((UUnaryTerm (tag :: tagt) (tm :: Term arg)) :: UTerm t) =
DUnaryTerm (typeRep, tag) (typeRep :: TypeRep arg, identity tm)
describe ((UBinaryTerm (tag :: tagt) (tm1 :: Term arg1) (tm2 :: Term arg2)) :: UTerm t) =
DBinaryTerm @tagt @arg1 @arg2 @t (typeRep, tag) (typeRep, identity tm1) (typeRep, identity tm2)
describe ((UTernaryTerm (tag :: tagt) (tm1 :: Term arg1) (tm2 :: Term arg2) (tm3 :: Term arg3)) :: UTerm t) =
DTernaryTerm @tagt @arg1 @arg2 @arg3 @t
(typeRep, tag)
(typeRep, identity tm1)
(typeRep, identity tm2)
(typeRep, identity tm3)
describe (UNotTerm arg) = DNotTerm (identity arg)
describe (UOrTerm arg1 arg2) = DOrTerm (identity arg1) (identity arg2)
describe (UAndTerm arg1 arg2) = DAndTerm (identity arg1) (identity arg2)
describe (UEqvTerm (arg1 :: Term arg) arg2) = DEqvTerm (typeRep :: TypeRep arg) (identity arg1) (identity arg2)
describe (UITETerm cond (l :: Term arg) r) = DITETerm (identity cond) (identity l) (identity r)
describe (UAddNumTerm arg1 arg2) = DAddNumTerm (identity arg1) (identity arg2)
describe (UUMinusNumTerm arg) = DUMinusNumTerm (identity arg)
describe (UTimesNumTerm arg1 arg2) = DTimesNumTerm (identity arg1) (identity arg2)
describe (UAbsNumTerm arg) = DAbsNumTerm (identity arg)
describe (USignumNumTerm arg) = DSignumNumTerm (identity arg)
describe (ULTNumTerm (arg1 :: arg) arg2) = DLTNumTerm (typeRep :: TypeRep arg) (identity arg1) (identity arg2)
describe (ULENumTerm (arg1 :: arg) arg2) = DLENumTerm (typeRep :: TypeRep arg) (identity arg1) (identity arg2)
describe (UAndBitsTerm arg1 arg2) = DAndBitsTerm (identity arg1) (identity arg2)
describe (UOrBitsTerm arg1 arg2) = DOrBitsTerm (identity arg1) (identity arg2)
describe (UXorBitsTerm arg1 arg2) = DXorBitsTerm (identity arg1) (identity arg2)
describe (UComplementBitsTerm arg) = DComplementBitsTerm (identity arg)
describe (UShiftBitsTerm arg n) = DShiftBitsTerm (identity arg) n
describe (URotateBitsTerm arg n) = DRotateBitsTerm (identity arg) n
describe (UBVToSignedTerm (arg :: Term bv)) = DBVToSignedTerm (typeRep :: TypeRep bv, identity arg)
describe (UBVToUnsignedTerm (arg :: Term bv)) = DBVToSignedTerm (typeRep :: TypeRep bv, identity arg)
describe (UBVConcatTerm (arg1 :: bv1) (arg2 :: bv2)) =
DBVConcatTerm (typeRep :: TypeRep bv1) (typeRep :: TypeRep bv2) (identity arg1) (identity arg2)
describe (UBVSelectTerm (ix :: TypeRep ix) _ (arg :: Term arg)) =
DBVSelectTerm ix (typeRep :: TypeRep arg, identity arg)
describe (UBVExtendTerm signed (n :: TypeRep n) (arg :: Term arg)) =
DBVExtendTerm signed n (typeRep :: TypeRep arg, identity arg)
describe (UTabularFunApplyTerm (func :: Term f) (arg :: Term a)) =
DTabularFunApplyTerm (typeRep :: TypeRep f, identity func) (typeRep :: TypeRep a, identity arg)
describe (UGeneralFunApplyTerm (func :: Term f) (arg :: Term a)) =
DGeneralFunApplyTerm (typeRep :: TypeRep f, identity func) (typeRep :: TypeRep a, identity arg)
describe (UDivIntegralTerm arg1 arg2) = DDivIntegralTerm (identity arg1) (identity arg2)
describe (UModIntegralTerm arg1 arg2) = DModIntegralTerm (identity arg1) (identity arg2)
describe (UQuotIntegralTerm arg1 arg2) = DRemIntegralTerm (identity arg1) (identity arg2)
describe (URemIntegralTerm arg1 arg2) = DQuotIntegralTerm (identity arg1) (identity arg2)
describe (UDivBoundedIntegralTerm arg1 arg2) = DDivBoundedIntegralTerm (identity arg1) (identity arg2)
describe (UModBoundedIntegralTerm arg1 arg2) = DModBoundedIntegralTerm (identity arg1) (identity arg2)
describe (UQuotBoundedIntegralTerm arg1 arg2) = DRemBoundedIntegralTerm (identity arg1) (identity arg2)
describe (URemBoundedIntegralTerm arg1 arg2) = DQuotBoundedIntegralTerm (identity arg1) (identity arg2)
identify i = go
where
go (UConTerm v) = ConTerm i v
go (USymTerm v) = SymTerm i v
go (UUnaryTerm tag tm) = UnaryTerm i tag tm
go (UBinaryTerm tag tm1 tm2) = BinaryTerm i tag tm1 tm2
go (UTernaryTerm tag tm1 tm2 tm3) = TernaryTerm i tag tm1 tm2 tm3
go (UNotTerm arg) = NotTerm i arg
go (UOrTerm arg1 arg2) = OrTerm i arg1 arg2
go (UAndTerm arg1 arg2) = AndTerm i arg1 arg2
go (UEqvTerm arg1 arg2) = EqvTerm i arg1 arg2
go (UITETerm cond l r) = ITETerm i cond l r
go (UAddNumTerm arg1 arg2) = AddNumTerm i arg1 arg2
go (UUMinusNumTerm arg) = UMinusNumTerm i arg
go (UTimesNumTerm arg1 arg2) = TimesNumTerm i arg1 arg2
go (UAbsNumTerm arg) = AbsNumTerm i arg
go (USignumNumTerm arg) = SignumNumTerm i arg
go (ULTNumTerm arg1 arg2) = LTNumTerm i arg1 arg2
go (ULENumTerm arg1 arg2) = LENumTerm i arg1 arg2
go (UAndBitsTerm arg1 arg2) = AndBitsTerm i arg1 arg2
go (UOrBitsTerm arg1 arg2) = OrBitsTerm i arg1 arg2
go (UXorBitsTerm arg1 arg2) = XorBitsTerm i arg1 arg2
go (UComplementBitsTerm arg) = ComplementBitsTerm i arg
go (UShiftBitsTerm arg n) = ShiftBitsTerm i arg n
go (URotateBitsTerm arg n) = RotateBitsTerm i arg n
go (UBVToSignedTerm arg) = BVToSignedTerm i arg
go (UBVToUnsignedTerm arg) = BVToUnsignedTerm i arg
go (UBVConcatTerm arg1 arg2) = BVConcatTerm i arg1 arg2
go (UBVSelectTerm ix w arg) = BVSelectTerm i ix w arg
go (UBVExtendTerm signed n arg) = BVExtendTerm i signed n arg
go (UTabularFunApplyTerm func arg) = TabularFunApplyTerm i func arg
go (UGeneralFunApplyTerm func arg) = GeneralFunApplyTerm i func arg
go (UDivIntegralTerm arg1 arg2) = DivIntegralTerm i arg1 arg2
go (UModIntegralTerm arg1 arg2) = ModIntegralTerm i arg1 arg2
go (UQuotIntegralTerm arg1 arg2) = QuotIntegralTerm i arg1 arg2
go (URemIntegralTerm arg1 arg2) = RemIntegralTerm i arg1 arg2
go (UDivBoundedIntegralTerm arg1 arg2) = DivBoundedIntegralTerm i arg1 arg2
go (UModBoundedIntegralTerm arg1 arg2) = ModBoundedIntegralTerm i arg1 arg2
go (UQuotBoundedIntegralTerm arg1 arg2) = QuotBoundedIntegralTerm i arg1 arg2
go (URemBoundedIntegralTerm arg1 arg2) = RemBoundedIntegralTerm i arg1 arg2
cache = termCache
instance (SupportedPrim t) => Eq (Description (Term t)) where
DConTerm (l :: tyl) == DConTerm (r :: tyr) = cast @tyl @tyr l == Just r
DSymTerm ls == DSymTerm rs = ls == rs
DUnaryTerm (tagl :: tagl) li == DUnaryTerm (tagr :: tagr) ri = eqHeteroTag tagl tagr && eqTypedId li ri
DBinaryTerm (tagl :: tagl) li1 li2 == DBinaryTerm (tagr :: tagr) ri1 ri2 =
eqHeteroTag tagl tagr && eqTypedId li1 ri1 && eqTypedId li2 ri2
DTernaryTerm (tagl :: tagl) li1 li2 li3 == DTernaryTerm (tagr :: tagr) ri1 ri2 ri3 =
eqHeteroTag tagl tagr && eqTypedId li1 ri1 && eqTypedId li2 ri2 && eqTypedId li3 ri3
DNotTerm li == DNotTerm ri = li == ri
DOrTerm li1 li2 == DOrTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DAndTerm li1 li2 == DAndTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DEqvTerm lrep li1 li2 == DEqvTerm rrep ri1 ri2 = eqTypeRepBool lrep rrep && li1 == ri1 && li2 == ri2
DITETerm lc li1 li2 == DITETerm rc ri1 ri2 = lc == rc && li1 == ri1 && li2 == ri2
DAddNumTerm li1 li2 == DAddNumTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DUMinusNumTerm li == DUMinusNumTerm ri = li == ri
DTimesNumTerm li1 li2 == DTimesNumTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DAbsNumTerm li == DAbsNumTerm ri = li == ri
DSignumNumTerm li == DSignumNumTerm ri = li == ri
DLTNumTerm lrep li1 li2 == DLTNumTerm rrep ri1 ri2 = eqTypeRepBool lrep rrep && li1 == ri1 && li2 == ri2
DLENumTerm lrep li1 li2 == DLENumTerm rrep ri1 ri2 = eqTypeRepBool lrep rrep && li1 == ri1 && li2 == ri2
DAndBitsTerm li1 li2 == DAndBitsTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DOrBitsTerm li1 li2 == DOrBitsTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DXorBitsTerm li1 li2 == DXorBitsTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DComplementBitsTerm li == DComplementBitsTerm ri = li == ri
DShiftBitsTerm li ln == DShiftBitsTerm ri rn = li == ri && ln == rn
DRotateBitsTerm li ln == DRotateBitsTerm ri rn = li == ri && ln == rn
DBVToSignedTerm li == DBVToSignedTerm ri = eqTypedId li ri
DBVToUnsignedTerm li == DBVToUnsignedTerm ri = eqTypedId li ri
DBVConcatTerm lrep1 lrep2 li1 li2 == DBVConcatTerm rrep1 rrep2 ri1 ri2 =
eqTypeRepBool lrep1 rrep1 && eqTypeRepBool lrep2 rrep2 && li1 == ri1 && li2 == ri2
DBVSelectTerm lix li == DBVSelectTerm rix ri =
eqTypeRepBool lix rix && eqTypedId li ri
DBVExtendTerm lIsSigned ln li == DBVExtendTerm rIsSigned rn ri =
lIsSigned == rIsSigned
&& eqTypeRepBool ln rn
&& eqTypedId li ri
DTabularFunApplyTerm lf li == DTabularFunApplyTerm rf ri = eqTypedId lf rf && eqTypedId li ri
DGeneralFunApplyTerm lf li == DGeneralFunApplyTerm rf ri = eqTypedId lf rf && eqTypedId li ri
DDivIntegralTerm li1 li2 == DDivIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DModIntegralTerm li1 li2 == DModIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DQuotIntegralTerm li1 li2 == DQuotIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DRemIntegralTerm li1 li2 == DRemIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DDivBoundedIntegralTerm li1 li2 == DDivBoundedIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DModBoundedIntegralTerm li1 li2 == DModBoundedIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DQuotBoundedIntegralTerm li1 li2 == DQuotBoundedIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
DRemBoundedIntegralTerm li1 li2 == DRemBoundedIntegralTerm ri1 ri2 = li1 == ri1 && li2 == ri2
_ == _ = False
instance (SupportedPrim t) => Hashable (Description (Term t)) where
hashWithSalt s (DConTerm c) = s `hashWithSalt` (0 :: Int) `hashWithSalt` c
hashWithSalt s (DSymTerm name) = s `hashWithSalt` (1 :: Int) `hashWithSalt` name
hashWithSalt s (DUnaryTerm tag id1) = s `hashWithSalt` (2 :: Int) `hashWithSalt` tag `hashWithSalt` id1
hashWithSalt s (DBinaryTerm tag id1 id2) =
s `hashWithSalt` (3 :: Int) `hashWithSalt` tag `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DTernaryTerm tag id1 id2 id3) =
s `hashWithSalt` (4 :: Int) `hashWithSalt` tag `hashWithSalt` id1 `hashWithSalt` id2 `hashWithSalt` id3
hashWithSalt s (DNotTerm id1) = s `hashWithSalt` (5 :: Int) `hashWithSalt` id1
hashWithSalt s (DOrTerm id1 id2) = s `hashWithSalt` (6 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DAndTerm id1 id2) = s `hashWithSalt` (7 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DEqvTerm rep id1 id2) =
s
`hashWithSalt` (8 :: Int)
`hashWithSalt` rep
`hashWithSalt` id1
`hashWithSalt` id2
hashWithSalt s (DITETerm idc id1 id2) =
s
`hashWithSalt` (9 :: Int)
`hashWithSalt` idc
`hashWithSalt` id1
`hashWithSalt` id2
hashWithSalt s (DAddNumTerm id1 id2) = s `hashWithSalt` (10 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DUMinusNumTerm id1) = s `hashWithSalt` (11 :: Int) `hashWithSalt` id1
hashWithSalt s (DTimesNumTerm id1 id2) = s `hashWithSalt` (12 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DAbsNumTerm id1) = s `hashWithSalt` (13 :: Int) `hashWithSalt` id1
hashWithSalt s (DSignumNumTerm id1) = s `hashWithSalt` (14 :: Int) `hashWithSalt` id1
hashWithSalt s (DLTNumTerm rep id1 id2) =
s `hashWithSalt` (15 :: Int) `hashWithSalt` rep `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DLENumTerm rep id1 id2) =
s `hashWithSalt` (16 :: Int) `hashWithSalt` rep `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DAndBitsTerm id1 id2) = s `hashWithSalt` (17 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DOrBitsTerm id1 id2) = s `hashWithSalt` (18 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DXorBitsTerm id1 id2) = s `hashWithSalt` (19 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DComplementBitsTerm id1) = s `hashWithSalt` (20 :: Int) `hashWithSalt` id1
hashWithSalt s (DShiftBitsTerm id1 n) = s `hashWithSalt` (21 :: Int) `hashWithSalt` id1 `hashWithSalt` n
hashWithSalt s (DRotateBitsTerm id1 n) = s `hashWithSalt` (22 :: Int) `hashWithSalt` id1 `hashWithSalt` n
hashWithSalt s (DBVToSignedTerm id) = s `hashWithSalt` (23 :: Int) `hashWithSalt` id
hashWithSalt s (DBVToUnsignedTerm id) = s `hashWithSalt` (24 :: Int) `hashWithSalt` id
hashWithSalt s (DBVConcatTerm rep1 rep2 id1 id2) =
s `hashWithSalt` (25 :: Int) `hashWithSalt` rep1 `hashWithSalt` rep2 `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DBVSelectTerm ix id1) = s `hashWithSalt` (26 :: Int) `hashWithSalt` ix `hashWithSalt` id1
hashWithSalt s (DBVExtendTerm signed n id1) =
s
`hashWithSalt` (27 :: Int)
`hashWithSalt` signed
`hashWithSalt` n
`hashWithSalt` id1
hashWithSalt s (DTabularFunApplyTerm id1 id2) = s `hashWithSalt` (28 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DGeneralFunApplyTerm id1 id2) = s `hashWithSalt` (29 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DDivIntegralTerm id1 id2) = s `hashWithSalt` (30 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DModIntegralTerm id1 id2) = s `hashWithSalt` (31 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DQuotIntegralTerm id1 id2) = s `hashWithSalt` (32 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DRemIntegralTerm id1 id2) = s `hashWithSalt` (33 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DDivBoundedIntegralTerm id1 id2) = s `hashWithSalt` (34 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DModBoundedIntegralTerm id1 id2) = s `hashWithSalt` (35 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DQuotBoundedIntegralTerm id1 id2) = s `hashWithSalt` (36 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
hashWithSalt s (DRemBoundedIntegralTerm id1 id2) = s `hashWithSalt` (37 :: Int) `hashWithSalt` id1 `hashWithSalt` id2
-- Basic Bool
defaultValueForBool :: Bool
defaultValueForBool = False
defaultValueForBoolDyn :: ModelValue
defaultValueForBoolDyn = toModelValue defaultValueForBool
instance SupportedPrim Bool where
pformatCon True = "true"
pformatCon False = "false"
defaultValue = defaultValueForBool
defaultValueDynamic _ = defaultValueForBoolDyn
defaultValueForInteger :: Integer
defaultValueForInteger = 0
defaultValueForIntegerDyn :: ModelValue
defaultValueForIntegerDyn = toModelValue defaultValueForInteger
-- Basic Integer
instance SupportedPrim Integer where
pformatCon = show
defaultValue = defaultValueForInteger
defaultValueDynamic _ = defaultValueForIntegerDyn
-- Signed BV
instance (KnownNat w, 1 <= w) => SupportedPrim (IntN w) where
type PrimConstraint (IntN w) = (KnownNat w, 1 <= w)
pformatCon = show
defaultValue = 0
-- Unsigned BV
instance (KnownNat w, 1 <= w) => SupportedPrim (WordN w) where
type PrimConstraint (WordN w) = (KnownNat w, 1 <= w)
pformatCon = show
defaultValue = 0
-- | General symbolic function type. Use the '#' operator to apply the function.
-- Note that this function should be applied to symbolic values only. It is by
-- itself already a symbolic value, but can be considered partially concrete
-- as the function body is specified. Use 'Grisette.IR.SymPrim.Data.SymPrim.-~>' for uninterpreted general
-- symbolic functions.
--
-- The result would be partially evaluated.
--
-- >>> :set -XOverloadedStrings
-- >>> :set -XTypeOperators
-- >>> let f = ("x" :: TypedSymbol Integer) --> ("x" + 1 + "y" :: SymInteger) :: Integer --> Integer
-- >>> f # 1 -- 1 has the type SymInteger
-- (+ 2 y)
-- >>> f # "a" -- "a" has the type SymInteger
-- (+ 1 (+ a y))
data (-->) a b where
GeneralFun :: (SupportedPrim a, SupportedPrim b) => TypedSymbol a -> Term b -> a --> b
instance (LinkedRep a sa, LinkedRep b sb) => Function (a --> b) where
type Arg (a --> b) = SymType a
type Ret (a --> b) = SymType b
(GeneralFun s t) # x = wrapTerm $ substTerm s (underlyingTerm x) t
{-
pattern GeneralFun :: () => (SupportedPrim a, SupportedPrim b) => TypedSymbol a -> Term b -> a --> b
pattern GeneralFun arg v <- GeneralFun arg v
{-# COMPLETE GeneralFun #-}
-}
infixr 0 -->
buildGeneralFun :: () => (SupportedPrim a, SupportedPrim b) => TypedSymbol a -> Term b -> a --> b
buildGeneralFun arg v = GeneralFun newarg (substTerm arg (symTerm newarg) v)
where
newarg = WithInfo arg ARG
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)
instance Eq (a --> b) where
GeneralFun sym1 tm1 == GeneralFun sym2 tm2 = sym1 == sym2 && tm1 == tm2
instance Show (a --> b) where
show (GeneralFun sym tm) = "\\(" ++ show sym ++ ") -> " ++ pformat tm
instance Lift (a --> b) where
liftTyped (GeneralFun sym tm) = [||GeneralFun sym tm||]
instance Hashable (a --> b) where
s `hashWithSalt` (GeneralFun sym tm) = s `hashWithSalt` sym `hashWithSalt` tm
instance NFData (a --> b) where
rnf (GeneralFun sym tm) = rnf sym `seq` rnf tm
instance (SupportedPrim a, SupportedPrim b) => SupportedPrim (a --> b) where
type PrimConstraint (a --> b) = (SupportedPrim a, SupportedPrim b)
defaultValue = buildGeneralFun (SimpleSymbol "a") (conTerm defaultValue)