hasmtlib 2.2.0 → 2.3.0
raw patch · 12 files changed
+456/−175 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Language.Hasmtlib.Internal.Parser: isIntFun :: Parser (Expr BoolSort)
- Language.Hasmtlib.Internal.Parser: parseSelect :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Parser (Expr v)
- Language.Hasmtlib.Internal.Parser: parseStore :: forall k v. (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Parser (Expr (ArraySort k v))
- Language.Hasmtlib.Internal.Parser: smtIte :: forall t. KnownSMTSort t => Parser (Expr t)
- Language.Hasmtlib.Internal.Parser: toIntFun :: Parser (Expr IntSort)
- Language.Hasmtlib.Internal.Parser: toRealFun :: Parser (Expr RealSort)
+ Language.Hasmtlib.Internal.Parser: parseSmtString :: Parser Text
+ Language.Hasmtlib.Internal.Parser: ternary :: forall t u v r. (KnownSMTSort t, KnownSMTSort u, KnownSMTSort v) => ByteString -> (Expr t -> Expr u -> Expr v -> Expr r) -> Parser (Expr r)
+ Language.Hasmtlib.Internal.Render: instance Language.Hasmtlib.Internal.Render.Render Data.Text.Internal.Text
+ Language.Hasmtlib.Lens: instance (Language.Hasmtlib.Type.SMTSort.KnownSMTSort k, Language.Hasmtlib.Type.SMTSort.KnownSMTSort v, GHC.Classes.Ord (Language.Hasmtlib.Type.SMTSort.HaskellType k)) => Control.Lens.At.Ixed (Language.Hasmtlib.Internal.Expr.Expr ('Language.Hasmtlib.Type.SMTSort.ArraySort k v))
+ Language.Hasmtlib.Lens: instance Control.Lens.At.Ixed (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Control.Lens.Cons.Cons (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Control.Lens.Cons.Snoc (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort) (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Control.Lens.Empty.AsEmpty (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Control.Lens.Prism.Prefixed (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Control.Lens.Prism.Suffixed (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Lens: instance Language.Hasmtlib.Type.SMTSort.KnownSMTSort t => Control.Lens.Plated.Plated (Language.Hasmtlib.Internal.Expr.Expr t)
+ Language.Hasmtlib.Lens: somePlate :: forall t f. (KnownSMTSort t, Applicative f) => (Expr t -> f (Expr t)) -> forall s. KnownSMTSort s => Expr s -> f (Expr s)
+ Language.Hasmtlib.Orderable: instance Language.Hasmtlib.Orderable.Orderable (Language.Hasmtlib.Internal.Expr.Expr 'Language.Hasmtlib.Type.SMTSort.StringSort)
+ Language.Hasmtlib.Type.Expr: [Abs] :: Num (HaskellType t) => Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Acos] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [And] :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [ArrSelect] :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v
+ Language.Hasmtlib.Type.Expr: [ArrStore] :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Expr (ArraySort k v) -> Expr k -> Expr v -> Expr (ArraySort k v)
+ Language.Hasmtlib.Type.Expr: [Asin] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [Atan] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [BvAdd] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvAnd] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvConcat] :: (KnownNat n, KnownNat m) => Expr (BvSort n) -> Expr (BvSort m) -> Expr (BvSort (n + m))
+ Language.Hasmtlib.Type.Expr: [BvLShR] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvMul] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvNand] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvNeg] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvNor] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvNot] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvOr] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvRotL] :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvRotR] :: (KnownNat n, KnownNat i, KnownNat (Mod i n)) => Proxy i -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvShL] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvSub] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvXor] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvuDiv] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [BvuGTHE] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [BvuGT] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [BvuLTHE] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [BvuLT] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [BvuRem] :: KnownNat n => Expr (BvSort n) -> Expr (BvSort n) -> Expr (BvSort n)
+ Language.Hasmtlib.Type.Expr: [Constant] :: Value t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Cos] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [Distinct] :: (Eq (HaskellType t), KnownSMTSort t, KnownNat n) => Vector (n + 2) (Expr t) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [Div] :: Expr RealSort -> Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [EQU] :: (Eq (HaskellType t), KnownSMTSort t, KnownNat n) => Vector (n + 2) (Expr t) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [Exists] :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [Exp] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [ForAll] :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [GTHE] :: (Ord (HaskellType t), KnownSMTSort t) => Expr t -> Expr t -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [GTH] :: (Ord (HaskellType t), KnownSMTSort t) => Expr t -> Expr t -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [IDiv] :: Expr IntSort -> Expr IntSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: [Impl] :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [IsInt] :: Expr RealSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [Ite] :: Expr BoolSort -> Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [LTHE] :: (Ord (HaskellType t), KnownSMTSort t) => Expr t -> Expr t -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [LTH] :: (Ord (HaskellType t), KnownSMTSort t) => Expr t -> Expr t -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [Mod] :: Expr IntSort -> Expr IntSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: [Mul] :: Num (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Neg] :: Num (HaskellType t) => Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Not] :: Boolean (HaskellType t) => Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Or] :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Pi] :: Expr RealSort
+ Language.Hasmtlib.Type.Expr: [Plus] :: Num (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Sin] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [Sqrt] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [StrAt] :: Expr StringSort -> Expr IntSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: [StrConcat] :: Expr StringSort -> Expr StringSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: [StrContains] :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [StrIndexOf] :: Expr StringSort -> Expr StringSort -> Expr IntSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: [StrLTHE] :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [StrLT] :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [StrLength] :: Expr StringSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: [StrPrefixOf] :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [StrReplaceAll] :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: [StrReplace] :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: [StrSubstring] :: Expr StringSort -> Expr IntSort -> Expr IntSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: [StrSuffixOf] :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: [StringValue] :: HaskellType StringSort -> Value StringSort
+ Language.Hasmtlib.Type.Expr: [Tan] :: Expr RealSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [ToInt] :: Expr RealSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: [ToReal] :: Expr IntSort -> Expr RealSort
+ Language.Hasmtlib.Type.Expr: [Var] :: SMTVar t -> Expr t
+ Language.Hasmtlib.Type.Expr: [Xor] :: Boolean (HaskellType t) => Expr t -> Expr t -> Expr t
+ Language.Hasmtlib.Type.Expr: strAt :: Expr StringSort -> Expr IntSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: strContains :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: strIndexOf :: Expr StringSort -> Expr StringSort -> Expr IntSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: strLength :: Expr StringSort -> Expr IntSort
+ Language.Hasmtlib.Type.Expr: strPrefixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.Expr: strReplace :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: strReplaceAll :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: strSubstring :: Expr StringSort -> Expr IntSort -> Expr IntSort -> Expr StringSort
+ Language.Hasmtlib.Type.Expr: strSuffixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort
+ Language.Hasmtlib.Type.SMTSort: StringSort :: SMTSort
+ Language.Hasmtlib.Type.SMTSort: [SStringSort] :: SSMTSort StringSort
+ Language.Hasmtlib.Type.SMTSort: instance Language.Hasmtlib.Type.SMTSort.KnownSMTSort 'Language.Hasmtlib.Type.SMTSort.StringSort
- Language.Hasmtlib.Codec: -- | Resulting of decoding <tt>a</tt>
+ Language.Hasmtlib.Codec: -- | Result of decoding <tt>a</tt>.
- Language.Hasmtlib.Internal.Parser: binary :: forall t r. KnownSMTSort t => ByteString -> (Expr t -> Expr t -> Expr r) -> Parser (Expr r)
+ Language.Hasmtlib.Internal.Parser: binary :: forall t u r. (KnownSMTSort t, KnownSMTSort u) => ByteString -> (Expr t -> Expr u -> Expr r) -> Parser (Expr r)
- Language.Hasmtlib.Type.ArrayMap: arrConst :: forall k_ajKf v_ajKg. Lens' (ConstArray k_ajKf v_ajKg) v_ajKg
+ Language.Hasmtlib.Type.ArrayMap: arrConst :: forall k_ajLE v_ajLF. Lens' (ConstArray k_ajLE v_ajLF) v_ajLF
- Language.Hasmtlib.Type.ArrayMap: stored :: forall k_ajKf v_ajKg k_alcE. Lens (ConstArray k_ajKf v_ajKg) (ConstArray k_alcE v_ajKg) (Map k_ajKf v_ajKg) (Map k_alcE v_ajKg)
+ Language.Hasmtlib.Type.ArrayMap: stored :: forall k_ajLE v_ajLF k_ale3. Lens (ConstArray k_ajLE v_ajLF) (ConstArray k_ale3 v_ajLF) (Map k_ajLE v_ajLF) (Map k_ale3 v_ajLF)
- Language.Hasmtlib.Type.Expr: varId :: forall t_asDV t_asKe. Iso (SMTVar t_asDV) (SMTVar t_asKe) Int Int
+ Language.Hasmtlib.Type.Expr: varId :: forall t_asQQ t_atAU. Iso (SMTVar t_asQQ) (SMTVar t_atAU) Int Int
- Language.Hasmtlib.Type.Solution: solVal :: forall t_aP7j. Lens' (SMTVarSol t_aP7j) (Value t_aP7j)
+ Language.Hasmtlib.Type.Solution: solVal :: forall t_aPMn. Lens' (SMTVarSol t_aPMn) (Value t_aPMn)
- Language.Hasmtlib.Type.Solution: solVar :: forall t_aP7j. Lens' (SMTVarSol t_aP7j) (SMTVar t_aP7j)
+ Language.Hasmtlib.Type.Solution: solVar :: forall t_aPMn. Lens' (SMTVarSol t_aPMn) (SMTVar t_aPMn)
Files
- CHANGELOG.md +10/−0
- README.md +8/−2
- hasmtlib.cabal +3/−2
- src/Language/Hasmtlib.hs +2/−0
- src/Language/Hasmtlib/Codec.hs +29/−4
- src/Language/Hasmtlib/Internal/Expr.hs +66/−84
- src/Language/Hasmtlib/Internal/Parser.hs +39/−77
- src/Language/Hasmtlib/Internal/Render.hs +6/−0
- src/Language/Hasmtlib/Lens.hs +211/−0
- src/Language/Hasmtlib/Orderable.hs +7/−0
- src/Language/Hasmtlib/Type/Expr.hs +55/−1
- src/Language/Hasmtlib/Type/SMTSort.hs +20/−5
CHANGELOG.md view
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [PVP versioning](https://pvp.haskell.org/). +## v2.3.0 _(2024-08-12)_++### Added+- Added full SMTLib2.6-standard support for sort String+- Added module `Language.Hasmtlib.Lens` featuring `instance Plated (Expr t)` for rewriting++### Changed+- Export constructors of `Expr t`+- `instance Show (Expr t)` now displays expressions in SMTLib2-Syntax+ ## v2.2.0 _(2024-08-09)_ ### Added
README.md view
@@ -59,12 +59,18 @@ - [x] SMTLib2-Sorts in the Haskell-Type ```haskell- data SMTSort = BoolSort | IntSort | RealSort | BvSort Nat | ArraySort SMTSort SMTSort+ data SMTSort =+ BoolSort+ | IntSort+ | RealSort+ | BvSort Nat+ | ArraySort SMTSort SMTSort+ | StringSort data Expr (t :: SMTSort) where ... ite :: Expr BoolSort -> Expr t -> Expr t -> Expr t ```-- [x] Full SMTLib 2.6 standard support for Sorts Int, Real, Bool, unsigned BitVec & Array+- [x] Full SMTLib 2.6 standard support for Sorts Int, Real, Bool, unsigned BitVec, Array & String - [x] Type-level length-indexed Bitvectors for BitVec ```haskell bvConcat :: (KnownNat n, KnownNat m) => Expr (BvSort n) -> Expr (BvSort m) -> Expr (BvSort (n + m))
hasmtlib.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 name: hasmtlib-version: 2.2.0+version: 2.3.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.@@ -14,7 +14,7 @@ author: Julian Bruder maintainer: julian.bruder@outlook.com copyright: © 2024 Julian Bruder-category: SMT+category: SMT, Logic build-type: Simple extra-source-files: README.md extra-doc-files: CHANGELOG.md@@ -26,6 +26,7 @@ default-extensions: DataKinds, GADTs, TypeFamilies, OverloadedStrings exposed-modules: Language.Hasmtlib+ , Language.Hasmtlib.Lens , Language.Hasmtlib.Codec , Language.Hasmtlib.Iteable , Language.Hasmtlib.Boolean
src/Language/Hasmtlib.hs view
@@ -10,6 +10,7 @@ , module Language.Hasmtlib.Type.SMTSort , module Language.Hasmtlib.Type.Solution , module Language.Hasmtlib.Type.ArrayMap+ , module Language.Hasmtlib.Lens , module Language.Hasmtlib.Integraled , module Language.Hasmtlib.Iteable , module Language.Hasmtlib.Boolean@@ -38,6 +39,7 @@ import Language.Hasmtlib.Type.SMTSort import Language.Hasmtlib.Type.Solution import Language.Hasmtlib.Type.ArrayMap+import Language.Hasmtlib.Lens import Language.Hasmtlib.Integraled import Language.Hasmtlib.Iteable import Language.Hasmtlib.Boolean
src/Language/Hasmtlib/Codec.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-} module Language.Hasmtlib.Codec where @@ -19,11 +20,13 @@ import Data.IntMap as IM hiding (foldl) import Data.Dependent.Map as DMap import Data.Tree (Tree)+import qualified Data.Text as Text import Data.Monoid (Sum, Product, First, Last, Dual) import Data.Functor.Identity (Identity) import qualified Data.Vector.Sized as V import Control.Monad import GHC.Generics+import GHC.TypeLits -- | Computes a default 'Decoded' 'Type' by distributing 'Decoded' to it's type arguments. type family DefaultDecoded a :: Type where@@ -35,13 +38,18 @@ DefaultDecoded (t a b c) = t (Decoded a) (Decoded b) (Decoded c) DefaultDecoded (t a b) = t (Decoded a) (Decoded b) DefaultDecoded (t a) = t (Decoded a)- DefaultDecoded () = ()+ DefaultDecoded x = TypeError (+ Text "DefaultDecoded (" :<>: ShowType x :<>: Text ") is not allowed."+ :$$: Text "Try providing the associated Type Decoded (" :<>: ShowType x :<>: Text ") manually:"+ :$$: Text "instance Codec (" :<>: ShowType x :<>: Text ") where "+ :$$: Text " type Decoded (" :<>: ShowType x :<>: Text ") = ... "+ ) -- | Lift values to SMT-Values or decode them. -- -- You can derive an instance of this class if your type is 'Generic'. class Codec a where- -- | Resulting of decoding @a@+ -- | Result of decoding @a@. type Decoded a :: Type type Decoded a = DefaultDecoded a @@ -126,12 +134,29 @@ decode sol (BvuGT x y) = liftA2 (>) (decode sol x) (decode sol y) 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 sol (StrConcat x y) = liftM2 (<>) (decode sol x) (decode sol y)+ decode sol (StrLength x) = toInteger . Text.length <$> decode sol x+ decode sol (StrLT x y) = liftM2 (<) (decode sol x) (decode sol y)+ decode sol (StrLTHE x y) = liftM2 (<=) (decode sol x) (decode sol y)+ decode sol (StrAt x i) = liftM2 (\x' i' -> Text.singleton $ Text.index x' (fromInteger i')) (decode sol x) (decode sol i)+ decode sol (StrSubstring x i j) = liftM3 (\x' (fromInteger -> i') (fromInteger -> j') -> Text.take (j' - i') $ Text.drop i' x') (decode sol x) (decode sol i) (decode sol j)+ decode sol (StrPrefixOf x y) = liftM2 Text.isPrefixOf (decode sol x) (decode sol y)+ decode sol (StrSuffixOf x y) = liftM2 Text.isSuffixOf (decode sol x) (decode sol y)+ decode sol (StrContains x y) = liftM2 (flip Text.isInfixOf) (decode sol x) (decode sol y)+ decode sol (StrIndexOf x y i) = join $ liftM3 (\x' y' (fromInteger -> i') -> Text.findIndex ((y' ==) . Text.singleton) (Text.drop i' x') >>= Just . toInteger) (decode sol x) (decode sol y) (decode sol i)+ decode sol (StrReplace src target replacement) = liftM3 (\src' target' replacement' -> replaceOne target' replacement' src') (decode sol target) (decode sol src) (decode sol replacement)+ where+ replaceOne pattern substitution text+ | Text.null back = text+ | otherwise = Text.concat [front, substitution, Text.drop (Text.length pattern) back]+ where+ (front, back) = Text.breakOn pattern text+ decode sol (StrReplaceAll src target replacement) = liftM3 (\src' target' replacement' -> Text.replace target' replacement' src') (decode sol target) (decode sol src) (decode sol replacement) decode _ (ForAll _ _) = Nothing decode _ (Exists _ _) = Nothing- encode = Constant . wrapValue -instance Codec ()+instance Codec () where type Decoded () = () instance (Codec a, Codec b) => Codec (a,b) instance (Codec a, Codec b, Codec c) => Codec (a,b,c) instance (Codec a, Codec b, Codec c, Codec d) => Codec (a,b,c,d)
src/Language/Hasmtlib/Internal/Expr.hs view
@@ -9,51 +9,59 @@ import Language.Hasmtlib.Type.SMTSort import Language.Hasmtlib.Boolean import Data.Map hiding (toList)-import Data.List (intercalate) import Data.Proxy import Data.Coerce-import Data.Foldable (toList)+import Data.String (IsString(..))+import Data.Text (pack) import Data.ByteString.Builder+import Data.ByteString.Lazy.UTF8 (toString) import qualified Data.Vector.Sized as V import Control.Lens import GHC.TypeLits+import GHC.Generics -- | 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)+newtype SMTVar (t :: SMTSort) = SMTVar { _varId :: Int } deriving (Show, Eq, Ord, Generic) $(makeLenses ''SMTVar) -- | 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)- ArrayValue :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => HaskellType (ArraySort k v) -> Value (ArraySort k v)+ 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)+ StringValue :: HaskellType StringSort -> Value StringSort +deriving instance Eq (HaskellType t) => Eq (Value t)+deriving instance Ord (HaskellType t) => Ord (Value t)+ -- | 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+unwrapValue (IntValue v) = v+unwrapValue (RealValue v) = v+unwrapValue (BoolValue v) = v+unwrapValue (BvValue v) = v+unwrapValue (ArrayValue v) = v+unwrapValue (StringValue v) = v {-# INLINEABLE unwrapValue #-} -- | 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+ SIntSort -> IntValue+ SRealSort -> RealValue+ SBoolSort -> BoolValue+ SBvSort _ -> BvValue SArraySort _ _ -> ArrayValue+ SStringSort -> StringValue {-# INLINEABLE wrapValue #-} -- | An existential wrapper that hides some known 'SMTSort'. type SomeKnownSMTSort f = SomeSMTSort '[KnownSMTSort] f --- | A SMT expression.+-- | Am SMT expression. -- For internal use only. -- For building expressions use the corresponding instances (Num, Boolean, ...). data Expr (t :: SMTSort) where@@ -122,6 +130,19 @@ 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) + StrConcat :: Expr StringSort -> Expr StringSort -> Expr StringSort+ StrLength :: Expr StringSort -> Expr IntSort+ StrLT :: Expr StringSort -> Expr StringSort -> Expr BoolSort+ StrLTHE :: Expr StringSort -> Expr StringSort -> Expr BoolSort+ StrAt :: Expr StringSort -> Expr IntSort -> Expr StringSort+ StrSubstring :: Expr StringSort -> Expr IntSort -> Expr IntSort -> Expr StringSort+ StrPrefixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort+ StrSuffixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort+ StrContains :: Expr StringSort -> Expr StringSort -> Expr BoolSort+ StrIndexOf :: Expr StringSort -> Expr StringSort -> Expr IntSort -> Expr IntSort+ StrReplace :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort+ StrReplaceAll :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort+ -- Just v if quantified var has been created already, Nothing otherwise ForAll :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort Exists :: KnownSMTSort t => Maybe (SMTVar t) -> (Expr t -> Expr BoolSort) -> Expr BoolSort@@ -158,6 +179,16 @@ minBound = Constant $ BvValue minBound maxBound = Constant $ BvValue maxBound +instance Semigroup (Expr StringSort) where+ (<>) = StrConcat++instance Monoid (Expr StringSort) where+ mempty = Constant $ StringValue mempty+ mappend = (<>)++instance IsString (Expr StringSort) where+ fromString = Constant . StringValue . pack+ instance Render (SMTVar t) where render v = "var_" <> intDec (coerce @(SMTVar t) @Int v) {-# INLINEABLE render #-}@@ -176,6 +207,7 @@ 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)+ render (StringValue x) = "\"" <> render x <> "\"" instance KnownSMTSort t => Render (Expr t) where render (Var v) = render v@@ -243,6 +275,19 @@ render (ArrSelect a i) = renderBinary "select" (render a) (render i) render (ArrStore a i v) = renderTernary "store" (render a) (render i) (render v) + render (StrConcat x y) = renderBinary "str.++" (render x) (render y)+ render (StrLength x) = renderUnary "str.len" (render x)+ render (StrLT x y) = renderBinary "str.<" (render x) (render y)+ render (StrLTHE x y) = renderBinary "str.<=" (render x) (render y)+ render (StrAt x i) = renderBinary "str.at" (render x) (render i)+ render (StrSubstring x i j) = renderTernary "str.substr" (render x) (render i) (render j)+ render (StrPrefixOf x y) = renderBinary "str.prefixof" (render x) (render y)+ render (StrSuffixOf x y) = renderBinary "str.suffixof" (render x) (render y)+ render (StrContains x y) = renderBinary "str.contains" (render x) (render y)+ render (StrIndexOf x y i) = renderTernary "str.indexof" (render x) (render y) (render i)+ render (StrReplace x y y') = renderTernary "str.replace" (render x) (render y) (render y')+ render (StrReplaceAll x y y') = renderTernary "str.replace_all" (render x) (render y) (render y')+ render (ForAll mQvar f) = renderQuantifier "forall" mQvar f render (Exists mQvar f) = renderQuantifier "exists" mQvar f @@ -257,70 +302,7 @@ 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+ show = toString . toLazyByteString . render -instance Show (Expr t) where- 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 xs) = "(= " ++ intercalate " " (show <$> toList xs) ++ ")"- show (Distinct xs) = "(distinct " ++ intercalate " " (show <$> toList xs) ++ ")"- 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)))) ++ ")"+instance KnownSMTSort t => Show (Expr t) where+ show = toString . toLazyByteString . render
src/Language/Hasmtlib/Internal/Parser.hs view
@@ -16,14 +16,17 @@ import Language.Hasmtlib.Type.SMTSort import Language.Hasmtlib.Type.Solution import Language.Hasmtlib.Type.ArrayMap+import Language.Hasmtlib.Type.Expr import Data.Bit import Data.Coerce import Data.Proxy import Data.Ratio ((%)) import Data.ByteString import Data.ByteString.Builder-import Data.Attoparsec.ByteString hiding (Result, skipWhile)+import Data.Attoparsec.ByteString hiding (Result, skipWhile, takeTill) import Data.Attoparsec.ByteString.Char8 hiding (Result)+import Data.Text.Encoding (decodeUtf8)+import qualified Data.Text as Text import Control.Applicative import Control.Lens hiding (op) import GHC.TypeNats@@ -83,6 +86,7 @@ <|> (string "Real" *> pure (SomeSMTSort SRealSort)) <|> parseSomeBitVecSort <|> parseSomeArraySort+ <|> (string "String" *> pure (SomeSMTSort SStringSort)) {-# INLINEABLE parseSomeSort #-} parseSomeBitVecSort :: Parser (SomeKnownOrdSMTSort SSMTSort)@@ -115,19 +119,19 @@ -- TODO: Add parseSelect parseExpr :: forall t. KnownSMTSort t => Parser (Expr t)-parseExpr = var <|> constantExpr <|> smtIte+parseExpr = var <|> constantExpr <|> ternary "ite" (ite @(Expr BoolSort)) <|> case sortSing @t of SIntSort -> unary "abs" abs <|> unary "-" negate <|> nary "+" sum <|> binary "-" (-) <|> nary "*" product <|> binary "mod" Mod- <|> toIntFun+ <|> unary "to_int" toIntSort <|> unary "str.len" strLength+ <|> ternary "str.indexof" strIndexOf SRealSort -> unary "abs" abs <|> unary "-" negate <|> nary "+" sum <|> binary "-" (-) <|> nary "*" product <|> binary "/" (/)- <|> toRealFun+ <|> unary "to_real" toRealSort <|> smtPi <|> unary "sqrt" sqrt <|> unary "exp" exp <|> unary "sin" sin <|> unary "cos" cos <|> unary "tan" tan <|> unary "arcsin" asin <|> unary "arccos" acos <|> unary "arctan" atan- SBoolSort -> isIntFun- <|> unary "not" not+ SBoolSort -> unary "not" not <|> nary "and" and <|> nary "or" or <|> binary "=>" (==>) <|> binary "xor" xor <|> binary @IntSort "=" (===) <|> binary @IntSort "distinct" (/==) <|> binary @RealSort "=" (===) <|> binary @RealSort "distinct" (/==)@@ -136,6 +140,10 @@ <|> binary @IntSort ">=" (>=?) <|> binary @IntSort ">" (>?) <|> binary @RealSort "<" (<?) <|> binary @RealSort "<=" (<=?) <|> binary @RealSort ">=" (>=?) <|> binary @RealSort ">" (>?)+ <|> binary @StringSort "str.<" (<?) <|> binary @StringSort "str.<=" (<=?)+ <|> unary "is_int" isIntSort+ <|> binary "str.prefixof" strPrefixOf <|> binary "str.suffixof" strSuffixOf+ <|> binary "str.contains" strContains -- 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@@ -143,14 +151,15 @@ <|> binary "bvadd" (+) <|> binary "bvsub" (-) <|> binary "bvmul" (*) <|> binary "bvudiv" BvuDiv <|> binary "bvurem" BvuRem <|> binary "bvshl" BvShL <|> binary "bvlshr" BvLShR- SArraySort _ _ -> parseStore+ SArraySort _ _ -> ternary "store" ArrStore -- TODO: Add compare ops for all (?) array-sorts+ SStringSort -> binary "str.++" (<>) <|> binary "str.at" strAt <|> ternary "str.substr" StrSubstring+ <|> ternary "str.replace" strReplace <|> ternary "str.replace_all" strReplaceAll var :: Parser (Expr t) var = do _ <- string "var_" vId <- decimal @Int- return $ Var $ coerce vId {-# INLINE var #-} @@ -161,7 +170,8 @@ SBoolSort -> parseBool SBvSort p -> anyBitvector p SArraySort k v -> constArray k v-{-# INLINE constant #-}+ SStringSort -> parseSmtString+{-# INLINEABLE constant #-} constantExpr :: forall t. KnownSMTSort t => Parser (Expr t) constantExpr = Constant . wrapValue <$> constant @t@@ -210,29 +220,12 @@ 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+parseSmtString :: Parser Text.Text+parseSmtString = do+ _ <- char '"'+ s <- decodeUtf8 <$> takeTill (== '"')+ _ <- char '"'+ return s unary :: forall t r. KnownSMTSort t => ByteString -> (Expr t -> Expr r) -> Parser (Expr r) unary opStr op = do@@ -244,7 +237,7 @@ return $ op val {-# INLINE unary #-} -binary :: forall t r. KnownSMTSort t => ByteString -> (Expr t -> Expr t -> Expr r) -> Parser (Expr r)+binary :: forall t u r. (KnownSMTSort t, KnownSMTSort u) => ByteString -> (Expr t -> Expr u -> Expr r) -> Parser (Expr r) binary opStr op = do _ <- char '(' >> skipSpace _ <- string opStr >> skipSpace@@ -255,6 +248,19 @@ return $ l `op` r {-# INLINE binary #-} +ternary :: forall t u v r. (KnownSMTSort t, KnownSMTSort u, KnownSMTSort v) => ByteString -> (Expr t -> Expr u -> Expr v -> Expr r) -> Parser (Expr r)+ternary opStr op = do+ _ <- char '(' >> skipSpace+ _ <- string opStr >> skipSpace+ l <- parseExpr+ _ <- skipSpace+ m <- parseExpr+ _ <- skipSpace+ r <- parseExpr+ _ <- skipSpace >> char ')'+ return $ op l m r+{-# INLINE ternary #-}+ nary :: forall t r. KnownSMTSort t => ByteString -> ([Expr t] -> Expr r) -> Parser (Expr r) nary opStr op = do _ <- char '(' >> skipSpace@@ -267,50 +273,6 @@ smtPi :: Parser (Expr RealSort) smtPi = string "real.pi" *> return pi {-# INLINE smtPi #-}--toRealFun :: Parser (Expr RealSort)-toRealFun = do- _ <- char '(' >> skipSpace- _ <- string "to_real" >> skipSpace- val <- parseExpr- _ <- skipSpace >> char ')'-- return $ ToReal val-{-# INLINEABLE toRealFun #-}--toIntFun :: Parser (Expr IntSort)-toIntFun = do- _ <- char '(' >> skipSpace- _ <- string "to_int" >> skipSpace- val <- parseExpr- _ <- skipSpace >> char ')'-- return $ ToInt val-{-# INLINEABLE toIntFun #-}--isIntFun :: Parser (Expr BoolSort)-isIntFun = do- _ <- char '(' >> skipSpace- _ <- string "is_int" >> skipSpace- val <- parseExpr- _ <- skipSpace >> char ')'-- return $ IsInt val-{-# INLINEABLE isIntFun #-}--smtIte :: forall t. KnownSMTSort t => Parser (Expr t)-smtIte = do- _ <- char '(' >> skipSpace- _ <- string "ite" >> skipSpace- p <- parseExpr @BoolSort- _ <- skipSpace- t <- parseExpr- _ <- skipSpace- f <- parseExpr- _ <- skipSpace >> char ')'-- return $ ite p t f-{-# INLINEABLE smtIte #-} anyValue :: Num a => Parser a -> Parser a anyValue p = negativeValue p <|> p
src/Language/Hasmtlib/Internal/Render.hs view
@@ -3,6 +3,8 @@ import Data.ByteString.Builder import Data.Foldable (foldl') import Data.Sequence+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text.Enc import GHC.TypeNats -- | Render values to their SMTLib2-Lisp form, represented as 'Builder'.@@ -39,6 +41,10 @@ instance Render Builder where render = id+ {-# INLINE render #-}++instance Render Text.Text where+ render = Text.Enc.encodeUtf8Builder {-# INLINE render #-} renderUnary :: Render a => Builder -> a -> Builder
+ src/Language/Hasmtlib/Lens.hs view
@@ -0,0 +1,211 @@+{-# LANGUAGE UndecidableInstances #-}++module Language.Hasmtlib.Lens where++import Language.Hasmtlib.Internal.Expr+import Language.Hasmtlib.Type.Expr+import Language.Hasmtlib.Type.SMTSort+import Language.Hasmtlib.Equatable+import Language.Hasmtlib.Orderable+import Language.Hasmtlib.Iteable+import Data.GADT.Compare+import Control.Lens++type instance Index (Expr StringSort) = Expr IntSort+type instance IxValue (Expr StringSort) = Expr StringSort++instance Ixed (Expr StringSort) where+ ix i f s = f (strAt s i) <&> \a ->+ let l = strSubstring a 0 i+ r = strSubstring a i (strLength a)+ in l <> strReplace r (strAt a i) s++instance AsEmpty (Expr StringSort) where+ _Empty = prism'+ (const mempty)+ (\s -> ite (s === mempty) (Just ()) Nothing)++instance Prefixed (Expr StringSort) where+ prefixed p = prism'+ (p <>)+ (\s -> ite (p `strPrefixOf` s) (Just $ strReplace s p mempty) Nothing)++instance Suffixed (Expr StringSort) where+ suffixed qs = prism'+ (<> qs)+ (\s -> ite (qs `strSuffixOf` s) (Just $ strSubstring s 0 (strLength s - strLength qs)) Nothing)++instance Cons (Expr StringSort) (Expr StringSort) (Expr StringSort) (Expr StringSort) where+ _Cons = prism'+ (uncurry (<>))+ (\s -> ite (strLength s >? 0) (Just (strAt s 0, strSubstring s 1 (strLength s))) Nothing)++instance Snoc (Expr StringSort) (Expr StringSort) (Expr StringSort) (Expr StringSort) where+ _Snoc = prism'+ (uncurry (<>))+ (\s -> ite (strLength s >? 0) (Just (strSubstring s 0 (strLength s - 1), strAt s (strLength s - 1))) Nothing)++type instance Index (Expr (ArraySort k v)) = Expr k+type instance IxValue (Expr (ArraySort k v)) = Expr v++instance (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Ixed (Expr (ArraySort k v)) where+ ix i f arr = f (select arr i) <&> store arr i++-- | **Caution for quantified expressions:** 'plate-function' @f@ will only be applied if quantification already has taken place.(&&)+-- Therefore make sure 'quantify' has been run before.+-- Otherwise the quantified expression and therefore all it's sub-expressions will not have @f@ applied.+instance KnownSMTSort t => Plated (Expr t) where+ plate _ expr@(Var _) = pure expr+ plate _ expr@(Constant _) = pure expr+ plate f (Plus x y) = Plus <$> f x <*> f y+ plate f (Neg x) = Neg <$> f x+ plate f (Mul x y) = Mul <$> f x <*> f y+ plate f (Abs x) = Abs <$> f x+ plate f (Mod x y) = Mod <$> f x <*> f y+ plate f (IDiv x y) = IDiv <$> f x <*> f y+ plate f (Div x y) = Div <$> f x <*> f y+ plate f (LTH x y) = LTH <$> somePlate f x <*> somePlate f y+ plate f (LTHE x y) = LTHE <$> somePlate f x <*> somePlate f y+ plate f (EQU xs) = EQU <$> traverse (somePlate f) xs+ plate f (Distinct xs) = Distinct <$> traverse (somePlate f) xs+ plate f (GTHE x y) = GTHE <$> somePlate f x <*> somePlate f y+ plate f (GTH x y) = GTH <$> somePlate f x <*> somePlate f y+ plate f (Not x) = Not <$> somePlate f x+ plate f (And x y) = And <$> somePlate f x <*> somePlate f y+ plate f (Or x y) = Or <$> somePlate f x <*> somePlate f y+ plate f (Impl x y) = Impl <$> somePlate f x <*> somePlate f y+ plate f (Xor x y) = Xor <$> somePlate f x <*> somePlate f y+ plate _ Pi = pure Pi+ plate f (Sqrt x) = Sqrt <$> f x+ plate f (Exp x) = Exp <$> f x+ plate f (Sin x) = Sin <$> f x+ plate f (Cos x) = Cos <$> f x+ plate f (Tan x) = Tan <$> f x+ plate f (Asin x) = Asin <$> f x+ plate f (Acos x) = Acos <$> f x+ plate f (Atan x) = Atan <$> f x+ plate f (ToReal x) = ToReal <$> somePlate f x+ plate f (ToInt x) = ToInt <$> somePlate f x+ plate f (IsInt x) = IsInt <$> somePlate f x+ plate f (Ite p t n) = Ite <$> somePlate f p <*> f t <*> f n+ plate f (BvNot x) = BvNot <$> f x+ plate f (BvAnd x y) = BvAnd <$> f x <*> f y+ plate f (BvOr x y) = BvOr <$> f x <*> f y+ plate f (BvXor x y) = BvXor <$> f x <*> f y+ plate f (BvNand x y) = BvNand <$> f x <*> f y+ plate f (BvNor x y) = BvNor <$> f x <*> f y+ plate f (BvNeg x) = BvNeg <$> f x+ plate f (BvAdd x y) = BvAdd <$> f x <*> f y+ plate f (BvSub x y) = BvSub <$> f x <*> f y+ plate f (BvMul x y) = BvMul <$> f x <*> f y+ plate f (BvuDiv x y) = BvuDiv <$> f x <*> f y+ plate f (BvuRem x y) = BvuRem <$> f x <*> f y+ plate f (BvShL x y) = BvShL <$> f x <*> f y+ plate f (BvLShR x y) = BvLShR <$> f x <*> f y+ plate f (BvConcat x y) = BvConcat <$> somePlate f x <*> somePlate f y+ plate f (BvRotL i x) = BvRotL i <$> f x+ plate f (BvRotR i x) = BvRotR i <$> f x+ plate f (BvuLT x y) = BvuLT <$> somePlate f x <*> somePlate f y+ plate f (BvuLTHE x y) = BvuLTHE <$> somePlate f x <*> somePlate f y+ plate f (BvuGTHE x y) = BvuGTHE <$> somePlate f x <*> somePlate f y+ plate f (BvuGT x y) = BvuGT <$> somePlate f x <*> somePlate f y+ plate f (ArrSelect i arr) = ArrSelect i <$> somePlate f arr+ plate f (ArrStore i x arr) = ArrStore i <$> somePlate f x <*> somePlate f arr+ plate f (StrConcat x y) = StrConcat <$> f x <*> f y+ plate f (StrLength x) = StrLength <$> somePlate f x+ plate f (StrLT x y) = StrLT <$> somePlate f x <*> somePlate f y+ plate f (StrLTHE x y) = StrLTHE <$> somePlate f x <*> somePlate f y+ plate f (StrAt x i) = StrAt <$> f x <*> somePlate f i+ plate f (StrSubstring x i j) = StrSubstring <$> f x <*> somePlate f i <*> somePlate f j+ plate f (StrPrefixOf x y) = StrPrefixOf <$> somePlate f x <*> somePlate f y+ plate f (StrSuffixOf x y) = StrSuffixOf <$> somePlate f x <*> somePlate f y+ plate f (StrContains x y) = StrContains <$> somePlate f x <*> somePlate f y+ plate f (StrIndexOf x y i) = StrIndexOf <$> somePlate f x <*> somePlate f y <*> f i+ plate f (StrReplace x y y') = StrReplace <$> f x <*> f y <*> f y'+ plate f (StrReplaceAll x y y') = StrReplaceAll <$> f x <*> f y <*> f y'+ plate f (ForAll (Just qv) expr) = ForAll (Just qv) . const <$> somePlate f (expr (Var qv))+ plate _ (ForAll Nothing expr) = pure $ ForAll Nothing expr+ plate f (Exists (Just qv) expr) = Exists (Just qv) . const <$> somePlate f (expr (Var qv))+ plate _ (Exists Nothing expr) = pure $ Exists Nothing expr++-- | Apply the 'plate'-function @f@ for given 'Expr' @expr@ if possible.+-- Otherwise try to apply @f@ for the children of @expr@.+-- **Caution for quantified expressions:** 'plate-function' @f@ will only be applied if quantification already has taken place.(&&)+-- Therefore make sure 'quantify' has been run before.+-- Otherwise the quantified expression and therefore all it's sub-expressions will not have @f@ applied.+somePlate :: forall t f. (KnownSMTSort t, Applicative f) => (Expr t -> f (Expr t)) -> (forall s. KnownSMTSort s => Expr s -> f (Expr s))+somePlate f expr = case geq (sortSing @t) (sortSing' expr) of+ Just Refl -> f expr+ Nothing -> case expr of+ Var _ -> pure expr+ Constant _ -> pure expr+ Plus x y -> Plus <$> somePlate f x <*> somePlate f y+ Neg x -> Neg <$> somePlate f x+ Mul x y -> Mul <$> somePlate f x <*> somePlate f y+ Abs x -> Abs <$> somePlate f x+ Mod x y -> Mod <$> somePlate f x <*> somePlate f y+ IDiv x y -> IDiv <$> somePlate f x <*> somePlate f y+ Div x y -> Div <$> somePlate f x <*> somePlate f y+ LTH x y -> LTH <$> somePlate f x <*> somePlate f y+ LTHE x y -> LTHE <$> somePlate f x <*> somePlate f y+ EQU xs -> EQU <$> traverse (somePlate f) xs+ Distinct xs -> Distinct <$> traverse (somePlate f) xs+ GTHE x y -> GTHE <$> somePlate f x <*> somePlate f y+ GTH x y -> GTH <$> somePlate f x <*> somePlate f y+ Not x -> Not <$> somePlate f x+ And x y -> And <$> somePlate f x <*> somePlate f y+ Or x y -> Or <$> somePlate f x <*> somePlate f y+ Impl x y -> Impl <$> somePlate f x <*> somePlate f y+ Xor x y -> Xor <$> somePlate f x <*> somePlate f y+ Pi -> pure Pi+ Sqrt x -> Sqrt <$> somePlate f x+ Exp x -> Exp <$> somePlate f x+ Sin x -> Sin <$> somePlate f x+ Cos x -> Cos <$> somePlate f x+ Tan x -> Tan <$> somePlate f x+ Asin x -> Asin <$> somePlate f x+ Acos x -> Acos <$> somePlate f x+ Atan x -> Atan <$> somePlate f x+ ToReal x -> ToReal <$> somePlate f x+ ToInt x -> ToInt <$> somePlate f x+ IsInt x -> IsInt <$> somePlate f x+ Ite p t n -> Ite <$> somePlate f p <*> somePlate f t <*> somePlate f n+ BvNot x -> BvNot <$> somePlate f x+ BvAnd x y -> BvAnd <$> somePlate f x <*> somePlate f y+ BvOr x y -> BvOr <$> somePlate f x <*> somePlate f y+ BvXor x y -> BvXor <$> somePlate f x <*> somePlate f y+ BvNand x y -> BvNand <$> somePlate f x <*> somePlate f y+ BvNor x y -> BvNor <$> somePlate f x <*> somePlate f y+ BvNeg x -> BvNeg <$> somePlate f x+ BvAdd x y -> BvAdd <$> somePlate f x <*> somePlate f y+ BvSub x y -> BvSub <$> somePlate f x <*> somePlate f y+ BvMul x y -> BvMul <$> somePlate f x <*> somePlate f y+ BvuDiv x y -> BvuDiv <$> somePlate f x <*> somePlate f y+ BvuRem x y -> BvuRem <$> somePlate f x <*> somePlate f y+ BvShL x y -> BvShL <$> somePlate f x <*> somePlate f y+ BvLShR x y -> BvLShR <$> somePlate f x <*> somePlate f y+ BvConcat x y -> BvConcat <$> somePlate f x <*> somePlate f y+ BvRotL i x -> BvRotL i <$> somePlate f x+ BvRotR i x -> BvRotR i <$> somePlate f x+ BvuLT x y -> BvuLT <$> somePlate f x <*> somePlate f y+ BvuLTHE x y -> BvuLTHE <$> somePlate f x <*> somePlate f y+ BvuGTHE x y -> BvuGTHE <$> somePlate f x <*> somePlate f y+ BvuGT x y -> BvuGT <$> somePlate f x <*> somePlate f y+ ArrSelect i arr -> ArrSelect i <$> somePlate f arr+ ArrStore i x arr -> ArrStore i <$> somePlate f x <*> somePlate f arr+ StrConcat x y -> StrConcat <$> somePlate f x <*> somePlate f y+ StrLength x -> StrLength <$> somePlate f x+ StrLT x y -> StrLT <$> somePlate f x <*> somePlate f y+ StrLTHE x y -> StrLTHE <$> somePlate f x <*> somePlate f y+ StrAt x i -> StrAt <$> somePlate f x <*> somePlate f i+ StrSubstring x i j -> StrSubstring <$> somePlate f x <*> somePlate f i <*> somePlate f j+ StrPrefixOf x y -> StrPrefixOf <$> somePlate f x <*> somePlate f y+ StrSuffixOf x y -> StrSuffixOf <$> somePlate f x <*> somePlate f y+ StrContains x y -> StrContains <$> somePlate f x <*> somePlate f y+ StrIndexOf x y i -> StrIndexOf <$> somePlate f x <*> somePlate f y <*> somePlate f i+ StrReplace x y y' -> StrReplace <$> somePlate f x <*> somePlate f y <*> somePlate f y'+ StrReplaceAll x y y' -> StrReplaceAll <$> somePlate f x <*> somePlate f y <*> somePlate f y'+ ForAll (Just qv) qexpr -> ForAll (Just qv) . const <$> somePlate f (qexpr (Var qv))+ ForAll Nothing qexpr -> pure $ ForAll Nothing qexpr+ Exists (Just qv) qexpr -> Exists (Just qv) . const <$> somePlate f (qexpr (Var qv))+ Exists Nothing qexpr -> pure $ Exists Nothing qexpr
src/Language/Hasmtlib/Orderable.hs view
@@ -85,6 +85,13 @@ (>?) = BvuGT {-# INLINE (>?) #-} +-- | Lexicographic ordering for '(<?)' and reflexive closure of lexicographic ordering for '(<=?)'+instance Orderable (Expr StringSort) where+ (<?) = StrLT+ {-# INLINE (<?) #-}+ (<=?) = StrLTHE+ {-# INLINE (<=?) #-}+ class GEquatable f => GOrderable f where (<?#) :: f a -> f a -> Expr BoolSort (<=?#) :: f a -> f a -> Expr BoolSort
src/Language/Hasmtlib/Type/Expr.hs view
@@ -4,12 +4,13 @@ module Language.Hasmtlib.Type.Expr ( SMTVar(..), varId , Value(..), unwrapValue, wrapValue- , Expr+ , Expr(..) , equal, distinct , bvShL, bvLShR, bvConcat, bvRotL, bvRotR , toIntSort, toRealSort, isIntSort , for_all , exists , select, store+ , strLength, strAt, strSubstring, strPrefixOf, strSuffixOf, strContains, strIndexOf, strReplace, strReplaceAll ) where @@ -118,3 +119,56 @@ -- | Checks whether an expression of type 'RealSort' may be safely converted to type 'IntSort'. isIntSort :: Expr RealSort -> Expr BoolSort isIntSort = IsInt++-- | Length of a string.+strLength :: Expr StringSort -> Expr IntSort+strLength = StrLength++-- | Singleton string containing a character at given position+-- or empty string when position is out of range.+-- The leftmost position is 0.+strAt :: Expr StringSort -> Expr IntSort -> Expr StringSort+strAt = StrAt++-- | @(strSubstring s i n)@ evaluates to the longest (unscattered) substring+-- of @s@ of length at most @n@ starting at position @i@.+-- It evaluates to the empty string if @n@ is negative or @i@ is not in+-- the interval @[0,l-1]@ where @l@ is the length of @s@.+strSubstring :: Expr StringSort -> Expr IntSort -> Expr IntSort -> Expr StringSort+strSubstring = StrSubstring++-- | First string is a prefix of second one.+-- @(str.prefixof s t)@ is @true@ iff @s@ is a prefix of @t@.+strPrefixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort+strPrefixOf = StrPrefixOf++-- | First string is a suffix of second one.+-- @(str.suffixof s t)@ is @true@ iff @s@ is a suffix of @t@.+strSuffixOf :: Expr StringSort -> Expr StringSort -> Expr BoolSort+strSuffixOf = StrSuffixOf++-- | First string contains second one+-- @(str.contains s t)@ iff @s@ contains @t@.+strContains :: Expr StringSort -> Expr StringSort -> Expr BoolSort+strContains = StrContains++-- | Index of first occurrence of second string in first one starting at the position specified by the third argument.+-- @(str.indexof s t i)@, with @0 <= i <= |s|@ is the position of the first+-- occurrence of @t@ in @s@ at or after position @i@, if any.+-- Otherwise, it is @-1@. Note that the result is @i@ whenever @i@ is within+-- the range @[0, |s|]@ and @t@ is empty.+strIndexOf :: Expr StringSort -> Expr StringSort -> Expr IntSort -> Expr IntSort+strIndexOf = StrIndexOf++-- | @(str.replace s t t')@ is the string obtained by replacing the first+-- occurrence of @t@ in @s@, if any, by @t'@. Note that if @t@ is empty, the+-- result is to prepend @t'@ to @s@; also, if @t@ does not occur in @s@ then+-- the result is @s@.+strReplace :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort+strReplace = StrReplace++-- | @(str.replace_all s t t’)@ is @s@ if @t@ is the empty string. Otherwise, it+-- is the string obtained from @s@ by replacing all occurrences of @t@ in @s@+-- by @t’@, starting with the first occurrence and proceeding in left-to-right order.+strReplaceAll :: Expr StringSort -> Expr StringSort -> Expr StringSort -> Expr StringSort+strReplaceAll = StrReplaceAll
src/Language/Hasmtlib/Type/SMTSort.hs view
@@ -10,6 +10,7 @@ import Data.Kind import Data.Proxy import Data.ByteString.Builder+import qualified Data.Text as Text import Control.Lens import GHC.TypeLits @@ -20,6 +21,7 @@ | RealSort -- ^ Sort of Real | BvSort Nat -- ^ Sort of BitVec with length n | ArraySort SMTSort SMTSort -- ^ Sort of Array with indices k and values v+ | StringSort -- ^ Sort of String -- | Injective type-family that computes the Haskell 'Type' of an 'SMTSort'. type family HaskellType (t :: SMTSort) = (r :: Type) | r -> t where@@ -28,14 +30,16 @@ HaskellType BoolSort = Bool HaskellType (BvSort n) = Bitvec n HaskellType (ArraySort k v) = ConstArray (HaskellType k) (HaskellType v)+ HaskellType StringSort = Text.Text -- | 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)- SArraySort :: (KnownSMTSort k, KnownSMTSort v, Ord (HaskellType k)) => Proxy k -> Proxy v -> SSMTSort (ArraySort k v)+ 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)+ SStringSort :: SSMTSort StringSort deriving instance Show (SSMTSort t) deriving instance Eq (SSMTSort t)@@ -46,8 +50,14 @@ geq SRealSort SRealSort = Just Refl geq SBoolSort SBoolSort = Just Refl geq (SBvSort n) (SBvSort m) = case sameNat n m of+ Nothing -> Nothing Just Refl -> Just Refl+ geq (SArraySort k v) (SArraySort k' v') = case geq (sortSing' k) (sortSing' k') of Nothing -> Nothing+ Just Refl -> case geq (sortSing' v) (sortSing' v') of+ Nothing -> Nothing+ Just Refl -> Just Refl+ geq SStringSort SStringSort = Just Refl geq _ _ = Nothing instance GCompare SSMTSort where@@ -65,6 +75,7 @@ GEQ -> GEQ GGT -> GGT GGT -> GGT+ gcompare SStringSort SStringSort = GEQ gcompare SBoolSort _ = GLT gcompare _ SBoolSort = GGT gcompare SIntSort _ = GLT@@ -73,6 +84,8 @@ gcompare _ SRealSort = GGT gcompare (SArraySort _ _) _ = GLT gcompare _ (SArraySort _ _) = GGT+ gcompare SStringSort _ = GLT+ gcompare _ SStringSort = GGT -- | Compute singleton 'SSMTSort' from it's promoted type 'SMTSort'. class KnownSMTSort (t :: SMTSort) where sortSing :: SSMTSort t@@ -82,6 +95,7 @@ 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)+instance KnownSMTSort StringSort where sortSing = SStringSort -- | Wrapper for 'sortSing' which takes a 'Proxy' sortSing' :: forall prxy t. KnownSMTSort t => prxy t -> SSMTSort t@@ -108,4 +122,5 @@ render SRealSort = "Real" render (SBvSort p) = renderBinary "_" ("BitVec" :: Builder) (natVal p) render (SArraySort k v) = renderBinary "Array" (sortSing' k) (sortSing' v)+ render SStringSort = "String" {-# INLINEABLE render #-}