{-# LANGUAGE Safe #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE PatternGuards #-}
module SimpleSMT
(
Solver(..)
, newSolver
, ackCommand
, simpleCommand
, simpleCommandMaybe
, loadFile
, loadString
, SExpr(..)
, showsSExpr, ppSExpr, readSExpr
, Logger(..)
, newLogger
, withLogLevel
, logMessageAt
, logIndented
, setLogic, setLogicMaybe
, setOption, setOptionMaybe
, produceUnsatCores
, named
, push, pushMany
, pop, popMany
, inNewScope
, declare
, declareFun
, declareDatatype
, define
, defineFun
, defineFunRec
, defineFunsRec
, assert
, check
, Result(..)
, getExprs, getExpr
, getConsts, getConst
, getUnsatCore
, Value(..)
, sexprToVal
, fam
, fun
, const
, app
, quoteSymbol
, symbol
, keyword
, as
, tInt
, tBool
, tReal
, tArray
, tBits
, int
, real
, bool
, bvBin
, bvHex
, value
, not
, and
, andMany
, or
, orMany
, xor
, implies
, ite
, eq
, distinct
, gt
, lt
, geq
, leq
, bvULt
, bvULeq
, bvSLt
, bvSLeq
, add
, addMany
, sub
, neg
, mul
, abs
, div
, mod
, divisible
, realDiv
, toInt
, toReal
, concat
, extract
, bvNot
, bvNeg
, bvAnd
, bvXOr
, bvOr
, bvAdd
, bvSub
, bvMul
, bvUDiv
, bvURem
, bvSDiv
, bvSRem
, bvShl
, bvLShr
, bvAShr
, signExtend
, zeroExtend
, select
, store
) where
import Prelude hiding (not, and, or, abs, div, mod, concat, const)
import qualified Prelude as P
import Data.Char(isSpace, isDigit)
import Data.List(unfoldr,intersperse)
import Data.Bits(testBit)
import Data.IORef(newIORef, atomicModifyIORef, modifyIORef', readIORef,
writeIORef)
import System.Process(runInteractiveProcess, waitForProcess)
import System.IO (hFlush, hGetLine, hGetContents, hPutStrLn, stdout, hClose)
import System.Exit(ExitCode)
import qualified Control.Exception as X
import Control.Concurrent(forkIO)
import Control.Monad(forever,when)
import Text.Read(readMaybe)
import Data.Ratio((%), numerator, denominator)
import Numeric(showHex, readHex, showFFloat)
data Result = Sat
| Unsat
| Unknown
deriving (Result -> Result -> Bool
(Result -> Result -> Bool)
-> (Result -> Result -> Bool) -> Eq Result
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Result -> Result -> Bool
$c/= :: Result -> Result -> Bool
== :: Result -> Result -> Bool
$c== :: Result -> Result -> Bool
Eq,Int -> Result -> ShowS
[Result] -> ShowS
Result -> String
(Int -> Result -> ShowS)
-> (Result -> String) -> ([Result] -> ShowS) -> Show Result
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Result] -> ShowS
$cshowList :: [Result] -> ShowS
show :: Result -> String
$cshow :: Result -> String
showsPrec :: Int -> Result -> ShowS
$cshowsPrec :: Int -> Result -> ShowS
Show)
data Value = Bool !Bool
| Int !Integer
| Real !Rational
| Bits !Int !Integer
| Other !SExpr
deriving (Value -> Value -> Bool
(Value -> Value -> Bool) -> (Value -> Value -> Bool) -> Eq Value
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Value -> Value -> Bool
$c/= :: Value -> Value -> Bool
== :: Value -> Value -> Bool
$c== :: Value -> Value -> Bool
Eq,Int -> Value -> ShowS
[Value] -> ShowS
Value -> String
(Int -> Value -> ShowS)
-> (Value -> String) -> ([Value] -> ShowS) -> Show Value
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Value] -> ShowS
$cshowList :: [Value] -> ShowS
show :: Value -> String
$cshow :: Value -> String
showsPrec :: Int -> Value -> ShowS
$cshowsPrec :: Int -> Value -> ShowS
Show)
data SExpr = Atom String
| List [SExpr]
deriving (SExpr -> SExpr -> Bool
(SExpr -> SExpr -> Bool) -> (SExpr -> SExpr -> Bool) -> Eq SExpr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SExpr -> SExpr -> Bool
$c/= :: SExpr -> SExpr -> Bool
== :: SExpr -> SExpr -> Bool
$c== :: SExpr -> SExpr -> Bool
Eq, Eq SExpr
Eq SExpr
-> (SExpr -> SExpr -> Ordering)
-> (SExpr -> SExpr -> Bool)
-> (SExpr -> SExpr -> Bool)
-> (SExpr -> SExpr -> Bool)
-> (SExpr -> SExpr -> Bool)
-> (SExpr -> SExpr -> SExpr)
-> (SExpr -> SExpr -> SExpr)
-> Ord SExpr
SExpr -> SExpr -> Bool
SExpr -> SExpr -> Ordering
SExpr -> SExpr -> SExpr
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SExpr -> SExpr -> SExpr
$cmin :: SExpr -> SExpr -> SExpr
max :: SExpr -> SExpr -> SExpr
$cmax :: SExpr -> SExpr -> SExpr
>= :: SExpr -> SExpr -> Bool
$c>= :: SExpr -> SExpr -> Bool
> :: SExpr -> SExpr -> Bool
$c> :: SExpr -> SExpr -> Bool
<= :: SExpr -> SExpr -> Bool
$c<= :: SExpr -> SExpr -> Bool
< :: SExpr -> SExpr -> Bool
$c< :: SExpr -> SExpr -> Bool
compare :: SExpr -> SExpr -> Ordering
$ccompare :: SExpr -> SExpr -> Ordering
$cp1Ord :: Eq SExpr
Ord, Int -> SExpr -> ShowS
[SExpr] -> ShowS
SExpr -> String
(Int -> SExpr -> ShowS)
-> (SExpr -> String) -> ([SExpr] -> ShowS) -> Show SExpr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SExpr] -> ShowS
$cshowList :: [SExpr] -> ShowS
show :: SExpr -> String
$cshow :: SExpr -> String
showsPrec :: Int -> SExpr -> ShowS
$cshowsPrec :: Int -> SExpr -> ShowS
Show)
showsSExpr :: SExpr -> ShowS
showsSExpr :: SExpr -> ShowS
showsSExpr SExpr
ex =
case SExpr
ex of
Atom String
x -> String -> ShowS
showString String
x
List [SExpr]
es -> Char -> ShowS
showChar Char
'(' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(SExpr -> ShowS -> ShowS) -> ShowS -> [SExpr] -> ShowS
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\SExpr
e ShowS
m -> SExpr -> ShowS
showsSExpr SExpr
e ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
m)
(Char -> ShowS
showChar Char
')') [SExpr]
es
ppSExpr :: SExpr -> ShowS
ppSExpr :: SExpr -> ShowS
ppSExpr = Int -> SExpr -> ShowS
go Int
0
where
tab :: Int -> ShowS
tab Int
n = String -> ShowS
showString (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
n Char
' ')
many :: [b -> b] -> b -> b
many = ((b -> b) -> (b -> b) -> b -> b) -> (b -> b) -> [b -> b] -> b -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (b -> b) -> (b -> b) -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) b -> b
forall a. a -> a
id
new :: Int -> SExpr -> ShowS
new Int
n SExpr
e = Char -> ShowS
showChar Char
'\n' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
tab Int
n ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SExpr -> ShowS
go Int
n SExpr
e
small :: t -> [SExpr] -> Maybe [ShowS]
small t
n [SExpr]
es =
case [SExpr]
es of
[] -> [ShowS] -> Maybe [ShowS]
forall a. a -> Maybe a
Just []
SExpr
e : [SExpr]
more
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
<= t
0 -> Maybe [ShowS]
forall a. Maybe a
Nothing
| Bool
otherwise -> case SExpr
e of
Atom String
x -> (String -> ShowS
showString String
x ShowS -> [ShowS] -> [ShowS]
forall a. a -> [a] -> [a]
:) ([ShowS] -> [ShowS]) -> Maybe [ShowS] -> Maybe [ShowS]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t -> [SExpr] -> Maybe [ShowS]
small (t
nt -> t -> t
forall a. Num a => a -> a -> a
-t
1) [SExpr]
more
SExpr
_ -> Maybe [ShowS]
forall a. Maybe a
Nothing
go :: Int -> SExpr -> ShowS
go :: Int -> SExpr -> ShowS
go Int
n SExpr
ex =
case SExpr
ex of
Atom String
x -> String -> ShowS
showString String
x
List [SExpr]
es
| Just [ShowS]
fs <- Integer -> [SExpr] -> Maybe [ShowS]
forall t. (Ord t, Num t) => t -> [SExpr] -> Maybe [ShowS]
small Integer
5 [SExpr]
es ->
Char -> ShowS
showChar Char
'(' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ShowS] -> ShowS
forall b. [b -> b] -> b -> b
many (ShowS -> [ShowS] -> [ShowS]
forall a. a -> [a] -> [a]
intersperse (Char -> ShowS
showChar Char
' ') [ShowS]
fs) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
')'
List (Atom String
x : [SExpr]
es) -> String -> ShowS
showString String
"(" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
x ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
[ShowS] -> ShowS
forall b. [b -> b] -> b -> b
many ((SExpr -> ShowS) -> [SExpr] -> [ShowS]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> SExpr -> ShowS
new (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3)) [SExpr]
es) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
")"
List [SExpr]
es -> String -> ShowS
showString String
"(" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ShowS] -> ShowS
forall b. [b -> b] -> b -> b
many ((SExpr -> ShowS) -> [SExpr] -> [ShowS]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> SExpr -> ShowS
new (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)) [SExpr]
es) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
")"
readSExpr :: String -> Maybe (SExpr, String)
readSExpr :: String -> Maybe (SExpr, String)
readSExpr (Char
c : String
more) | Char -> Bool
isSpace Char
c = String -> Maybe (SExpr, String)
readSExpr String
more
readSExpr (Char
';' : String
more) = String -> Maybe (SExpr, String)
readSExpr (String -> Maybe (SExpr, String))
-> String -> Maybe (SExpr, String)
forall a b. (a -> b) -> a -> b
$ Int -> ShowS
forall a. Int -> [a] -> [a]
drop Int
1 ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n') String
more
readSExpr (Char
'|' : String
more) = do (String
sym, Char
'|' : String
rest) <- (String, String) -> Maybe (String, String)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
(/=) Char
'|') String
more)
(SExpr, String) -> Maybe (SExpr, String)
forall a. a -> Maybe a
Just (String -> SExpr
Atom (Char
'|' Char -> ShowS
forall a. a -> [a] -> [a]
: String
sym String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'|']), String
rest)
readSExpr (Char
'(' : String
more) = do ([SExpr]
xs,String
more1) <- String -> Maybe ([SExpr], String)
list String
more
(SExpr, String) -> Maybe (SExpr, String)
forall (m :: * -> *) a. Monad m => a -> m a
return ([SExpr] -> SExpr
List [SExpr]
xs, String
more1)
where
list :: String -> Maybe ([SExpr], String)
list (Char
c : String
txt) | Char -> Bool
isSpace Char
c = String -> Maybe ([SExpr], String)
list String
txt
list (Char
')' : String
txt) = ([SExpr], String) -> Maybe ([SExpr], String)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], String
txt)
list String
txt = do (SExpr
v,String
txt1) <- String -> Maybe (SExpr, String)
readSExpr String
txt
([SExpr]
vs,String
txt2) <- String -> Maybe ([SExpr], String)
list String
txt1
([SExpr], String) -> Maybe ([SExpr], String)
forall (m :: * -> *) a. Monad m => a -> m a
return (SExpr
vSExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
:[SExpr]
vs, String
txt2)
readSExpr String
txt = case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
end String
txt of
(String
as,String
bs) | Bool -> Bool
P.not (String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
as) -> (SExpr, String) -> Maybe (SExpr, String)
forall a. a -> Maybe a
Just (String -> SExpr
Atom String
as, String
bs)
(String, String)
_ -> Maybe (SExpr, String)
forall a. Maybe a
Nothing
where end :: Char -> Bool
end Char
x = Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
')' Bool -> Bool -> Bool
|| Char -> Bool
isSpace Char
x
data Solver = Solver
{ Solver -> SExpr -> IO SExpr
command :: SExpr -> IO SExpr
, Solver -> IO ExitCode
stop :: IO ExitCode
}
newSolver :: String ->
[String] ->
Maybe Logger ->
IO Solver
newSolver :: String -> [String] -> Maybe Logger -> IO Solver
newSolver String
exe [String]
opts Maybe Logger
mbLog =
do (Handle
hIn, Handle
hOut, Handle
hErr, ProcessHandle
h) <- String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess String
exe [String]
opts Maybe String
forall a. Maybe a
Nothing Maybe [(String, String)]
forall a. Maybe a
Nothing
let info :: String -> IO ()
info String
a = case Maybe Logger
mbLog of
Maybe Logger
Nothing -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just Logger
l -> Logger -> String -> IO ()
logMessage Logger
l String
a
ThreadId
_ <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (do String
errs <- Handle -> IO String
hGetLine Handle
hErr
String -> IO ()
info (String
"[stderr] " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
errs))
IO () -> (SomeException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`X.catch` \X.SomeException {} -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
IO (Maybe SExpr)
getResponse <-
do String
txt <- Handle -> IO String
hGetContents Handle
hOut
IORef [SExpr]
ref <- [SExpr] -> IO (IORef [SExpr])
forall a. a -> IO (IORef a)
newIORef ((String -> Maybe (SExpr, String)) -> String -> [SExpr]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr String -> Maybe (SExpr, String)
readSExpr String
txt)
IO (Maybe SExpr) -> IO (IO (Maybe SExpr))
forall (m :: * -> *) a. Monad m => a -> m a
return (IO (Maybe SExpr) -> IO (IO (Maybe SExpr)))
-> IO (Maybe SExpr) -> IO (IO (Maybe SExpr))
forall a b. (a -> b) -> a -> b
$ IORef [SExpr]
-> ([SExpr] -> ([SExpr], Maybe SExpr)) -> IO (Maybe SExpr)
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef [SExpr]
ref (([SExpr] -> ([SExpr], Maybe SExpr)) -> IO (Maybe SExpr))
-> ([SExpr] -> ([SExpr], Maybe SExpr)) -> IO (Maybe SExpr)
forall a b. (a -> b) -> a -> b
$ \[SExpr]
xs ->
case [SExpr]
xs of
[] -> ([SExpr]
xs, Maybe SExpr
forall a. Maybe a
Nothing)
SExpr
y : [SExpr]
ys -> ([SExpr]
ys, SExpr -> Maybe SExpr
forall a. a -> Maybe a
Just SExpr
y)
let cmd :: SExpr -> IO ()
cmd SExpr
c = do let txt :: String
txt = SExpr -> ShowS
showsSExpr SExpr
c String
""
String -> IO ()
info (String
"[send->] " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
txt)
Handle -> String -> IO ()
hPutStrLn Handle
hIn String
txt
Handle -> IO ()
hFlush Handle
hIn
command :: SExpr -> IO SExpr
command SExpr
c =
do SExpr -> IO ()
cmd SExpr
c
Maybe SExpr
mb <- IO (Maybe SExpr)
getResponse
case Maybe SExpr
mb of
Just SExpr
res -> do String -> IO ()
info (String
"[<-recv] " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
res String
"")
SExpr -> IO SExpr
forall (m :: * -> *) a. Monad m => a -> m a
return SExpr
res
Maybe SExpr
Nothing -> String -> IO SExpr
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Missing response from solver"
stop :: IO ExitCode
stop =
do SExpr -> IO ()
cmd ([SExpr] -> SExpr
List [String -> SExpr
Atom String
"exit"])
ExitCode
ec <- ProcessHandle -> IO ExitCode
waitForProcess ProcessHandle
h
IO () -> (IOException -> IO ()) -> IO ()
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
X.catch (do Handle -> IO ()
hClose Handle
hIn
Handle -> IO ()
hClose Handle
hOut
Handle -> IO ()
hClose Handle
hErr)
(\IOException
ex -> String -> IO ()
info (IOException -> String
forall a. Show a => a -> String
show (IOException
ex::X.IOException)))
ExitCode -> IO ExitCode
forall (m :: * -> *) a. Monad m => a -> m a
return ExitCode
ec
solver :: Solver
solver = Solver :: (SExpr -> IO SExpr) -> IO ExitCode -> Solver
Solver { IO ExitCode
SExpr -> IO SExpr
stop :: IO ExitCode
command :: SExpr -> IO SExpr
stop :: IO ExitCode
command :: SExpr -> IO SExpr
.. }
Solver -> String -> String -> IO ()
setOption Solver
solver String
":print-success" String
"true"
Solver -> String -> String -> IO ()
setOption Solver
solver String
":produce-models" String
"true"
Solver -> IO Solver
forall (m :: * -> *) a. Monad m => a -> m a
return Solver
solver
loadFile :: Solver -> FilePath -> IO ()
loadFile :: Solver -> String -> IO ()
loadFile Solver
s String
file = Solver -> String -> IO ()
loadString Solver
s (String -> IO ()) -> IO String -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> IO String
readFile String
file
loadString :: Solver -> String -> IO ()
loadString :: Solver -> String -> IO ()
loadString Solver
s String
str = String -> IO ()
go (ShowS
dropComments String
str)
where
go :: String -> IO ()
go String
txt
| (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isSpace String
txt = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise =
case String -> Maybe (SExpr, String)
readSExpr String
txt of
Just (SExpr
e,String
rest) -> Solver -> SExpr -> IO SExpr
command Solver
s SExpr
e IO SExpr -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> IO ()
go String
rest
Maybe (SExpr, String)
Nothing -> String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ String
"Failed to parse SMT file."
, String
txt
]
dropComments :: ShowS
dropComments = [String] -> String
unlines ([String] -> String) -> (String -> [String]) -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ShowS
dropComment ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines
dropComment :: ShowS
dropComment String
xs = case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
';') String
xs of
(String
as,Char
_:String
_) -> String
as
(String, String)
_ -> String
xs
ackCommand :: Solver -> SExpr -> IO ()
ackCommand :: Solver -> SExpr -> IO ()
ackCommand Solver
proc SExpr
c =
do SExpr
res <- Solver -> SExpr -> IO SExpr
command Solver
proc SExpr
c
case SExpr
res of
Atom String
"success" -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
SExpr
_ -> String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Unexpected result from the SMT solver:"
, String
" Expected: success"
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
res String
""
]
simpleCommand :: Solver -> [String] -> IO ()
simpleCommand :: Solver -> [String] -> IO ()
simpleCommand Solver
proc = Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> ([String] -> SExpr) -> [String] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SExpr] -> SExpr
List ([SExpr] -> SExpr) -> ([String] -> [SExpr]) -> [String] -> SExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> SExpr) -> [String] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map String -> SExpr
Atom
simpleCommandMaybe :: Solver -> [String] -> IO Bool
simpleCommandMaybe :: Solver -> [String] -> IO Bool
simpleCommandMaybe Solver
proc [String]
c =
do SExpr
res <- Solver -> SExpr -> IO SExpr
command Solver
proc ([SExpr] -> SExpr
List ((String -> SExpr) -> [String] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map String -> SExpr
Atom [String]
c))
case SExpr
res of
Atom String
"success" -> Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
Atom String
"unsupported" -> Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
SExpr
_ -> String -> IO Bool
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO Bool) -> String -> IO Bool
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Unexpected result from the SMT solver:"
, String
" Expected: success or unsupported"
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
res String
""
]
setOption :: Solver -> String -> String -> IO ()
setOption :: Solver -> String -> String -> IO ()
setOption Solver
s String
x String
y = Solver -> [String] -> IO ()
simpleCommand Solver
s [ String
"set-option", String
x, String
y ]
setOptionMaybe :: Solver -> String -> String -> IO Bool
setOptionMaybe :: Solver -> String -> String -> IO Bool
setOptionMaybe Solver
s String
x String
y = Solver -> [String] -> IO Bool
simpleCommandMaybe Solver
s [ String
"set-option", String
x, String
y ]
setLogic :: Solver -> String -> IO ()
setLogic :: Solver -> String -> IO ()
setLogic Solver
s String
x = Solver -> [String] -> IO ()
simpleCommand Solver
s [ String
"set-logic", String
x ]
setLogicMaybe :: Solver -> String -> IO Bool
setLogicMaybe :: Solver -> String -> IO Bool
setLogicMaybe Solver
s String
x = Solver -> [String] -> IO Bool
simpleCommandMaybe Solver
s [ String
"set-logic", String
x ]
produceUnsatCores :: Solver -> IO Bool
produceUnsatCores :: Solver -> IO Bool
produceUnsatCores Solver
s = Solver -> String -> String -> IO Bool
setOptionMaybe Solver
s String
":produce-unsat-cores" String
"true"
push :: Solver -> IO ()
push :: Solver -> IO ()
push Solver
proc = Solver -> Integer -> IO ()
pushMany Solver
proc Integer
1
pop :: Solver -> IO ()
pop :: Solver -> IO ()
pop Solver
proc = Solver -> Integer -> IO ()
popMany Solver
proc Integer
1
pushMany :: Solver -> Integer -> IO ()
pushMany :: Solver -> Integer -> IO ()
pushMany Solver
proc Integer
n = Solver -> [String] -> IO ()
simpleCommand Solver
proc [ String
"push", Integer -> String
forall a. Show a => a -> String
show Integer
n ]
popMany :: Solver -> Integer -> IO ()
popMany :: Solver -> Integer -> IO ()
popMany Solver
proc Integer
n = Solver -> [String] -> IO ()
simpleCommand Solver
proc [ String
"pop", Integer -> String
forall a. Show a => a -> String
show Integer
n ]
inNewScope :: Solver -> IO a -> IO a
inNewScope :: Solver -> IO a -> IO a
inNewScope Solver
s IO a
m =
do Solver -> IO ()
push Solver
s
IO a
m IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
`X.finally` Solver -> IO ()
pop Solver
s
declare :: Solver -> String -> SExpr -> IO SExpr
declare :: Solver -> String -> SExpr -> IO SExpr
declare Solver
proc String
f SExpr
t = Solver -> String -> [SExpr] -> SExpr -> IO SExpr
declareFun Solver
proc String
f [] SExpr
t
declareFun :: Solver -> String -> [SExpr] -> SExpr -> IO SExpr
declareFun :: Solver -> String -> [SExpr] -> SExpr -> IO SExpr
declareFun Solver
proc String
f [SExpr]
as SExpr
r =
do Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [SExpr] -> SExpr
fun String
"declare-fun" [ String -> SExpr
Atom String
f, [SExpr] -> SExpr
List [SExpr]
as, SExpr
r ]
SExpr -> IO SExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> SExpr
const String
f)
declareDatatype ::
Solver ->
String ->
[String] ->
[(String, [(String, SExpr)])] ->
IO ()
declareDatatype :: Solver
-> String -> [String] -> [(String, [(String, SExpr)])] -> IO ()
declareDatatype Solver
proc String
t [] [(String, [(String, SExpr)])]
cs =
Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> [SExpr] -> SExpr
fun String
"declare-datatype" ([SExpr] -> SExpr) -> [SExpr] -> SExpr
forall a b. (a -> b) -> a -> b
$
[ String -> SExpr
Atom String
t
, [SExpr] -> SExpr
List [ [SExpr] -> SExpr
List (String -> SExpr
Atom String
c SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: [ [SExpr] -> SExpr
List [String -> SExpr
Atom String
s, SExpr
argTy] | (String
s, SExpr
argTy) <- [(String, SExpr)]
args]) | (String
c, [(String, SExpr)]
args) <- [(String, [(String, SExpr)])]
cs ]
]
declareDatatype Solver
proc String
t [String]
ps [(String, [(String, SExpr)])]
cs =
Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> [SExpr] -> SExpr
fun String
"declare-datatype" ([SExpr] -> SExpr) -> [SExpr] -> SExpr
forall a b. (a -> b) -> a -> b
$
[ String -> SExpr
Atom String
t
, String -> [SExpr] -> SExpr
fun String
"par" ([SExpr] -> SExpr) -> [SExpr] -> SExpr
forall a b. (a -> b) -> a -> b
$
[ [SExpr] -> SExpr
List ((String -> SExpr) -> [String] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map String -> SExpr
Atom [String]
ps)
, [SExpr] -> SExpr
List [ [SExpr] -> SExpr
List (String -> SExpr
Atom String
c SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: [ [SExpr] -> SExpr
List [String -> SExpr
Atom String
s, SExpr
argTy] | (String
s, SExpr
argTy) <- [(String, SExpr)]
args]) | (String
c, [(String, SExpr)]
args) <- [(String, [(String, SExpr)])]
cs ]
]
]
define :: Solver ->
String ->
SExpr ->
SExpr ->
IO SExpr
define :: Solver -> String -> SExpr -> SExpr -> IO SExpr
define Solver
proc String
f SExpr
t SExpr
e = Solver -> String -> [(String, SExpr)] -> SExpr -> SExpr -> IO SExpr
defineFun Solver
proc String
f [] SExpr
t SExpr
e
defineFun :: Solver ->
String ->
[(String,SExpr)] ->
SExpr ->
SExpr ->
IO SExpr
defineFun :: Solver -> String -> [(String, SExpr)] -> SExpr -> SExpr -> IO SExpr
defineFun Solver
proc String
f [(String, SExpr)]
as SExpr
t SExpr
e =
do Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [SExpr] -> SExpr
fun String
"define-fun"
([SExpr] -> SExpr) -> [SExpr] -> SExpr
forall a b. (a -> b) -> a -> b
$ [ String -> SExpr
Atom String
f, [SExpr] -> SExpr
List [ [SExpr] -> SExpr
List [String -> SExpr
const String
x,SExpr
a] | (String
x,SExpr
a) <- [(String, SExpr)]
as ], SExpr
t, SExpr
e]
SExpr -> IO SExpr
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> SExpr
const String
f)
defineFunRec :: Solver ->
String ->
[(String,SExpr)] ->
SExpr ->
(SExpr -> SExpr) ->
IO SExpr
defineFunRec :: Solver
-> String
-> [(String, SExpr)]
-> SExpr
-> (SExpr -> SExpr)
-> IO SExpr
defineFunRec Solver
proc String
f [(String, SExpr)]
as SExpr
t SExpr -> SExpr
e =
do let fs :: SExpr
fs = String -> SExpr
const String
f
Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [SExpr] -> SExpr
fun String
"define-fun-rec"
([SExpr] -> SExpr) -> [SExpr] -> SExpr
forall a b. (a -> b) -> a -> b
$ [ String -> SExpr
Atom String
f, [SExpr] -> SExpr
List [ [SExpr] -> SExpr
List [String -> SExpr
const String
x,SExpr
a] | (String
x,SExpr
a) <- [(String, SExpr)]
as ], SExpr
t, SExpr -> SExpr
e SExpr
fs]
SExpr -> IO SExpr
forall (m :: * -> *) a. Monad m => a -> m a
return SExpr
fs
defineFunsRec :: Solver ->
[(String, [(String,SExpr)], SExpr, SExpr)] ->
IO ()
defineFunsRec :: Solver -> [(String, [(String, SExpr)], SExpr, SExpr)] -> IO ()
defineFunsRec Solver
proc [(String, [(String, SExpr)], SExpr, SExpr)]
ds = Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [SExpr] -> SExpr
fun String
"define-funs-rec" [ SExpr
decls, SExpr
bodies ]
where
oneArg :: (String, [(String, SExpr)], SExpr, d) -> SExpr
oneArg (String
f, [(String, SExpr)]
args, SExpr
t, d
_) = [SExpr] -> SExpr
List [ String -> SExpr
Atom String
f, [SExpr] -> SExpr
List [ [SExpr] -> SExpr
List [String -> SExpr
const String
x,SExpr
a] | (String
x,SExpr
a) <- [(String, SExpr)]
args ], SExpr
t]
decls :: SExpr
decls = [SExpr] -> SExpr
List (((String, [(String, SExpr)], SExpr, SExpr) -> SExpr)
-> [(String, [(String, SExpr)], SExpr, SExpr)] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map (String, [(String, SExpr)], SExpr, SExpr) -> SExpr
forall d. (String, [(String, SExpr)], SExpr, d) -> SExpr
oneArg [(String, [(String, SExpr)], SExpr, SExpr)]
ds)
bodies :: SExpr
bodies = [SExpr] -> SExpr
List (((String, [(String, SExpr)], SExpr, SExpr) -> SExpr)
-> [(String, [(String, SExpr)], SExpr, SExpr)] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map (\(String
_, [(String, SExpr)]
_, SExpr
_, SExpr
body) -> SExpr
body) [(String, [(String, SExpr)], SExpr, SExpr)]
ds)
assert :: Solver -> SExpr -> IO ()
assert :: Solver -> SExpr -> IO ()
assert Solver
proc SExpr
e = Solver -> SExpr -> IO ()
ackCommand Solver
proc (SExpr -> IO ()) -> SExpr -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [SExpr] -> SExpr
fun String
"assert" [SExpr
e]
check :: Solver -> IO Result
check :: Solver -> IO Result
check Solver
proc =
do SExpr
res <- Solver -> SExpr -> IO SExpr
command Solver
proc ([SExpr] -> SExpr
List [ String -> SExpr
Atom String
"check-sat" ])
case SExpr
res of
Atom String
"unsat" -> Result -> IO Result
forall (m :: * -> *) a. Monad m => a -> m a
return Result
Unsat
Atom String
"unknown" -> Result -> IO Result
forall (m :: * -> *) a. Monad m => a -> m a
return Result
Unknown
Atom String
"sat" -> Result -> IO Result
forall (m :: * -> *) a. Monad m => a -> m a
return Result
Sat
SExpr
_ -> String -> IO Result
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO Result) -> String -> IO Result
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Unexpected result from the SMT solver:"
, String
" Expected: unsat, unknown, or sat"
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
res String
""
]
sexprToVal :: SExpr -> Value
sexprToVal :: SExpr -> Value
sexprToVal SExpr
expr =
case SExpr
expr of
Atom String
"true" -> Bool -> Value
Bool Bool
True
Atom String
"false" -> Bool -> Value
Bool Bool
False
Atom (Char
'#' : Char
'b' : String
ds)
| Just Integer
n <- String -> Maybe Integer
binLit String
ds -> Int -> Integer -> Value
Bits (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ds) Integer
n
Atom (Char
'#' : Char
'x' : String
ds)
| [(Integer
n,[])] <- ReadS Integer
forall a. (Eq a, Num a) => ReadS a
readHex String
ds -> Int -> Integer -> Value
Bits (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ds) Integer
n
Atom String
txt
| Just Integer
n <- String -> Maybe Integer
forall a. Read a => String -> Maybe a
readMaybe String
txt -> Integer -> Value
Int Integer
n
List [ Atom String
"-", SExpr
x ]
| Int Integer
a <- SExpr -> Value
sexprToVal SExpr
x -> Integer -> Value
Int (Integer -> Integer
forall a. Num a => a -> a
negate Integer
a)
List [ Atom String
"/", SExpr
x, SExpr
y ]
| Int Integer
a <- SExpr -> Value
sexprToVal SExpr
x
, Int Integer
b <- SExpr -> Value
sexprToVal SExpr
y -> Rational -> Value
Real (Integer
a Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
b)
SExpr
_ -> SExpr -> Value
Other SExpr
expr
where
binLit :: String -> Maybe Integer
binLit String
cs = do [Integer]
ds <- (Char -> Maybe Integer) -> String -> Maybe [Integer]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Char -> Maybe Integer
forall a. Num a => Char -> Maybe a
binDigit String
cs
Integer -> Maybe Integer
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer -> Maybe Integer) -> Integer -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ [Integer] -> Integer
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Integer] -> Integer) -> [Integer] -> Integer
forall a b. (a -> b) -> a -> b
$ (Integer -> Integer -> Integer)
-> [Integer] -> [Integer] -> [Integer]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(*) ([Integer] -> [Integer]
forall a. [a] -> [a]
reverse [Integer]
ds) [Integer]
powers2
powers2 :: [Integer]
powers2 = Integer
1 Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: (Integer -> Integer) -> [Integer] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*) [Integer]
powers2
binDigit :: Char -> Maybe a
binDigit Char
'0' = a -> Maybe a
forall a. a -> Maybe a
Just a
0
binDigit Char
'1' = a -> Maybe a
forall a. a -> Maybe a
Just a
1
binDigit Char
_ = Maybe a
forall a. Maybe a
Nothing
getExprs :: Solver -> [SExpr] -> IO [(SExpr, Value)]
getExprs :: Solver -> [SExpr] -> IO [(SExpr, Value)]
getExprs Solver
proc [SExpr]
vals =
do SExpr
res <- Solver -> SExpr -> IO SExpr
command Solver
proc (SExpr -> IO SExpr) -> SExpr -> IO SExpr
forall a b. (a -> b) -> a -> b
$ [SExpr] -> SExpr
List [ String -> SExpr
Atom String
"get-value", [SExpr] -> SExpr
List [SExpr]
vals ]
case SExpr
res of
List [SExpr]
xs -> (SExpr -> IO (SExpr, Value)) -> [SExpr] -> IO [(SExpr, Value)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM SExpr -> IO (SExpr, Value)
forall (m :: * -> *). MonadFail m => SExpr -> m (SExpr, Value)
getAns [SExpr]
xs
SExpr
_ -> String -> IO [(SExpr, Value)]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO [(SExpr, Value)]) -> String -> IO [(SExpr, Value)]
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Unexpected response from the SMT solver:"
, String
" Exptected: a list"
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
res String
""
]
where
getAns :: SExpr -> m (SExpr, Value)
getAns SExpr
expr =
case SExpr
expr of
List [ SExpr
e, SExpr
v ] -> (SExpr, Value) -> m (SExpr, Value)
forall (m :: * -> *) a. Monad m => a -> m a
return (SExpr
e, SExpr -> Value
sexprToVal SExpr
v)
SExpr
_ -> String -> m (SExpr, Value)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m (SExpr, Value)) -> String -> m (SExpr, Value)
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Unexpected response from the SMT solver:"
, String
" Expected: (expr val)"
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
expr String
""
]
getConsts :: Solver -> [String] -> IO [(String, Value)]
getConsts :: Solver -> [String] -> IO [(String, Value)]
getConsts Solver
proc [String]
xs =
do [(SExpr, Value)]
ans <- Solver -> [SExpr] -> IO [(SExpr, Value)]
getExprs Solver
proc ((String -> SExpr) -> [String] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map String -> SExpr
Atom [String]
xs)
[(String, Value)] -> IO [(String, Value)]
forall (m :: * -> *) a. Monad m => a -> m a
return [ (String
x,Value
e) | (Atom String
x, Value
e) <- [(SExpr, Value)]
ans ]
getExpr :: Solver -> SExpr -> IO Value
getExpr :: Solver -> SExpr -> IO Value
getExpr Solver
proc SExpr
x =
do [ (SExpr
_,Value
v) ] <- Solver -> [SExpr] -> IO [(SExpr, Value)]
getExprs Solver
proc [SExpr
x]
Value -> IO Value
forall (m :: * -> *) a. Monad m => a -> m a
return Value
v
getConst :: Solver -> String -> IO Value
getConst :: Solver -> String -> IO Value
getConst Solver
proc String
x = Solver -> SExpr -> IO Value
getExpr Solver
proc (String -> SExpr
Atom String
x)
getUnsatCore :: Solver -> IO [String]
getUnsatCore :: Solver -> IO [String]
getUnsatCore Solver
s =
do SExpr
res <- Solver -> SExpr -> IO SExpr
command Solver
s (SExpr -> IO SExpr) -> SExpr -> IO SExpr
forall a b. (a -> b) -> a -> b
$ [SExpr] -> SExpr
List [ String -> SExpr
Atom String
"get-unsat-core" ]
case SExpr
res of
List [SExpr]
xs -> (SExpr -> IO String) -> [SExpr] -> IO [String]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM SExpr -> IO String
forall (m :: * -> *). MonadFail m => SExpr -> m String
fromAtom [SExpr]
xs
SExpr
_ -> String -> SExpr -> IO [String]
forall (m :: * -> *) a. MonadFail m => String -> SExpr -> m a
unexpected String
"a list of atoms" SExpr
res
where
fromAtom :: SExpr -> m String
fromAtom SExpr
x =
case SExpr
x of
Atom String
a -> String -> m String
forall (m :: * -> *) a. Monad m => a -> m a
return String
a
SExpr
_ -> String -> SExpr -> m String
forall (m :: * -> *) a. MonadFail m => String -> SExpr -> m a
unexpected String
"an atom" SExpr
x
unexpected :: String -> SExpr -> m a
unexpected String
x SExpr
e =
String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ String
"Unexpected response from the SMT Solver:"
, String
" Expected: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x
, String
" Result: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ SExpr -> ShowS
showsSExpr SExpr
e String
""
]
fam :: String -> [Integer] -> SExpr
fam :: String -> [Integer] -> SExpr
fam String
f [Integer]
is = [SExpr] -> SExpr
List (String -> SExpr
Atom String
"_" SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: String -> SExpr
Atom String
f SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: (Integer -> SExpr) -> [Integer] -> [SExpr]
forall a b. (a -> b) -> [a] -> [b]
map (String -> SExpr
Atom (String -> SExpr) -> (Integer -> String) -> Integer -> SExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> String
forall a. Show a => a -> String
show) [Integer]
is)
fun :: String -> [SExpr] -> SExpr
fun :: String -> [SExpr] -> SExpr
fun String
f [] = String -> SExpr
Atom String
f
fun String
f [SExpr]
as = [SExpr] -> SExpr
List (String -> SExpr
Atom String
f SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: [SExpr]
as)
const :: String -> SExpr
const :: String -> SExpr
const String
f = String -> [SExpr] -> SExpr
fun String
f []
app :: SExpr -> [SExpr] -> SExpr
app :: SExpr -> [SExpr] -> SExpr
app SExpr
f [SExpr]
xs = [SExpr] -> SExpr
List (SExpr
f SExpr -> [SExpr] -> [SExpr]
forall a. a -> [a] -> [a]
: [SExpr]
xs)
allowedSimpleChar :: Char -> Bool
allowedSimpleChar :: Char -> Bool
allowedSimpleChar Char
c =
Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ([Char
'a' .. Char
'z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'A' .. Char
'Z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"~!@$%^&*_-+=<>.?/")
isSimpleSymbol :: String -> Bool
isSimpleSymbol :: String -> Bool
isSimpleSymbol s :: String
s@(Char
c : String
_) = Bool -> Bool
P.not (Char -> Bool
isDigit Char
c) Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
allowedSimpleChar String
s
isSimpleSymbol String
_ = Bool
False
quoteSymbol :: String -> String
quoteSymbol :: ShowS
quoteSymbol String
s
| String -> Bool
isSimpleSymbol String
s = String
s
| Bool
otherwise = Char
'|' Char -> ShowS
forall a. a -> [a] -> [a]
: String
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"|"
symbol :: String -> SExpr
symbol :: String -> SExpr
symbol = String -> SExpr
Atom (String -> SExpr) -> ShowS -> String -> SExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
quoteSymbol
keyword :: String -> SExpr
keyword :: String -> SExpr
keyword String
s = String -> SExpr
Atom (Char
':' Char -> ShowS
forall a. a -> [a] -> [a]
: String
s)
as :: SExpr -> SExpr -> SExpr
as :: SExpr -> SExpr -> SExpr
as SExpr
s SExpr
t = String -> [SExpr] -> SExpr
fun String
"as" [SExpr
s, SExpr
t]
tInt :: SExpr
tInt :: SExpr
tInt = String -> SExpr
const String
"Int"
tBool :: SExpr
tBool :: SExpr
tBool = String -> SExpr
const String
"Bool"
tReal :: SExpr
tReal :: SExpr
tReal = String -> SExpr
const String
"Real"
tArray :: SExpr ->
SExpr ->
SExpr
tArray :: SExpr -> SExpr -> SExpr
tArray SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"Array" [SExpr
x,SExpr
y]
tBits :: Integer ->
SExpr
tBits :: Integer -> SExpr
tBits Integer
w = String -> [Integer] -> SExpr
fam String
"BitVec" [Integer
w]
bool :: Bool -> SExpr
bool :: Bool -> SExpr
bool Bool
b = String -> SExpr
const (if Bool
b then String
"true" else String
"false")
int :: Integer -> SExpr
int :: Integer -> SExpr
int Integer
x | Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = SExpr -> SExpr
neg (Integer -> SExpr
int (Integer -> Integer
forall a. Num a => a -> a
negate Integer
x))
| Bool
otherwise = String -> SExpr
Atom (Integer -> String
forall a. Show a => a -> String
show Integer
x)
real :: Rational -> SExpr
real :: Rational -> SExpr
real Rational
x
| Double -> Rational
forall a. Real a => a -> Rational
toRational Double
y Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== Rational
x = String -> SExpr
Atom (Maybe Int -> Double -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat Maybe Int
forall a. Maybe a
Nothing Double
y String
"")
| Bool
otherwise = SExpr -> SExpr -> SExpr
realDiv (Integer -> SExpr
int (Rational -> Integer
forall a. Ratio a -> a
numerator Rational
x)) (Integer -> SExpr
int (Rational -> Integer
forall a. Ratio a -> a
denominator Rational
x))
where y :: Double
y = Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
x :: Double
bvBin :: Int -> Integer -> SExpr
bvBin :: Int -> Integer -> SExpr
bvBin Int
w Integer
v = String -> SExpr
const (String
"#b" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
bits)
where
bits :: String
bits = ShowS
forall a. [a] -> [a]
reverse [ if Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Integer
v Int
n then Char
'1' else Char
'0' | Int
n <- [ Int
0 .. Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 ] ]
bvHex :: Int -> Integer -> SExpr
bvHex :: Int -> Integer -> SExpr
bvHex Int
w Integer
v
| Integer
v Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
0 = String -> SExpr
const (String
"#x" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
padding String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
hex)
| Bool
otherwise = Int -> Integer -> SExpr
bvHex Int
w (Integer
2Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^Int
w Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
v)
where
hex :: String
hex = Integer -> ShowS
forall a. (Integral a, Show a) => a -> ShowS
showHex Integer
v String
""
padding :: String
padding = Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int -> Int -> Int
forall a. Integral a => a -> a -> a
P.div (Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3) Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
hex) Char
'0'
value :: Value -> SExpr
value :: Value -> SExpr
value Value
val =
case Value
val of
Bool Bool
b -> Bool -> SExpr
bool Bool
b
Int Integer
n -> Integer -> SExpr
int Integer
n
Real Rational
r -> Rational -> SExpr
real Rational
r
Bits Int
w Integer
v | Int -> Int -> Int
forall a. Integral a => a -> a -> a
P.mod Int
w Int
4 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 -> Int -> Integer -> SExpr
bvHex Int
w Integer
v
| Bool
otherwise -> Int -> Integer -> SExpr
bvBin Int
w Integer
v
Other SExpr
o -> SExpr
o
not :: SExpr -> SExpr
not :: SExpr -> SExpr
not SExpr
p = String -> [SExpr] -> SExpr
fun String
"not" [SExpr
p]
and :: SExpr -> SExpr -> SExpr
and :: SExpr -> SExpr -> SExpr
and SExpr
p SExpr
q = String -> [SExpr] -> SExpr
fun String
"and" [SExpr
p,SExpr
q]
andMany :: [SExpr] -> SExpr
andMany :: [SExpr] -> SExpr
andMany [SExpr]
xs = if [SExpr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SExpr]
xs then Bool -> SExpr
bool Bool
True else String -> [SExpr] -> SExpr
fun String
"and" [SExpr]
xs
or :: SExpr -> SExpr -> SExpr
or :: SExpr -> SExpr -> SExpr
or SExpr
p SExpr
q = String -> [SExpr] -> SExpr
fun String
"or" [SExpr
p,SExpr
q]
orMany :: [SExpr] -> SExpr
orMany :: [SExpr] -> SExpr
orMany [SExpr]
xs = if [SExpr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SExpr]
xs then Bool -> SExpr
bool Bool
False else String -> [SExpr] -> SExpr
fun String
"or" [SExpr]
xs
xor :: SExpr -> SExpr -> SExpr
xor :: SExpr -> SExpr -> SExpr
xor SExpr
p SExpr
q = String -> [SExpr] -> SExpr
fun String
"xor" [SExpr
p,SExpr
q]
implies :: SExpr -> SExpr -> SExpr
implies :: SExpr -> SExpr -> SExpr
implies SExpr
p SExpr
q = String -> [SExpr] -> SExpr
fun String
"=>" [SExpr
p,SExpr
q]
ite :: SExpr -> SExpr -> SExpr -> SExpr
ite :: SExpr -> SExpr -> SExpr -> SExpr
ite SExpr
x SExpr
y SExpr
z = String -> [SExpr] -> SExpr
fun String
"ite" [SExpr
x,SExpr
y,SExpr
z]
eq :: SExpr -> SExpr -> SExpr
eq :: SExpr -> SExpr -> SExpr
eq SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"=" [SExpr
x,SExpr
y]
distinct :: [SExpr] -> SExpr
distinct :: [SExpr] -> SExpr
distinct [SExpr]
xs = if [SExpr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SExpr]
xs then Bool -> SExpr
bool Bool
True else String -> [SExpr] -> SExpr
fun String
"distinct" [SExpr]
xs
gt :: SExpr -> SExpr -> SExpr
gt :: SExpr -> SExpr -> SExpr
gt SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
">" [SExpr
x,SExpr
y]
lt :: SExpr -> SExpr -> SExpr
lt :: SExpr -> SExpr -> SExpr
lt SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"<" [SExpr
x,SExpr
y]
geq :: SExpr -> SExpr -> SExpr
geq :: SExpr -> SExpr -> SExpr
geq SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
">=" [SExpr
x,SExpr
y]
leq :: SExpr -> SExpr -> SExpr
leq :: SExpr -> SExpr -> SExpr
leq SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"<=" [SExpr
x,SExpr
y]
bvULt :: SExpr -> SExpr -> SExpr
bvULt :: SExpr -> SExpr -> SExpr
bvULt SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvult" [SExpr
x,SExpr
y]
bvULeq :: SExpr -> SExpr -> SExpr
bvULeq :: SExpr -> SExpr -> SExpr
bvULeq SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvule" [SExpr
x,SExpr
y]
bvSLt :: SExpr -> SExpr -> SExpr
bvSLt :: SExpr -> SExpr -> SExpr
bvSLt SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvslt" [SExpr
x,SExpr
y]
bvSLeq :: SExpr -> SExpr -> SExpr
bvSLeq :: SExpr -> SExpr -> SExpr
bvSLeq SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvsle" [SExpr
x,SExpr
y]
add :: SExpr -> SExpr -> SExpr
add :: SExpr -> SExpr -> SExpr
add SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"+" [SExpr
x,SExpr
y]
addMany :: [SExpr] -> SExpr
addMany :: [SExpr] -> SExpr
addMany [SExpr]
xs = if [SExpr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SExpr]
xs then Integer -> SExpr
int Integer
0 else String -> [SExpr] -> SExpr
fun String
"+" [SExpr]
xs
sub :: SExpr -> SExpr -> SExpr
sub :: SExpr -> SExpr -> SExpr
sub SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"-" [SExpr
x,SExpr
y]
neg :: SExpr -> SExpr
neg :: SExpr -> SExpr
neg SExpr
x = String -> [SExpr] -> SExpr
fun String
"-" [SExpr
x]
mul :: SExpr -> SExpr -> SExpr
mul :: SExpr -> SExpr -> SExpr
mul SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"*" [SExpr
x,SExpr
y]
abs :: SExpr -> SExpr
abs :: SExpr -> SExpr
abs SExpr
x = String -> [SExpr] -> SExpr
fun String
"abs" [SExpr
x]
div :: SExpr -> SExpr -> SExpr
div :: SExpr -> SExpr -> SExpr
div SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"div" [SExpr
x,SExpr
y]
mod :: SExpr -> SExpr -> SExpr
mod :: SExpr -> SExpr -> SExpr
mod SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"mod" [SExpr
x,SExpr
y]
divisible :: SExpr -> Integer -> SExpr
divisible :: SExpr -> Integer -> SExpr
divisible SExpr
x Integer
n = [SExpr] -> SExpr
List [ String -> [Integer] -> SExpr
fam String
"divisible" [Integer
n], SExpr
x ]
realDiv :: SExpr -> SExpr -> SExpr
realDiv :: SExpr -> SExpr -> SExpr
realDiv SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"/" [SExpr
x,SExpr
y]
concat :: SExpr -> SExpr -> SExpr
concat :: SExpr -> SExpr -> SExpr
concat SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"concat" [SExpr
x,SExpr
y]
signExtend :: Integer -> SExpr -> SExpr
signExtend :: Integer -> SExpr -> SExpr
signExtend Integer
i SExpr
x = [SExpr] -> SExpr
List [ String -> [Integer] -> SExpr
fam String
"sign_extend" [Integer
i], SExpr
x ]
zeroExtend :: Integer -> SExpr -> SExpr
zeroExtend :: Integer -> SExpr -> SExpr
zeroExtend Integer
i SExpr
x = [SExpr] -> SExpr
List [ String -> [Integer] -> SExpr
fam String
"zero_extend" [Integer
i], SExpr
x ]
toInt :: SExpr -> SExpr
toInt :: SExpr -> SExpr
toInt SExpr
e = String -> [SExpr] -> SExpr
fun String
"to_int" [SExpr
e]
toReal :: SExpr -> SExpr
toReal :: SExpr -> SExpr
toReal SExpr
e = String -> [SExpr] -> SExpr
fun String
"to_real" [SExpr
e]
extract :: SExpr -> Integer -> Integer -> SExpr
SExpr
x Integer
y Integer
z = [SExpr] -> SExpr
List [ String -> [Integer] -> SExpr
fam String
"extract" [Integer
y,Integer
z], SExpr
x ]
bvNot :: SExpr -> SExpr
bvNot :: SExpr -> SExpr
bvNot SExpr
x = String -> [SExpr] -> SExpr
fun String
"bvnot" [SExpr
x]
bvAnd :: SExpr -> SExpr -> SExpr
bvAnd :: SExpr -> SExpr -> SExpr
bvAnd SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvand" [SExpr
x,SExpr
y]
bvOr :: SExpr -> SExpr -> SExpr
bvOr :: SExpr -> SExpr -> SExpr
bvOr SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvor" [SExpr
x,SExpr
y]
bvXOr :: SExpr -> SExpr -> SExpr
bvXOr :: SExpr -> SExpr -> SExpr
bvXOr SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvxor" [SExpr
x,SExpr
y]
bvNeg :: SExpr -> SExpr
bvNeg :: SExpr -> SExpr
bvNeg SExpr
x = String -> [SExpr] -> SExpr
fun String
"bvneg" [SExpr
x]
bvAdd :: SExpr -> SExpr -> SExpr
bvAdd :: SExpr -> SExpr -> SExpr
bvAdd SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvadd" [SExpr
x,SExpr
y]
bvSub :: SExpr -> SExpr -> SExpr
bvSub :: SExpr -> SExpr -> SExpr
bvSub SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvsub" [SExpr
x,SExpr
y]
bvMul :: SExpr -> SExpr -> SExpr
bvMul :: SExpr -> SExpr -> SExpr
bvMul SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvmul" [SExpr
x,SExpr
y]
bvUDiv :: SExpr -> SExpr -> SExpr
bvUDiv :: SExpr -> SExpr -> SExpr
bvUDiv SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvudiv" [SExpr
x,SExpr
y]
bvURem :: SExpr -> SExpr -> SExpr
bvURem :: SExpr -> SExpr -> SExpr
bvURem SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvurem" [SExpr
x,SExpr
y]
bvSDiv :: SExpr -> SExpr -> SExpr
bvSDiv :: SExpr -> SExpr -> SExpr
bvSDiv SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvsdiv" [SExpr
x,SExpr
y]
bvSRem :: SExpr -> SExpr -> SExpr
bvSRem :: SExpr -> SExpr -> SExpr
bvSRem SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvsrem" [SExpr
x,SExpr
y]
bvShl :: SExpr -> SExpr -> SExpr
bvShl :: SExpr -> SExpr -> SExpr
bvShl SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvshl" [SExpr
x,SExpr
y]
bvLShr :: SExpr -> SExpr -> SExpr
bvLShr :: SExpr -> SExpr -> SExpr
bvLShr SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvlshr" [SExpr
x,SExpr
y]
bvAShr :: SExpr -> SExpr -> SExpr
bvAShr :: SExpr -> SExpr -> SExpr
bvAShr SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"bvashr" [SExpr
x,SExpr
y]
select :: SExpr -> SExpr -> SExpr
select :: SExpr -> SExpr -> SExpr
select SExpr
x SExpr
y = String -> [SExpr] -> SExpr
fun String
"select" [SExpr
x,SExpr
y]
store :: SExpr ->
SExpr ->
SExpr ->
SExpr
store :: SExpr -> SExpr -> SExpr -> SExpr
store SExpr
x SExpr
y SExpr
z = String -> [SExpr] -> SExpr
fun String
"store" [SExpr
x,SExpr
y,SExpr
z]
named :: String -> SExpr -> SExpr
named :: String -> SExpr -> SExpr
named String
x SExpr
e = String -> [SExpr] -> SExpr
fun String
"!" [SExpr
e, String -> SExpr
Atom String
":named", String -> SExpr
Atom String
x ]
data Logger = Logger
{ Logger -> String -> IO ()
logMessage :: String -> IO ()
, Logger -> IO Int
logLevel :: IO Int
, Logger -> Int -> IO ()
logSetLevel:: Int -> IO ()
, Logger -> IO ()
logTab :: IO ()
, Logger -> IO ()
logUntab :: IO ()
}
withLogLevel :: Logger -> Int -> IO a -> IO a
withLogLevel :: Logger -> Int -> IO a -> IO a
withLogLevel Logger { IO Int
IO ()
Int -> IO ()
String -> IO ()
logUntab :: IO ()
logTab :: IO ()
logSetLevel :: Int -> IO ()
logLevel :: IO Int
logMessage :: String -> IO ()
logUntab :: Logger -> IO ()
logTab :: Logger -> IO ()
logSetLevel :: Logger -> Int -> IO ()
logLevel :: Logger -> IO Int
logMessage :: Logger -> String -> IO ()
.. } Int
l IO a
m =
do Int
l0 <- IO Int
logLevel
IO () -> IO () -> IO a -> IO a
forall a b c. IO a -> IO b -> IO c -> IO c
X.bracket_ (Int -> IO ()
logSetLevel Int
l) (Int -> IO ()
logSetLevel Int
l0) IO a
m
logIndented :: Logger -> IO a -> IO a
logIndented :: Logger -> IO a -> IO a
logIndented Logger { IO Int
IO ()
Int -> IO ()
String -> IO ()
logUntab :: IO ()
logTab :: IO ()
logSetLevel :: Int -> IO ()
logLevel :: IO Int
logMessage :: String -> IO ()
logUntab :: Logger -> IO ()
logTab :: Logger -> IO ()
logSetLevel :: Logger -> Int -> IO ()
logLevel :: Logger -> IO Int
logMessage :: Logger -> String -> IO ()
.. } = IO () -> IO () -> IO a -> IO a
forall a b c. IO a -> IO b -> IO c -> IO c
X.bracket_ IO ()
logTab IO ()
logUntab
logMessageAt :: Logger -> Int -> String -> IO ()
logMessageAt :: Logger -> Int -> String -> IO ()
logMessageAt Logger
logger Int
l String
msg = Logger -> Int -> IO () -> IO ()
forall a. Logger -> Int -> IO a -> IO a
withLogLevel Logger
logger Int
l (Logger -> String -> IO ()
logMessage Logger
logger String
msg)
newLogger :: Int -> IO Logger
newLogger :: Int -> IO Logger
newLogger Int
l =
do IORef Int
tab <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
IORef Int
lev <- Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0
let logLevel :: IO Int
logLevel = IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
lev
logSetLevel :: Int -> IO ()
logSetLevel = IORef Int -> Int -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Int
lev
shouldLog :: IO () -> IO ()
shouldLog IO ()
m =
do Int
cl <- IO Int
logLevel
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
cl Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l) IO ()
m
logMessage :: String -> IO ()
logMessage String
x = IO () -> IO ()
shouldLog (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
do let ls :: [String]
ls = String -> [String]
lines String
x
Int
t <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
tab
String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
t Char
' ' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
l | String
l <- [String]
ls ]
Handle -> IO ()
hFlush Handle
stdout
logTab :: IO ()
logTab = IO () -> IO ()
shouldLog (IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Int
tab (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2))
logUntab :: IO ()
logUntab = IO () -> IO ()
shouldLog (IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Int
tab (Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
2))
Logger -> IO Logger
forall (m :: * -> *) a. Monad m => a -> m a
return Logger :: (String -> IO ())
-> IO Int -> (Int -> IO ()) -> IO () -> IO () -> Logger
Logger { IO Int
IO ()
Int -> IO ()
String -> IO ()
logUntab :: IO ()
logTab :: IO ()
logMessage :: String -> IO ()
logSetLevel :: Int -> IO ()
logLevel :: IO Int
logUntab :: IO ()
logTab :: IO ()
logSetLevel :: Int -> IO ()
logLevel :: IO Int
logMessage :: String -> IO ()
.. }