packages feed

hasmtlib 1.0.2 → 1.1.0

raw patch · 12 files changed

+471/−248 lines, 12 filesdep +dependent-mapdep +somePVP ok

version bump matches the API change (PVP)

Dependencies added: dependent-map, some

API changes (from Hackage documentation)

- Language.Hasmtlib.Internal.Parser: fromSomeList :: [SomeKnownSMTSort SMTVarSol] -> Solution
- Language.Hasmtlib.Internal.Parser: parseAnyBvUpToLength :: Natural -> Parser (SomeKnownSMTSort SMTVarSol)
- Language.Hasmtlib.Internal.Parser: parseSol :: forall t. KnownSMTSort t => Parser (SMTVarSol t)
- Language.Hasmtlib.Type.Expr: [SomeKnownSMTSort] :: forall (t :: SMTSort) f. KnownSMTSort t => f t -> SomeKnownSMTSort f
- Language.Hasmtlib.Type.Expr: data SomeKnownSMTSort f
- Language.Hasmtlib.Type.Solution: instance GHC.Classes.Eq (Language.Hasmtlib.Type.Solution.SMTVarSol t)
- Language.Hasmtlib.Type.Solution: instance GHC.Classes.Ord (Language.Hasmtlib.Type.Solution.SMTVarSol t)
+ Language.Hasmtlib.Internal.Parser: constArray :: forall k v. (KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Proxy v -> Parser (ConstArray (HaskellType k) (HaskellType v))
+ Language.Hasmtlib.Internal.Parser: constantExpr :: forall t. KnownSMTSort t => Parser (Expr t)
+ Language.Hasmtlib.Internal.Parser: parseExpr' :: forall prxy t. KnownSMTSort t => prxy t -> Parser (Expr t)
+ Language.Hasmtlib.Internal.Parser: parseSelect :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Parser (Expr v)
+ Language.Hasmtlib.Internal.Parser: parseSomeArraySort :: Parser (SomeKnownOrdSMTSort SSMTSort)
+ Language.Hasmtlib.Internal.Parser: parseSomeBitVecSort :: Parser (SomeKnownOrdSMTSort SSMTSort)
+ Language.Hasmtlib.Internal.Parser: parseSomeSort :: Parser (SomeKnownOrdSMTSort SSMTSort)
+ Language.Hasmtlib.Internal.Parser: parseStore :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Parser (Expr (ArraySort k v))
+ Language.Hasmtlib.Type.ArrayMap: ConstArray :: v -> Map k v -> ConstArray k v
+ Language.Hasmtlib.Type.ArrayMap: [_arrConst] :: ConstArray k v -> v
+ Language.Hasmtlib.Type.ArrayMap: [_stored] :: ConstArray k v -> Map k v
+ Language.Hasmtlib.Type.ArrayMap: arrConst :: forall k_ajbA v_ajbB. Lens' (ConstArray k_ajbA v_ajbB) v_ajbB
+ Language.Hasmtlib.Type.ArrayMap: arrSelect :: ArrayMap f k v => f k v -> k -> v
+ Language.Hasmtlib.Type.ArrayMap: arrStore :: ArrayMap f k v => f k v -> k -> v -> f k v
+ Language.Hasmtlib.Type.ArrayMap: asConst :: forall f k v. ArrayMap f k v => v -> f k v
+ Language.Hasmtlib.Type.ArrayMap: asConst' :: ArrayMap f k v => Proxy f -> Proxy k -> v -> f k v
+ Language.Hasmtlib.Type.ArrayMap: class ArrayMap f k v
+ Language.Hasmtlib.Type.ArrayMap: data ConstArray k v
+ Language.Hasmtlib.Type.ArrayMap: instance (GHC.Classes.Eq v, GHC.Classes.Eq k) => GHC.Classes.Eq (Language.Hasmtlib.Type.ArrayMap.ConstArray k v)
+ Language.Hasmtlib.Type.ArrayMap: instance (GHC.Classes.Ord v, GHC.Classes.Ord k) => GHC.Classes.Ord (Language.Hasmtlib.Type.ArrayMap.ConstArray k v)
+ Language.Hasmtlib.Type.ArrayMap: instance (GHC.Show.Show v, GHC.Show.Show k) => GHC.Show.Show (Language.Hasmtlib.Type.ArrayMap.ConstArray k v)
+ Language.Hasmtlib.Type.ArrayMap: instance Data.Foldable.Foldable (Language.Hasmtlib.Type.ArrayMap.ConstArray k)
+ Language.Hasmtlib.Type.ArrayMap: instance Data.Traversable.Traversable (Language.Hasmtlib.Type.ArrayMap.ConstArray k)
+ Language.Hasmtlib.Type.ArrayMap: instance GHC.Base.Functor (Language.Hasmtlib.Type.ArrayMap.ConstArray k)
+ Language.Hasmtlib.Type.ArrayMap: instance GHC.Classes.Ord k => Language.Hasmtlib.Type.ArrayMap.ArrayMap Language.Hasmtlib.Type.ArrayMap.ConstArray k v
+ Language.Hasmtlib.Type.ArrayMap: stored :: forall k_ajbA v_ajbB k_akE1. Lens (ConstArray k_ajbA v_ajbB) (ConstArray k_akE1 v_ajbB) (Map k_ajbA v_ajbB) (Map k_akE1 v_ajbB)
+ Language.Hasmtlib.Type.ArrayMap: viewConst :: ArrayMap f k v => f k v -> v
+ Language.Hasmtlib.Type.Expr: ArraySort :: SMTSort -> SMTSort -> SMTSort
+ Language.Hasmtlib.Type.Expr: [ArrayValue] :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => HaskellType (ArraySort k v) -> Value (ArraySort k v)
+ Language.Hasmtlib.Type.Expr: [SArraySort] :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Proxy v -> SSMTSort (ArraySort k v)
+ Language.Hasmtlib.Type.Expr: [SomeSMTSort] :: forall cs f (t :: SMTSort). AllC cs t => f t -> SomeSMTSort cs f
+ Language.Hasmtlib.Type.Expr: data SomeSMTSort cs f
+ Language.Hasmtlib.Type.Expr: select :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v
+ Language.Hasmtlib.Type.Expr: sortSing' :: forall prxy t. KnownSMTSort t => prxy t -> SSMTSort t
+ Language.Hasmtlib.Type.Expr: store :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v -> Expr (ArraySort k v)
+ Language.Hasmtlib.Type.Expr: type SomeKnownSMTSort f = SomeSMTSort '[KnownSMTSort] f
+ Language.Hasmtlib.Type.Expr: varId :: forall t_anxP t_anER. Iso (SMTVar t_anxP) (SMTVar t_anER) Int Int
+ Language.Hasmtlib.Type.Solution: IntValueMap :: IntMap (Value t) -> IntValueMap t
+ Language.Hasmtlib.Type.Solution: class Ord (HaskellType t) => OrdHaskellType t
+ Language.Hasmtlib.Type.Solution: fromSomeVarSols :: [SomeKnownOrdSMTSort SMTVarSol] -> Solution
+ Language.Hasmtlib.Type.Solution: instance GHC.Base.Monoid (Language.Hasmtlib.Type.Solution.IntValueMap t)
+ Language.Hasmtlib.Type.Solution: instance GHC.Base.Semigroup (Language.Hasmtlib.Type.Solution.IntValueMap t)
+ Language.Hasmtlib.Type.Solution: instance GHC.Classes.Ord (Language.Hasmtlib.Internal.Expr.HaskellType t) => Language.Hasmtlib.Type.Solution.OrdHaskellType t
+ Language.Hasmtlib.Type.Solution: instance GHC.Show.Show (Language.Hasmtlib.Type.Solution.IntValueMap t)
+ Language.Hasmtlib.Type.Solution: newtype IntValueMap t
+ Language.Hasmtlib.Type.Solution: type SomeKnownOrdSMTSort f = SomeSMTSort '[KnownSMTSort, OrdHaskellType] f
- Language.Hasmtlib.Internal.Parser: constant :: forall t. KnownSMTSort t => Parser (Expr t)
+ Language.Hasmtlib.Internal.Parser: constant :: forall t. KnownSMTSort t => Parser (HaskellType t)
- Language.Hasmtlib.Internal.Parser: parseSomeSol :: Parser (SomeKnownSMTSort SMTVarSol)
+ Language.Hasmtlib.Internal.Parser: parseSomeSol :: Parser (SomeKnownOrdSMTSort SMTVarSol)
- Language.Hasmtlib.Type.Solution: solVal :: forall t_aDr6. Lens' (SMTVarSol t_aDr6) (Value t_aDr6)
+ Language.Hasmtlib.Type.Solution: solVal :: forall t_aGNU. Lens' (SMTVarSol t_aGNU) (Value t_aGNU)
- Language.Hasmtlib.Type.Solution: solVar :: forall t_aDr6. Lens' (SMTVarSol t_aDr6) (SMTVar t_aDr6)
+ Language.Hasmtlib.Type.Solution: solVar :: forall t_aGNU. Lens' (SMTVarSol t_aGNU) (SMTVar t_aGNU)
- Language.Hasmtlib.Type.Solution: type Solution = IntMap (SomeKnownSMTSort SMTVarSol)
+ Language.Hasmtlib.Type.Solution: type Solution = DMap SSMTSort IntValueMap

Files

hasmtlib.cabal view
@@ -1,7 +1,7 @@ cabal-version:         3.0  name:                  hasmtlib-version:               1.0.2+version:               1.1.0 synopsis:              A monad for interfacing with external SMT solvers description:           Hasmtlib is a library for generating SMTLib2-problems using a monad.   It takes care of encoding your problem, marshaling the data to an external solver and parsing and interpreting the result into Haskell types.@@ -47,6 +47,7 @@                      , Language.Hasmtlib.Type.Solution                      , Language.Hasmtlib.Type.Solver                      , Language.Hasmtlib.Type.Option+                     , Language.Hasmtlib.Type.ArrayMap    other-modules:       Language.Hasmtlib.Internal.Expr                      , Language.Hasmtlib.Internal.Expr.Num@@ -55,12 +56,14 @@                      , base                         >= 4.17.2 && < 5                      , bytestring                   >= 0.11.5 && < 1                      , containers                   >= 0.6.7  && < 1+                     , dependent-map                >= 0.4    && < 1                      , mtl                          >= 2.2.2  && < 3                      , text                         >= 2.0.2  && < 3                      , data-default                 >= 0.7.1  && < 1                      , lens                         >= 5      && < 6                      , smtlib-backends              >= 0.4    && < 1                      , smtlib-backends-process      >= 0.3    && < 1+                     , some                         >= 1.0.6  && < 1.1                      , utf8-string                  >= 1.0.2  && < 2                      , bitvec                       >= 1.1.5  && < 2                      , finite-typelits              >= 0.1.0  && < 1
src/Language/Hasmtlib.hs view
@@ -7,6 +7,7 @@   , module Language.Hasmtlib.Type.Solver   , module Language.Hasmtlib.Type.Option   , module Language.Hasmtlib.Type.Solution+  , module Language.Hasmtlib.Type.ArrayMap   , module Language.Hasmtlib.Integraled   , module Language.Hasmtlib.Iteable   , module Language.Hasmtlib.Boolean@@ -29,6 +30,7 @@ import Language.Hasmtlib.Type.Solver import Language.Hasmtlib.Type.Option import Language.Hasmtlib.Type.Solution+import Language.Hasmtlib.Type.ArrayMap import Language.Hasmtlib.Integraled import Language.Hasmtlib.Iteable import Language.Hasmtlib.Boolean
src/Language/Hasmtlib/Codec.hs view
@@ -8,17 +8,16 @@ import Language.Hasmtlib.Internal.Bitvec import Language.Hasmtlib.Internal.Expr import Language.Hasmtlib.Type.Solution+import Language.Hasmtlib.Type.ArrayMap import Language.Hasmtlib.Boolean import Data.Kind import Data.Coerce-import Data.Proxy import Data.Map (Map) import Data.Sequence (Seq) import Data.IntMap as IM+import Data.Dependent.Map as DMap import Data.Tree (Tree)-import qualified Data.Vector.Unboxed.Sized as V import Control.Monad-import GHC.TypeNats  -- | Compute the default 'Decoded' 'Type' for every functor-wrapper. --   Useful for instances using default signatures.@@ -43,57 +42,42 @@ -- | Decode and evaluate expressions instance KnownSMTSort t => Codec (Expr t) where   type Decoded (Expr t) = HaskellType t-  decode sol (Var var)    = do-    someSol <- IM.lookup (coerce var) sol-    case sortSing @t of-      SIntSort   -> case someSol of-                    SomeKnownSMTSort (SMTVarSol _ (IntValue v))  -> Just v-                    _                                            -> Nothing-      SRealSort  -> case someSol of-                    SomeKnownSMTSort (SMTVarSol _ (RealValue v)) -> Just v-                    _                                            -> Nothing-      SBoolSort  -> case someSol of-                    SomeKnownSMTSort (SMTVarSol _ (BoolValue v)) -> Just v-                    _                                            -> Nothing-      SBvSort p  -> case someSol of-                    SomeKnownSMTSort (SMTVarSol _ (BvValue v))   -> goN p v-                    _                                            -> Nothing-        where-          goN :: forall n m. KnownNat n => Proxy n -> Bitvec m -> Maybe (Bitvec n)-          goN _ = coerce . V.toSized @n . V.fromSized . coerce--  decode _ (Constant v) = Just $ unwrapValue v-  decode sol (Plus x y) = liftA2 (+)   (decode sol x) (decode sol y)-  decode sol (Neg x)    = fmap negate  (decode sol x)-  decode sol (Mul x y)  = liftA2 (*)   (decode sol x) (decode sol y)-  decode sol (Abs x)    = fmap abs     (decode sol x)-  decode sol (Mod x y)  = liftA2 mod   (decode sol x) (decode sol y)-  decode sol (IDiv x y) = liftA2 div   (decode sol x) (decode sol y)-  decode sol (Div x y)  = liftA2 (/)   (decode sol x) (decode sol y)-  decode sol (LTH x y)  = liftA2 (<)   (decode sol x) (decode sol y)-  decode sol (LTHE x y) = liftA2 (<=)  (decode sol x) (decode sol y)-  decode sol (EQU x y)  = liftA2 (==)  (decode sol x) (decode sol y)-  decode sol (Distinct x y)  = liftA2 (/=)  (decode sol x) (decode sol y)-  decode sol (GTHE x y) = liftA2 (>=)  (decode sol x) (decode sol y)-  decode sol (GTH x y)  = liftA2 (>)   (decode sol x) (decode sol y)-  decode sol (Not x)    = fmap   not  (decode sol x)-  decode sol (And x y)  = liftA2 (&&) (decode sol x) (decode sol y)-  decode sol (Or x y)   = liftA2 (||) (decode sol x) (decode sol y)-  decode sol (Impl x y) = liftA2 (==>) (decode sol x) (decode sol y)-  decode sol (Xor x y)  = liftA2 xor   (decode sol x) (decode sol y)-  decode _ Pi           = Just pi-  decode sol (Sqrt x)   = fmap sqrt  (decode sol x)-  decode sol (Exp x)    = fmap exp   (decode sol x)-  decode sol (Sin x)    = fmap sin   (decode sol x)-  decode sol (Cos x)    = fmap cos   (decode sol x)-  decode sol (Tan x)    = fmap tan   (decode sol x)-  decode sol (Asin x)   = fmap asin  (decode sol x)-  decode sol (Acos x)   = fmap acos  (decode sol x)-  decode sol (Atan x)   = fmap atan  (decode sol x)-  decode sol (ToReal x) = fmap realToFrac (decode sol x)-  decode sol (ToInt x)  = fmap truncate   (decode sol x)-  decode sol (IsInt x)  = fmap ((0 ==) . snd . properFraction) (decode sol x)-  decode sol (Ite p t f) = liftM3 (\p' t' f' -> if p' then t' else f') (decode sol p) (decode sol t) (decode sol f) +  decode sol (Var var)  = do+    (IntValueMap m) <- DMap.lookup (sortSing @t) sol+    val <- IM.lookup (coerce var) m+    return $ unwrapValue val+  decode _ (Constant v)         = Just $ unwrapValue v+  decode sol (Plus x y)         = liftA2 (+)   (decode sol x) (decode sol y)+  decode sol (Neg x)            = fmap negate  (decode sol x)+  decode sol (Mul x y)          = liftA2 (*)   (decode sol x) (decode sol y)+  decode sol (Abs x)            = fmap abs     (decode sol x)+  decode sol (Mod x y)          = liftA2 mod   (decode sol x) (decode sol y)+  decode sol (IDiv x y)         = liftA2 div   (decode sol x) (decode sol y)+  decode sol (Div x y)          = liftA2 (/)   (decode sol x) (decode sol y)+  decode sol (LTH x y)          = liftA2 (<)   (decode sol x) (decode sol y)+  decode sol (LTHE x y)         = liftA2 (<=)  (decode sol x) (decode sol y)+  decode sol (EQU x y)          = liftA2 (==)  (decode sol x) (decode sol y)+  decode sol (Distinct x y)     = liftA2 (/=)  (decode sol x) (decode sol y)+  decode sol (GTHE x y)         = liftA2 (>=)  (decode sol x) (decode sol y)+  decode sol (GTH x y)          = liftA2 (>)   (decode sol x) (decode sol y)+  decode sol (Not x)            = fmap   not  (decode sol x)+  decode sol (And x y)          = liftA2 (&&) (decode sol x) (decode sol y)+  decode sol (Or x y)           = liftA2 (||) (decode sol x) (decode sol y)+  decode sol (Impl x y)         = liftA2 (==>) (decode sol x) (decode sol y)+  decode sol (Xor x y)          = liftA2 xor   (decode sol x) (decode sol y)+  decode _ Pi                   = Just pi+  decode sol (Sqrt x)           = fmap sqrt  (decode sol x)+  decode sol (Exp x)            = fmap exp   (decode sol x)+  decode sol (Sin x)            = fmap sin   (decode sol x)+  decode sol (Cos x)            = fmap cos   (decode sol x)+  decode sol (Tan x)            = fmap tan   (decode sol x)+  decode sol (Asin x)           = fmap asin  (decode sol x)+  decode sol (Acos x)           = fmap acos  (decode sol x)+  decode sol (Atan x)           = fmap atan  (decode sol x)+  decode sol (ToReal x)         = fmap realToFrac (decode sol x)+  decode sol (ToInt x)          = fmap truncate   (decode sol x)+  decode sol (IsInt x)          = fmap ((0 ==) . snd . properFraction) (decode sol x)+  decode sol (Ite p t f)        = liftM3 (\p' t' f' -> if p' then t' else f') (decode sol p) (decode sol t) (decode sol f)    decode sol (BvNot x)          = fmap not (decode sol x)   decode sol (BvAnd x y)        = liftA2 (&&) (decode sol x) (decode sol y)   decode sol (BvOr x y)         = liftA2 (||) (decode sol x) (decode sol y)@@ -115,8 +99,11 @@   decode sol (BvuLTHE x y)      = liftA2 (<=) (decode sol x) (decode sol y)   decode sol (BvuGTHE x y)      = liftA2 (>=) (decode sol x) (decode sol y)   decode sol (BvuGT x y)        = liftA2 (>) (decode sol x) (decode sol y)-  decode _ (ForAll _ _)       = Nothing-  decode _ (Exists _ _)       = Nothing+  decode sol (ArrSelect i arr)  = liftA2 arrSelect (decode sol i) (decode sol arr)+  decode sol (ArrStore i x arr) = liftM3 arrStore (decode sol i) (decode sol x) (decode sol arr)+  decode _ (ForAll _ _)         = Nothing+  decode _ (Exists _ _)         = Nothing+     encode = Constant . wrapValue  instance Codec () where
src/Language/Hasmtlib/Internal/Expr.hs view
@@ -2,12 +2,16 @@ {-# LANGUAGE NoStarIsType #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}  module Language.Hasmtlib.Internal.Expr where  import Language.Hasmtlib.Internal.Bitvec import Language.Hasmtlib.Internal.Render+import Language.Hasmtlib.Type.ArrayMap import Language.Hasmtlib.Boolean+import Data.GADT.Compare+import Data.Map import Data.Kind import Data.Proxy import Data.Coerce@@ -16,70 +20,129 @@ import GHC.TypeLits  -- | Sorts in SMTLib2 - used as promoted type (data-kind).-data SMTSort = IntSort | RealSort | BoolSort | BvSort Nat+data SMTSort =+    BoolSort                      -- ^ Sort of Bool+  | IntSort                       -- ^ Sort of Int+  | RealSort                      -- ^ Sort of Real+  | BvSort Nat                    -- ^ Sort of BitVec with length n+  | ArraySort SMTSort SMTSort     -- ^ Sort of Array with indices k and values v  -- | An internal SMT variable with a phantom-type which holds an 'Int' as it's identifier. type role SMTVar phantom newtype SMTVar (t :: SMTSort) = SMTVar { _varId :: Int } deriving (Show, Eq, Ord) $(makeLenses ''SMTVar) --- | Injective type-family that computes the Haskell 'Type' of a 'SMTSort'.+-- | Injective type-family that computes the Haskell 'Type' of an 'SMTSort'. type family HaskellType (t :: SMTSort) = (r :: Type) | r -> t where-  HaskellType IntSort    = Integer-  HaskellType RealSort   = Double-  HaskellType BoolSort   = Bool-  HaskellType (BvSort n) = Bitvec n+  HaskellType IntSort         = Integer+  HaskellType RealSort        = Double+  HaskellType BoolSort        = Bool+  HaskellType (BvSort n)      = Bitvec n+  HaskellType (ArraySort k v) = ConstArray (HaskellType k) (HaskellType v)  -- | A wrapper for values of 'SMTSort's. data Value (t :: SMTSort) where-  IntValue  :: HaskellType IntSort    -> Value IntSort-  RealValue :: HaskellType RealSort   -> Value RealSort-  BoolValue :: HaskellType BoolSort   -> Value BoolSort-  BvValue   :: HaskellType (BvSort n) -> Value (BvSort n)+  IntValue   :: HaskellType IntSort    -> Value IntSort+  RealValue  :: HaskellType RealSort   -> Value RealSort+  BoolValue  :: HaskellType BoolSort   -> Value BoolSort+  BvValue    :: HaskellType (BvSort n) -> Value (BvSort n)+  ArrayValue :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => HaskellType (ArraySort k v) -> Value (ArraySort k v) --- | Unwrap a value.+-- | Unwrap a value from 'Value'. unwrapValue :: Value t -> HaskellType t unwrapValue (IntValue  v) = v unwrapValue (RealValue v) = v unwrapValue (BoolValue v) = v unwrapValue (BvValue   v) = v+unwrapValue (ArrayValue v) = v {-# INLINEABLE unwrapValue #-} --- | Wrap a value.+-- | Wrap a value into 'Value'. wrapValue :: forall t. KnownSMTSort t => HaskellType t -> Value t wrapValue = case sortSing @t of   SIntSort  -> IntValue   SRealSort -> RealValue   SBoolSort -> BoolValue   SBvSort _ -> BvValue+  SArraySort _ _ -> ArrayValue {-# INLINEABLE wrapValue #-} -deriving instance Show (Value t)-deriving instance Eq   (Value t)-deriving instance Ord  (Value t)- -- | Singleton for 'SMTSort'. data SSMTSort (t :: SMTSort) where-  SIntSort  :: SSMTSort IntSort-  SRealSort :: SSMTSort RealSort-  SBoolSort :: SSMTSort BoolSort-  SBvSort   :: KnownNat n => Proxy n -> SSMTSort (BvSort n)+  SIntSort   :: SSMTSort IntSort+  SRealSort  :: SSMTSort RealSort+  SBoolSort  :: SSMTSort BoolSort+  SBvSort    :: KnownNat n => Proxy n -> SSMTSort (BvSort n)+  SArraySort :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Proxy v -> SSMTSort (ArraySort k v)  deriving instance Show (SSMTSort t) deriving instance Eq   (SSMTSort t) deriving instance Ord  (SSMTSort t) +instance GEq SSMTSort where+  geq SIntSort SIntSort       = Just Refl+  geq SRealSort SRealSort     = Just Refl+  geq SBoolSort SBoolSort     = Just Refl+  geq (SBvSort n) (SBvSort m) = case sameNat n m of+    Just Refl -> Just Refl+    Nothing   -> Nothing+  geq _ _                     = Nothing++instance GCompare SSMTSort where+  gcompare SBoolSort SBoolSort     = GEQ+  gcompare SIntSort SIntSort       = GEQ+  gcompare SRealSort SRealSort     = GEQ+  gcompare (SBvSort n) (SBvSort m) = case cmpNat n m of+    LTI -> GLT+    EQI -> GEQ+    GTI -> GGT+  gcompare (SArraySort k v) (SArraySort k' v') = case gcompare (sortSing' k) (sortSing' k') of+    GLT -> GLT+    GEQ -> case gcompare (sortSing' v) (sortSing' v') of+      GLT -> GLT+      GEQ -> GEQ+      GGT -> GGT+    GGT -> GGT+  gcompare SBoolSort _        = GLT+  gcompare _ SBoolSort        = GGT+  gcompare SIntSort _         = GLT+  gcompare _ SIntSort         = GGT+  gcompare SRealSort _        = GLT+  gcompare _ SRealSort        = GGT+  gcompare (SArraySort _ _) _ = GLT+  gcompare _ (SArraySort _ _) = GGT+ -- | Compute singleton 'SSMTSort' from it's promoted type 'SMTSort'. class    KnownSMTSort (t :: SMTSort)           where sortSing :: SSMTSort t instance KnownSMTSort IntSort                  where sortSing = SIntSort instance KnownSMTSort RealSort                 where sortSing = SRealSort instance KnownSMTSort BoolSort                 where sortSing = SBoolSort instance KnownNat n => KnownSMTSort (BvSort n) where sortSing = SBvSort (Proxy @n)+instance (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => KnownSMTSort (ArraySort k v) where+   sortSing = SArraySort (Proxy @k) (Proxy @v) --- | An existential wrapper that hides some 'SMTSort'.-data SomeKnownSMTSort f where-  SomeKnownSMTSort :: forall (t :: SMTSort) f. KnownSMTSort t => f t -> SomeKnownSMTSort f+-- | Wrapper for 'sortSing' which takes a 'Proxy'+sortSing' :: forall prxy t. KnownSMTSort t => prxy t -> SSMTSort t+sortSing' _ = sortSing @t +-- | AllC ensures that a list of constraints is applied to a poly-kinded 'Type' k+-- +-- @+-- AllC '[]       k = ()+-- AllC (c ': cs) k = (c k, AllC cs k)+-- @ +type AllC :: [k -> Constraint] -> k -> Constraint+type family AllC cs k :: Constraint where+  AllC '[]       k = ()+  AllC (c ': cs) k = (c k, AllC cs k)++-- | An existential wrapper that hides some 'SMTSort' and a list of 'Constraint's holding for it.+data SomeSMTSort cs f where+  SomeSMTSort :: forall cs f (t :: SMTSort). AllC cs t => f t -> SomeSMTSort cs f++-- | An existential wrapper that hides some known 'SMTSort'.+type SomeKnownSMTSort f = SomeSMTSort '[KnownSMTSort] f + -- | A SMT expression. --   For internal use only. --   For building expressions use the corresponding instances (Num, Boolean, ...).@@ -108,47 +171,50 @@   Impl      :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t   Xor       :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t -  Pi       :: Expr RealSort-  Sqrt     :: Expr RealSort -> Expr RealSort-  Exp      :: Expr RealSort -> Expr RealSort-  Sin      :: Expr RealSort -> Expr RealSort-  Cos      :: Expr RealSort -> Expr RealSort-  Tan      :: Expr RealSort -> Expr RealSort-  Asin     :: Expr RealSort -> Expr RealSort-  Acos     :: Expr RealSort -> Expr RealSort-  Atan     :: Expr RealSort -> Expr RealSort+  Pi        :: Expr RealSort+  Sqrt      :: Expr RealSort -> Expr RealSort+  Exp       :: Expr RealSort -> Expr RealSort+  Sin       :: Expr RealSort -> Expr RealSort+  Cos       :: Expr RealSort -> Expr RealSort+  Tan       :: Expr RealSort -> Expr RealSort+  Asin      :: Expr RealSort -> Expr RealSort+  Acos      :: Expr RealSort -> Expr RealSort+  Atan      :: Expr RealSort -> Expr RealSort -  ToReal   :: Expr IntSort  -> Expr RealSort-  ToInt    :: Expr RealSort -> Expr IntSort-  IsInt    :: Expr RealSort -> Expr BoolSort+  ToReal    :: Expr IntSort  -> Expr RealSort+  ToInt     :: Expr RealSort -> Expr IntSort+  IsInt     :: Expr RealSort -> Expr BoolSort -  Ite      :: Expr BoolSort -> Expr t -> Expr t -> Expr t+  Ite       :: Expr BoolSort -> Expr t -> Expr t -> Expr t -  BvNot    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)-  BvAnd    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvOr     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvXor    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvNand   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvNor    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvNeg    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)-  BvAdd    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvSub    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvMul    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvuDiv   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvuRem   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvShL    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvLShR   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)-  BvConcat :: (KnownNat n, KnownNat m) => Expr (BvSort n) -> Expr (BvSort m) -> Expr (BvSort (n + m))-  BvRotL   :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)-  BvRotR   :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)-  BvuLT    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort-  BvuLTHE  :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort-  BvuGTHE  :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort-  BvuGT    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort+  BvNot     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)+  BvAnd     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvOr      :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvXor     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvNand    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvNor     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvNeg     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)+  BvAdd     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvSub     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvMul     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvuDiv    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvuRem    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvShL     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvLShR    :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)+  BvConcat  :: (KnownNat n, KnownNat m) => Expr (BvSort n) -> Expr (BvSort m) -> Expr (BvSort (n + m))+  BvRotL    :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)+  BvRotR    :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)+  BvuLT     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort+  BvuLTHE   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort+  BvuGTHE   :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort+  BvuGT     :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort -  ForAll   :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort-  Exists   :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort+  ArrSelect :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v+  ArrStore  :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v -> Expr (ArraySort k v) +  ForAll    :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort+  Exists    :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort+ instance Boolean (Expr BoolSort) where   bool = Constant . BoolValue   {-# INLINE bool #-}@@ -182,22 +248,35 @@   maxBound = Constant $ BvValue maxBound  instance Render (SSMTSort t) where+  render SBoolSort   = "Bool"   render SIntSort    = "Int"   render SRealSort   = "Real"-  render SBoolSort   = "Bool"   render (SBvSort p) = renderBinary "_" ("BitVec" :: Builder) (natVal p)+  render (SArraySort k v) = renderBinary "Array" (sortSing' k) (sortSing' v)   {-# INLINEABLE render #-}  instance Render (SMTVar t) where   render v = "var_" <> intDec (coerce @(SMTVar t) @Int v)   {-# INLINEABLE render #-} +instance Render (Value t) where+  render (IntValue x)   = render x+  render (RealValue x)  = render x+  render (BoolValue x)  = render x+  render (BvValue   v)  = "#b" <> render v+  render (ArrayValue arr) = case minViewWithKey (arr^.stored) of+    Nothing -> constRender $ arr^.arrConst+    Just ((k,v), stored')+      | size (arr^.stored) > 1 -> render $ ArrStore (Constant (wrapValue (arr & stored .~ stored'))) (Constant (wrapValue k)) (Constant (wrapValue v))+      | otherwise  -> constRender v+    where+      constRender v = "((as const " <> render (goSing arr) <> ") " <> render (wrapValue v) <> ")"+      goSing :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => ConstArray (HaskellType k) (HaskellType v) -> SSMTSort (ArraySort k v)+      goSing _ = sortSing @(ArraySort k v)+ instance KnownSMTSort t => Render (Expr t) where-  render (Var v)                  = render v-  render (Constant (IntValue x))  = render x-  render (Constant (RealValue x)) = render x-  render (Constant (BoolValue x)) = render x-  render (Constant (BvValue   v)) = "#b" <> render v+  render (Var v)      = render v+  render (Constant c) = render c    render (Plus x y)   = renderBinary "+" x y   render (Neg x)      = renderUnary  "-" x@@ -258,6 +337,9 @@   render (BvuGTHE x y)      = renderBinary "bvuge"  (render x) (render y)   render (BvuGT x y)        = renderBinary "bvugt"  (render x) (render y) +  render (ArrSelect a i)    = renderBinary  "select" (render a) (render i)+  render (ArrStore a i v)   = renderTernary "store"  (render a) (render i) (render v)+   render (ForAll mQvar f) = renderQuantifier "forall" mQvar f   render (Exists mQvar f) = renderQuantifier "exists" mQvar f @@ -271,65 +353,71 @@     expr = render $ f $ Var qvar renderQuantifier _ Nothing _ = mempty +instance Show (Value t) where+  show (IntValue x)   = "IntValue "   ++ show x+  show (RealValue x)  = "RealValue "  ++ show x+  show (BoolValue x)  = "BoolValue "  ++ show x+  show (BvValue x)    = "BvValue "    ++ show x+  show (ArrayValue x) = "ArrValue: "  ++ show (render (ArrayValue x)) -- FIXME: This is bad but easy now+ instance Show (Expr t) where-  show (Var v)                  = show v-  show (Constant (IntValue x))  = show x-  show (Constant (RealValue x)) = show x-  show (Constant (BoolValue x)) = show x-  show (Constant (BvValue   x)) = show x-  show (Plus x y)               = "(" ++ show x ++ " + " ++ show y ++ ")"-  show (Neg x)                  = "(- " ++ show x ++ ")"-  show (Mul x y)                = "(" ++ show x ++ " * " ++ show y ++ ")"-  show (Abs x)                  = "(abs " ++ show x ++ ")"-  show (Mod x y)                = "(" ++ show x ++ " mod " ++ show y ++ ")"-  show (IDiv x y)               = "(" ++ show x ++ " div " ++ show y ++ ")"-  show (Div x y)                = "(" ++ show x ++ " / " ++ show y ++ ")"-  show (LTH x y)                = "(" ++ show x ++ " < " ++ show y ++ ")"-  show (LTHE x y)               = "(" ++ show x ++ " <= " ++ show y ++ ")"-  show (EQU x y)                = "(" ++ show x ++ " == " ++ show y ++ ")"-  show (Distinct x y)           = "(" ++ show x ++ " /= " ++ show y ++ ")"-  show (GTHE x y)               = "(" ++ show x ++ " >= " ++ show y ++ ")"-  show (GTH x y)                = "(" ++ show x ++ " > " ++ show y ++ ")"-  show (Not x)                  = "(not " ++ show x ++ ")"-  show (And x y)                = "(" ++ show x ++ " && " ++ show y ++ ")"-  show (Or x y)                 = "(" ++ show x ++ " || " ++ show y ++ ")"-  show (Impl x y)               = "(" ++ show x ++ " ==> " ++ show y ++ ")"-  show (Xor x y)                = "(" ++ show x ++ " xor " ++ show y ++ ")"-  show Pi                       = "pi"-  show (Sqrt x)                 = "(sqrt "    ++ show x ++ ")"-  show (Exp x)                  = "(exp "     ++ show x ++ ")"-  show (Sin x)                  = "(sin "     ++ show x ++ ")"-  show (Cos x)                  = "(cos "     ++ show x ++ ")"-  show (Tan x)                  = "(tan "     ++ show x ++ ")"-  show (Asin x)                 = "(arcsin "  ++ show x ++ ")"-  show (Acos x)                 = "(arccos "  ++ show x ++ ")"-  show (Atan x)                 = "(arctan "  ++ show x ++ ")"-  show (ToReal x)               = "(to_real " ++ show x ++ ")"-  show (ToInt x)                = "(to_int "  ++ show x ++ ")"-  show (IsInt x)                = "(is_int "  ++ show x ++ ")"-  show (Ite p t f)              = "(ite " ++ show p ++ " " ++ show t ++ " " ++ show f ++ ")"-  show (BvNot x)                = "(not "  ++ show x ++ ")"-  show (BvAnd x y)              = "(" ++ show x ++ " && " ++ show y ++ ")"-  show (BvOr x y)               = "(" ++ show x ++ " || " ++ show y ++ ")"-  show (BvXor x y)              = "(" ++ show x ++ " xor " ++ show y ++ ")"-  show (BvNand x y)             = "(" ++ show x ++ " nand " ++ show y ++ ")"-  show (BvNor x y)              = "(" ++ show x ++ " nor " ++ show y ++ ")"-  show (BvNeg x)                = "(- " ++ show x ++ ")"-  show (BvAdd x y)              = "(" ++ show x ++ " + " ++ show y ++ ")"-  show (BvSub x y)              = "(" ++ show x ++ " - " ++ show y ++ ")"-  show (BvMul x y)              = "(" ++ show x ++ " * " ++ show y ++ ")"-  show (BvuDiv x y)             = "(" ++ show x ++ " udiv " ++ show y ++ ")"-  show (BvuRem x y)             = "(" ++ show x ++ " urem " ++ show y ++ ")"-  show (BvShL x y)              = "(" ++ show x ++ " bvshl " ++ show y ++ ")"-  show (BvLShR x y)             = "(" ++ show x ++ " bvlshr " ++ show y ++ ")"-  show (BvConcat x y)           = "(" ++ show x ++ " bvconcat " ++ show y ++ ")"-  show (BvRotL i x)             = "(" ++ show x ++ " bvrotl " ++ show (natVal i) ++ ")"-  show (BvRotR i x)             = "(" ++ show x ++ " bvrotr " ++ show (natVal i) ++ ")"-  show (BvuLT x y)              = "(" ++ show x ++ " bvult " ++ show y ++ ")"-  show (BvuLTHE x y)            = "(" ++ show x ++ " bvule " ++ show y ++ ")"-  show (BvuGTHE x y)            = "(" ++ show x ++ " bvuge " ++ show y ++ ")"-  show (BvuGT x y)              = "(" ++ show x ++ " bvugt " ++ show y ++ ")"-  show (ForAll (Just qv) f)     = "(forall " ++ show qv ++ ": " ++ show (f (Var qv)) ++ ")"-  show (ForAll Nothing f)       = "(forall var_-1: " ++ show (f (Var (SMTVar (-1)))) ++ ")"-  show (Exists (Just qv) f)     = "(exists " ++ show qv ++ ": " ++ show (f (Var qv)) ++ ")"-  show (Exists Nothing f)       = "(exists var_-1: " ++ show (f (Var (SMTVar (-1)))) ++ ")"+  show (Var v)              = show v+  show (Constant c)         = show c+  show (Plus x y)           = "(" ++ show x ++ " + " ++ show y ++ ")"+  show (Neg x)              = "(- " ++ show x ++ ")"+  show (Mul x y)            = "(" ++ show x ++ " * " ++ show y ++ ")"+  show (Abs x)              = "(abs " ++ show x ++ ")"+  show (Mod x y)            = "(" ++ show x ++ " mod " ++ show y ++ ")"+  show (IDiv x y)           = "(" ++ show x ++ " div " ++ show y ++ ")"+  show (Div x y)            = "(" ++ show x ++ " / " ++ show y ++ ")"+  show (LTH x y)            = "(" ++ show x ++ " < " ++ show y ++ ")"+  show (LTHE x y)           = "(" ++ show x ++ " <= " ++ show y ++ ")"+  show (EQU x y)            = "(" ++ show x ++ " == " ++ show y ++ ")"+  show (Distinct x y)       = "(" ++ show x ++ " /= " ++ show y ++ ")"+  show (GTHE x y)           = "(" ++ show x ++ " >= " ++ show y ++ ")"+  show (GTH x y)            = "(" ++ show x ++ " > " ++ show y ++ ")"+  show (Not x)              = "(not " ++ show x ++ ")"+  show (And x y)            = "(" ++ show x ++ " && " ++ show y ++ ")"+  show (Or x y)             = "(" ++ show x ++ " || " ++ show y ++ ")"+  show (Impl x y)           = "(" ++ show x ++ " ==> " ++ show y ++ ")"+  show (Xor x y)            = "(" ++ show x ++ " xor " ++ show y ++ ")"+  show Pi                   = "pi"+  show (Sqrt x)             = "(sqrt "    ++ show x ++ ")"+  show (Exp x)              = "(exp "     ++ show x ++ ")"+  show (Sin x)              = "(sin "     ++ show x ++ ")"+  show (Cos x)              = "(cos "     ++ show x ++ ")"+  show (Tan x)              = "(tan "     ++ show x ++ ")"+  show (Asin x)             = "(arcsin "  ++ show x ++ ")"+  show (Acos x)             = "(arccos "  ++ show x ++ ")"+  show (Atan x)             = "(arctan "  ++ show x ++ ")"+  show (ToReal x)           = "(to_real " ++ show x ++ ")"+  show (ToInt x)            = "(to_int "  ++ show x ++ ")"+  show (IsInt x)            = "(is_int "  ++ show x ++ ")"+  show (Ite p t f)          = "(ite " ++ show p ++ " " ++ show t ++ " " ++ show f ++ ")"+  show (BvNot x)            = "(not "  ++ show x ++ ")"+  show (BvAnd x y)          = "(" ++ show x ++ " && " ++ show y ++ ")"+  show (BvOr x y)           = "(" ++ show x ++ " || " ++ show y ++ ")"+  show (BvXor x y)          = "(" ++ show x ++ " xor " ++ show y ++ ")"+  show (BvNand x y)         = "(" ++ show x ++ " nand " ++ show y ++ ")"+  show (BvNor x y)          = "(" ++ show x ++ " nor " ++ show y ++ ")"+  show (BvNeg x)            = "(- " ++ show x ++ ")"+  show (BvAdd x y)          = "(" ++ show x ++ " + " ++ show y ++ ")"+  show (BvSub x y)          = "(" ++ show x ++ " - " ++ show y ++ ")"+  show (BvMul x y)          = "(" ++ show x ++ " * " ++ show y ++ ")"+  show (BvuDiv x y)         = "(" ++ show x ++ " udiv " ++ show y ++ ")"+  show (BvuRem x y)         = "(" ++ show x ++ " urem " ++ show y ++ ")"+  show (BvShL x y)          = "(" ++ show x ++ " bvshl " ++ show y ++ ")"+  show (BvLShR x y)         = "(" ++ show x ++ " bvlshr " ++ show y ++ ")"+  show (BvConcat x y)       = "(" ++ show x ++ " bvconcat " ++ show y ++ ")"+  show (BvRotL i x)         = "(" ++ show x ++ " bvrotl " ++ show (natVal i) ++ ")"+  show (BvRotR i x)         = "(" ++ show x ++ " bvrotr " ++ show (natVal i) ++ ")"+  show (BvuLT x y)          = "(" ++ show x ++ " bvult " ++ show y ++ ")"+  show (BvuLTHE x y)        = "(" ++ show x ++ " bvule " ++ show y ++ ")"+  show (BvuGTHE x y)        = "(" ++ show x ++ " bvuge " ++ show y ++ ")"+  show (BvuGT x y)          = "(" ++ show x ++ " bvugt " ++ show y ++ ")"+  show (ForAll (Just qv) f) = "(forall " ++ show qv ++ ": " ++ show (f (Var qv)) ++ ")"+  show (ForAll Nothing f)   = "(forall var_-1: " ++ show (f (Var (SMTVar (-1)))) ++ ")"+  show (ArrSelect i arr)    = "(select " ++ show i ++ " " ++ show arr ++ ")"+  show (ArrStore i x arr)   = "(select " ++ show i ++ " " ++ show x ++ " " ++ show arr ++ ")"+  show (Exists (Just qv) f) = "(exists " ++ show qv ++ ": " ++ show (f (Var qv)) ++ ")"+  show (Exists Nothing f)   = "(exists var_-1: " ++ show (f (Var (SMTVar (-1)))) ++ ")"
src/Language/Hasmtlib/Internal/Parser.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ImpredicativeTypes #-}+{-# LANGUAGE LiberalTypeSynonyms #-}  module Language.Hasmtlib.Internal.Parser where @@ -12,6 +13,7 @@ import Language.Hasmtlib.Iteable import Language.Hasmtlib.Codec import Language.Hasmtlib.Type.Solution+import Language.Hasmtlib.Type.ArrayMap import Data.Bit import Data.Coerce import Data.Proxy@@ -20,7 +22,6 @@ import Data.ByteString.Builder import Data.Attoparsec.ByteString hiding (Result, skipWhile) import Data.Attoparsec.ByteString.Char8 hiding (Result)-import qualified Data.IntMap as IM import Control.Applicative import Control.Lens hiding (op) import GHC.TypeNats@@ -47,7 +48,7 @@   varSols <- many $ parseSomeSol <* skipSpace   _       <- (skipSpace >> char ')' >> skipSpace) <|> skipSpace -  return $ fromSomeList varSols+  return $ fromSomeVarSols varSols  smt2ModelParser :: Parser Solution smt2ModelParser = do@@ -55,46 +56,64 @@   varSols <- many $ parseSomeSol <* skipSpace   _       <- (skipSpace >> char ')' >> skipSpace) <|> skipSpace -  return $ fromSomeList varSols--fromSomeList :: [SomeKnownSMTSort SMTVarSol] -> Solution-fromSomeList = IM.fromList . fmap (\case someVarSol@(SomeKnownSMTSort varSol) -> (coerce (varSol^.solVar), someVarSol))--parseSomeSol :: Parser (SomeKnownSMTSort SMTVarSol)-parseSomeSol = SomeKnownSMTSort <$> (parseSol @IntSort)-           <|> SomeKnownSMTSort <$> (parseSol @RealSort)-           <|> SomeKnownSMTSort <$> (parseSol @BoolSort)-           <|> parseAnyBvUpToLength 128--parseAnyBvUpToLength :: Natural -> Parser (SomeKnownSMTSort SMTVarSol)-parseAnyBvUpToLength hi = asum $ fmap ((\case SomeNat p -> goProxy p) . someNatVal) [0..hi]-  where-    goProxy :: forall n. KnownNat n => Proxy n -> Parser (SomeKnownSMTSort SMTVarSol)-    goProxy _ = SomeKnownSMTSort <$> parseSol @(BvSort n)+  return $ fromSomeVarSols varSols -parseSol :: forall t. KnownSMTSort t => Parser (SMTVarSol t)-parseSol = do+parseSomeSol :: Parser (SomeKnownOrdSMTSort SMTVarSol)+parseSomeSol = do   _     <- char '(' >> skipSpace   _     <- string "define-fun" >> skipSpace   _     <- string "var_"   vId   <- decimal @Int   _     <- skipSpace >> string "()" >> skipSpace-  _     <- string $ toStrict $ toLazyByteString $ render (sortSing @t)+  (SomeSMTSort someSort) <- parseSomeSort   _     <- skipSpace-  expr  <- parseExpr @t+  expr  <- parseExpr' someSort   _     <- skipSpace >> char ')'--  -- Try to evaluate expression given by solver as solution-  -- Better: Take into scope already successfully parsed solutions for other vars.-  -- Is this even required though? Do the solvers ever answer like-wise?   case decode mempty expr of     Nothing    -> fail $ "Solver reponded with solution for var_" ++ show vId ++ " but it contains "                       ++ "another var. This cannot be parsed and evaluated currently."-    Just value -> return $ SMTVarSol (coerce vId) (wrapValue value)-{-# INLINEABLE parseSol #-}+    Just value -> return $ SomeSMTSort $ SMTVarSol (coerce vId) (wrapValue value)+{-# INLINEABLE parseSomeSol #-} +parseSomeSort :: Parser (SomeKnownOrdSMTSort SSMTSort)+parseSomeSort = (string "Bool" *> pure (SomeSMTSort SBoolSort))+        <|> (string "Int"  *> pure (SomeSMTSort SIntSort))+        <|> (string "Real" *> pure (SomeSMTSort SRealSort))+        <|> parseSomeBitVecSort+        <|> parseSomeArraySort+{-# INLINEABLE parseSomeSort #-}++parseSomeBitVecSort :: Parser (SomeKnownOrdSMTSort SSMTSort)+parseSomeBitVecSort = do+  _ <- char '(' >> skipSpace >> char '_' >> skipSpace+  _ <- string "BitVec" >> skipSpace+  n <- decimal+  _ <- skipSpace >> char ')'+  case someNatVal $ fromInteger n of+    SomeNat pn -> return $ SomeSMTSort $ SBvSort pn+{-# INLINEABLE parseSomeBitVecSort #-}++parseSomeArraySort :: Parser (SomeKnownOrdSMTSort SSMTSort)+parseSomeArraySort = do+  _ <- char '(' >> skipSpace+  _ <- string "Array" >> skipSpace+  (SomeSMTSort keySort)   <- parseSomeSort+  _ <- skipSpace+  (SomeSMTSort valueSort) <- parseSomeSort+  _ <- skipSpace >> char ')'+  return $ SomeSMTSort $ SArraySort (goProxy keySort) (goProxy valueSort)+    where+      goProxy :: forall t. SSMTSort t -> Proxy t+      goProxy _ = Proxy @t+{-# INLINEABLE parseSomeArraySort #-}++parseExpr' :: forall prxy t. KnownSMTSort t => prxy t -> Parser (Expr t)+parseExpr' _ = parseExpr @t+{-# INLINE parseExpr' #-}++-- TODO: Add parseSelect parseExpr :: forall t. KnownSMTSort t => Parser (Expr t)-parseExpr = var <|> constant <|> smtIte+parseExpr = var <|> constantExpr <|> smtIte         <|> case sortSing @t of               SIntSort  -> unary "abs" abs <|> unary  "-" negate                       <|> nary "+" sum  <|> binary "-" (-) <|> nary "*" product <|> binary "mod" Mod@@ -115,15 +134,15 @@                       <|> binary @IntSort ">=" (>=?) <|> binary @IntSort ">" (>?)                       <|> binary @RealSort "<" (<?) <|> binary @RealSort "<=" (<=?)                       <|> binary @RealSort ">=" (>=?) <|> binary @RealSort ">" (>?)-                      -- TODO: All (?) bv lengths - also for '=' and 'distinct'---                      <|> binary @(BvSort 10) "bvult" (<?) <|> binary @(BvSort 10) "bvule" (<=?)---                      <|> binary @(BvSort 10) "bvuge" (>=?) <|> binary @(BvSort 10) "bvugt" (>?)+                      -- TODO: Add compare ops for all (?) bv-sorts               SBvSort _ -> unary "bvnot" not                       <|> binary "bvand" (&&)  <|> binary "bvor" (||) <|> binary "bvxor" xor <|> binary "bvnand" BvNand <|> binary "bvnor" BvNor                       <|> unary  "bvneg" negate                       <|> binary "bvadd" (+)  <|> binary "bvsub" (-) <|> binary "bvmul" (*)                       <|> binary "bvudiv" BvuDiv <|> binary "bvurem" BvuRem                       <|> binary "bvshl" BvShL <|> binary "bvlshr" BvLShR+              SArraySort _ _ -> parseStore+                      -- TODO: Add compare ops for all (?) array-sorts  var :: Parser (Expr t) var = do@@ -131,21 +150,24 @@   vId <- decimal @Int    return $ Var $ coerce vId-{-# INLINEABLE var #-}+{-# INLINE var #-} -constant :: forall t. KnownSMTSort t => Parser (Expr t)-constant = do-  cval <- case sortSing @t of-    SIntSort  -> anyValue decimal-    SRealSort -> anyValue parseRatioDouble <|> parseToRealDouble <|> anyValue rational-    SBoolSort -> parseBool-    SBvSort p -> anyBitvector p+constant :: forall t. KnownSMTSort t => Parser (HaskellType t)+constant = case sortSing @t of+  SIntSort  -> anyValue decimal+  SRealSort -> anyValue parseRatioDouble <|> parseToRealDouble <|> anyValue rational+  SBoolSort -> parseBool+  SBvSort p -> anyBitvector p+  SArraySort k v -> constArray k v+{-# INLINE constant #-} -  return $ Constant $ wrapValue cval-{-# INLINEABLE constant #-}+constantExpr :: forall t. KnownSMTSort t => Parser (Expr t)+constantExpr = Constant . wrapValue <$> constant @t+{-# INLINE constantExpr #-}  anyBitvector :: KnownNat n => Proxy n -> Parser (Bitvec n) anyBitvector p = binBitvector p <|> hexBitvector p <|> literalBitvector p+{-# INLINE anyBitvector #-}  binBitvector :: KnownNat n => Proxy n -> Parser (Bitvec n) binBitvector p = do@@ -161,7 +183,7 @@ hexBitvector _ = do   _ <- string "#x" >> skipSpace   fromInteger <$> hexadecimal-{-# INLINEABLE hexBitvector #-}+{-# INLINE hexBitvector #-}  literalBitvector :: KnownNat n => Proxy n -> Parser (Bitvec n) literalBitvector _ = do@@ -172,8 +194,44 @@   _ <- skipWhile (/= ')') >> char ')'    return $ fromInteger x-{-# INLINEABLE literalBitvector #-}+{-# INLINE literalBitvector #-} +constArray :: forall k v. (KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Proxy v -> Parser (ConstArray (HaskellType k) (HaskellType v))+constArray _ _ = do+  _ <- char '(' >> skipSpace >> char '(' >> skipSpace+  _ <- string "as" >> skipSpace >> string "const" >> skipSpace+  _ <- char '(' >> skipWhile (/= ')') >> char ')' >> skipSpace+  _ <- char ')' >> skipSpace+  constVal <- constant @v+  _ <- skipSpace >> char ')'++  return $ asConst constVal+{-# INLINEABLE constArray #-}++parseSelect :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Parser (Expr v)+parseSelect _ = do+  _ <- char '(' >> skipSpace+  _ <- string "select" >> skipSpace+  arr <- parseExpr @(ArraySort k v)+  _ <- skipSpace+  i <- parseExpr @k+  _ <- skipSpace >> char ')'++  return $ ArrSelect arr i++parseStore :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Parser (Expr (ArraySort k v))+parseStore = do+  _ <- char '(' >> skipSpace+  _ <- string "store" >> skipSpace+  arr <- parseExpr @(ArraySort k v)+  _ <- skipSpace+  i <- parseExpr @k+  _ <- skipSpace+  x <- parseExpr @v+  _ <- skipSpace >> char ')'++  return $ ArrStore arr i x+ unary :: forall t r. KnownSMTSort t => ByteString -> (Expr t -> Expr r) -> Parser (Expr r) unary opStr op = do   _ <- char '(' >> skipSpace@@ -182,7 +240,7 @@   _ <- skipSpace >> char ')'    return $ op val-{-# INLINEABLE unary #-}+{-# INLINE unary #-}  binary :: forall t r. KnownSMTSort t => ByteString -> (Expr t -> Expr t -> Expr r) -> Parser (Expr r) binary opStr op = do@@ -193,7 +251,7 @@   r <- parseExpr   _ <- skipSpace >> char ')'   return $ l `op` r-{-# INLINEABLE binary #-}+{-# INLINE binary #-}  nary :: forall t r. KnownSMTSort t => ByteString -> ([Expr t] -> Expr r) -> Parser (Expr r) nary opStr op = do@@ -202,11 +260,11 @@   args <- parseExpr `sepBy1` skipSpace   _    <- skipSpace >> char ')'   return $ op args-{-# INLINEABLE nary #-}+{-# INLINE nary #-}  smtPi :: Parser (Expr RealSort) smtPi = string "real.pi" *> return pi-{-# INLINEABLE smtPi #-}+{-# INLINE smtPi #-}  toRealFun :: Parser (Expr RealSort) toRealFun = do@@ -263,7 +321,7 @@   _ <- skipSpace >> char ')'    return $ negate val-{-# INLINEABLE negativeValue #-}+{-# INLINE negativeValue #-}  parseRatioDouble :: Parser Double parseRatioDouble = do
src/Language/Hasmtlib/Solver/CVC5.hs view
@@ -3,7 +3,5 @@ import Language.Hasmtlib.Solver.Common import qualified SMTLIB.Backends.Process as P --- TODO: Add support for lib binding: https://github.com/tweag/smtlib-backends/tree/master/smtlib-backends-cvc5- cvc5 :: ProcessSolver cvc5 = ProcessSolver $ P.defaultConfig { P.exe = "cvc5", P.args = [] }
src/Language/Hasmtlib/Solver/Z3.hs view
@@ -3,8 +3,6 @@ import Language.Hasmtlib.Solver.Common import qualified SMTLIB.Backends.Process as P --- TODO: Add support for lib binding: https://github.com/tweag/smtlib-backends/tree/master/smtlib-backends-z3- z3 :: ProcessSolver z3 = ProcessSolver P.defaultConfig 
+ src/Language/Hasmtlib/Type/ArrayMap.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-}++module Language.Hasmtlib.Type.ArrayMap where++import Data.Proxy+import qualified Data.Map as Map  +import Control.Lens++-- | Class that allows access to a map-like array where specific values are is the default value or overwritten values.+--   Every index has a value by default.+--   Values at indices can be overwritten manually.+-- +--   Based on McCarthy`s basic array theory.+-- +--   Therefore the following axioms must hold:+-- +-- 1. forall A i x: arrSelect (store A i x) == x+-- +-- 2. forall A i j x: i /= j ==> (arrSelect (arrStore A i x) j === arrSelect A j)+class ArrayMap f k v where+  asConst'   :: Proxy f -> Proxy k -> v -> f k v +  viewConst  :: f k v -> v+  arrSelect  :: f k v -> k -> v+  arrStore   :: f k v -> k -> v -> f k v++-- | Wrapper for 'asConst'' which hides the 'Proxy'+asConst :: forall f k v. ArrayMap f k v => v -> f k v+asConst = asConst' (Proxy @f) (Proxy @k)++-- | A map-like array with a default constant value and partially overwritten values.  +data ConstArray k v = ConstArray +  { _arrConst :: v+  , _stored :: Map.Map k v+  } deriving (Show, Eq, Ord, Functor, Foldable, Traversable)+$(makeLenses ''ConstArray)++instance Ord k => ArrayMap ConstArray k v where+  asConst' _ _ x = ConstArray x Map.empty+  viewConst arr = arr^.arrConst+  arrSelect arr i = case Map.lookup i (arr^.stored) of+    Nothing -> viewConst arr+    Just x  -> x+  arrStore arr i x = arr & stored %~ Map.insert i x
src/Language/Hasmtlib/Type/Expr.hs view
@@ -2,12 +2,13 @@  module Language.Hasmtlib.Type.Expr  ( SMTSort(..)- , SMTVar(..)+ , SMTVar(..), varId  , HaskellType  , Value(..), unwrapValue, wrapValue- , SSMTSort(..), KnownSMTSort(..), SomeKnownSMTSort(..)+ , SSMTSort(..), KnownSMTSort(..), sortSing', SomeSMTSort(..), SomeKnownSMTSort  , Expr  , for_all , exists+ , select, store  , module Language.Hasmtlib.Internal.Expr.Num  ) where@@ -49,3 +50,11 @@ --   It will only be scoped for the lambdas body. exists :: forall t. KnownSMTSort t => (Expr t -> Expr BoolSort) -> Expr BoolSort exists = Exists Nothing++-- | Select a value from an array.+select :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v+select = ArrSelect++-- | Store a value in an array.+store :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v -> Expr (ArraySort k v)+store = ArrStore
src/Language/Hasmtlib/Type/Pipe.hs view
@@ -12,7 +12,8 @@ import Language.Hasmtlib.Internal.Parser hiding (var, constant) import qualified SMTLIB.Backends as B import Data.List (isPrefixOf)-import Data.IntMap (singleton)+import Data.IntMap as IMap (singleton)+import Data.Dependent.Map as DMap import Data.Coerce import Data.ByteString.Builder import Data.ByteString.Lazy hiding (filter, singleton, isPrefixOf)@@ -97,7 +98,13 @@       Left e    -> liftIO $ do         print model         error e-      Right sol -> return $ decode (singleton (sol^.solVar.varId) (SomeKnownSMTSort sol)) v+      Right sol -> +        return $ +          decode +            (DMap.singleton +              (sortSing @t) +              (IntValueMap $ IMap.singleton (sol^.solVar.varId) (sol^.solVal))) +            v   getValue expr = do     model <- getModel     return $ decode model expr
src/Language/Hasmtlib/Type/SMT.hs view
@@ -35,7 +35,7 @@    var' p = do     newVar <- smtvar' p-    vars %= (|> SomeKnownSMTSort newVar)+    vars %= (|> SomeSMTSort newVar)     return $ Var newVar   {-# INLINEABLE var' #-} @@ -75,5 +75,5 @@ {-# INLINEABLE renderAssert #-}  renderVars :: Seq (SomeKnownSMTSort SMTVar) -> Seq Builder-renderVars = fmap (\(SomeKnownSMTSort v) -> renderDeclareVar v)+renderVars = fmap (\(SomeSMTSort v) -> renderDeclareVar v) {-# INLINEABLE renderVars #-}
src/Language/Hasmtlib/Type/Solution.hs view
@@ -1,9 +1,14 @@+{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE UndecidableInstances #-}  module Language.Hasmtlib.Type.Solution where  import Language.Hasmtlib.Type.Expr-import Data.IntMap+import Data.IntMap as IMap hiding (foldl)+import Data.Dependent.Map as DMap+import Data.Dependent.Map.Lens import Control.Lens  -- | Function that turns a state into a result and a solution.@@ -12,12 +17,36 @@ -- | Results of check-sat commands. data Result = Unsat | Unknown | Sat deriving (Show, Eq, Ord) --- | A Solution is a Map from the variable-identifier to some solution for it.-type Solution = IntMap (SomeKnownSMTSort SMTVarSol)+-- | A Solution is a dependent map 'DMap' from 'SSMTSort's t to 'IntMap' t.+type Solution = DMap SSMTSort IntValueMap +-- | Newtype for 'IntMap' 'Value' so we can use it as right-hand-side of 'DMap'.+newtype IntValueMap t = IntValueMap (IntMap (Value t))+  deriving stock Show+  deriving newtype (Semigroup, Monoid)+ -- | A solution for a single variable.-data SMTVarSol (t :: SMTSort) = SMTVarSol +data SMTVarSol (t :: SMTSort) = SMTVarSol   { _solVar :: SMTVar t                       -- ^ A variable in the SMT-Problem   , _solVal :: Value t                        -- ^ An assignment for this variable in a solution-  } deriving (Show, Eq, Ord)+  } deriving Show $(makeLenses ''SMTVarSol)++-- | Alias class for constraint 'Ord' ('HaskellType' t)+class Ord (HaskellType t) => OrdHaskellType t+instance Ord (HaskellType t) => OrdHaskellType t++-- | An existential wrapper that hides some known 'SMTSort' with an 'Ord' 'HaskellType' +type SomeKnownOrdSMTSort f = SomeSMTSort '[KnownSMTSort, OrdHaskellType] f++-- | Create a 'Solution' from some 'SMTVarSol's.+fromSomeVarSols :: [SomeKnownOrdSMTSort SMTVarSol] -> Solution+fromSomeVarSols = foldl+  (\dsol (SomeSMTSort s) -> let sSort = sortSing' s in+    dsol & dmat sSort %~+      (\case+        Nothing -> Just $ IntValueMap $ IMap.singleton (s^.solVar.varId) (s^.solVal)+        Just (IntValueMap im) -> Just $ IntValueMap $ IMap.insert (s^.solVar.varId) (s^.solVal) im+      )+  )+  mempty