co-feldspar-0.1.0.1: src/Feldspar/Verify/SMT.hs
module Feldspar.Verify.SMT
( module Feldspar.Verify.SMT
, module SimpleSMT
)
where
import Data.List
import Control.Monad.State.Strict
import Control.Applicative
import SimpleSMT(
SExpr(..), Result(..), Value(..)
, bool, int, real, fun, fam, ite
, tBool, tInt, tReal, tArray, tBits
, select, store, concat, extract
, bvULt, bvULeq, bvSLt, bvSLeq, bvNeg, bvAdd, bvSub, bvMul, bvUDiv
, bvURem, bvSDiv, bvSRem, bvAnd, bvOr, bvNot, bvXOr, bvShl, bvAShr, bvLShr
, signExtend, zeroExtend, realDiv
, add, sub, mul, neg, abs, lt, leq, gt, geq, implies)
-- , newLogger)
import qualified SimpleSMT as SMT
--------------------------------------------------------------------------------
-- * Simple SMT front-end.
--------------------------------------------------------------------------------
type SMT = StateT SMTState IO
data SMTState = SMTState {
st_solver :: SMT.Solver
, st_next :: Integer }
runZ3 :: [String] -> SMT a -> IO a
runZ3 args m = do
--logger <- fmap Just (SMT.newLogger 0)
let logger = Nothing
solver <- SMT.newSolver "z3" (["-smt2", "-in", "-t:10000"] ++ args) logger
--solver <- SMT.newSolver "cvc4" (["--lang=smt", "--force-logic=ALL", "--incremental","-"] ++ args) logger
evalStateT m (SMTState solver 0)
freshNum :: SMT Integer
freshNum = do
st <- get
put st { st_next = st_next st + 1 }
return (st_next st)
withSolver :: (SMT.Solver -> SMT a) -> SMT a
withSolver k = do
st <- get
k (st_solver st)
stack :: SMT a -> SMT a
stack m = withSolver $ \solver ->
lift (SMT.push solver) *> m <* lift (SMT.pop solver)
not :: SExpr -> SExpr
not p
| p == bool True = bool False
| p == bool False = bool True
| otherwise = SMT.not p
conj :: [SExpr] -> SExpr
conj xs | bool False `elem` xs = bool False
conj [] = bool True
conj [x] = x
conj xs = fun "and" xs
disj :: [SExpr] -> SExpr
disj xs | bool True `elem` xs = bool True
disj [] = bool False
disj [x] = x
disj xs = fun "or" xs
(.||.), (.&&.) :: SExpr -> SExpr -> SExpr
x .||. y = disj [x, y]
x .&&. y = conj [x, y]
eq :: SExpr -> SExpr -> SExpr
eq x y
| x == y = bool True
| otherwise = SMT.eq x y
setOption :: String -> String -> SMT ()
setOption opt val = withSolver $ \solver -> lift (SMT.setOption solver opt val)
getExpr :: SExpr -> SMT Value
getExpr exp = withSolver $ \solver -> lift (SMT.getExpr solver exp)
assert :: SExpr -> SMT ()
assert expr = withSolver $ \solver -> lift (SMT.assert solver expr)
simplify :: SExpr -> SMT SExpr
simplify expr = withSolver $ \solver -> lift (SMT.command solver (fun "simplify" [expr]))
assertSimp :: SExpr -> SMT ()
assertSimp expr = simplify expr >>= assert
check :: SMT Result
check = withSolver $ \solver -> lift (SMT.check solver)
declare :: String -> SExpr -> SMT SExpr
declare name ty = withSolver $ \solver -> lift (SMT.declare solver name ty)
declareFun :: String -> [SExpr] -> SExpr -> SMT SExpr
declareFun name args res = withSolver $ \solver -> lift (SMT.declareFun solver name args res)
declareSort :: String -> SMT ()
declareSort name = withSolver $ \solver -> lift (SMT.simpleCommand solver ["declare-sort", name])
--------------------------------------------------------------------------------
-- ** Show SMT expressions.
--------------------------------------------------------------------------------
showSExpr :: SExpr -> String
showSExpr exp = SMT.showsSExpr exp ""
showValue :: Value -> String
showValue (Bool x) = show x
showValue (Int x) = show x
showValue (Real x) = show x
showValue (Bits _ x) = show x
showValue (Other x) = showSExpr x
showArray :: Value -> SExpr -> SMT String
showArray n arr = do
vals <- sequence [ getExpr (select arr i) | i <- take cutoff (indexes n) ]
if length (take (cutoff+1) (indexes n)) <= cutoff
then
return ("{" ++ intercalate ", " (map showValue vals) ++ "}")
else
return ("{" ++ intercalate ", " (map showValue vals) ++ ", ...}")
where
cutoff :: Int
cutoff = 20
indexes :: Value -> [SExpr]
indexes (Int n) = map int [0..n-1]
indexes (Bits w n) = map (bits w) [0..n-1]
bits :: Int -> Integer -> SExpr
bits w n = List [Atom "_", Atom ("bv" ++ show m), int (fromIntegral w)]
where
m = n `mod` (2^w)
--------------------------------------------------------------------------------