{-# LANGUAGE NamedFieldPuns #-}
module Data.SBV.SMT.Utils (
SMTLibConverter
, SMTLibIncConverter
, addAnnotations
, showTimeoutValue
, alignDiagnostic
, alignPlain
, debug
, mergeSExpr
, SBVException(..)
)
where
import qualified Control.Exception as C
import Data.SBV.Core.Data
import Data.SBV.Utils.Lib (joinArgs)
import Data.List (intercalate)
import qualified Data.Set as Set (Set)
import System.Exit (ExitCode(..))
type SMTLibConverter a = Set.Set Kind
-> Bool
-> [String]
-> ([(Quantifier, NamedSymVar)], [NamedSymVar])
-> [Either SW (SW, [SW])]
-> [(SW, CW)]
-> [((Int, Kind, Kind), [SW])]
-> [(Int, ArrayInfo)]
-> [(String, SBVType)]
-> [(String, [String])]
-> SBVPgm
-> [(Bool, [(String, String)], SW)]
-> SW
-> SMTConfig
-> a
type SMTLibIncConverter a = [NamedSymVar]
-> Set.Set Kind
-> [(SW, CW)]
-> [(Int, ArrayInfo)]
-> [((Int, Kind, Kind), [SW])]
-> [(String, SBVType)]
-> SBVPgm
-> SMTConfig
-> a
addAnnotations :: [(String, String)] -> String -> String
addAnnotations [] x = x
addAnnotations atts x = "(! " ++ x ++ " " ++ unwords (map mkAttr atts) ++ ")"
where mkAttr (a, v) = a ++ " |" ++ concatMap sanitize v ++ "|"
sanitize '|' = "_bar_"
sanitize '\\' = "_backslash_"
sanitize c = [c]
showTimeoutValue :: Int -> String
showTimeoutValue i = case (i `quotRem` 1000000, i `quotRem` 500000) of
((s, 0), _) -> shows s "s"
(_, (hs, 0)) -> shows (fromIntegral hs / (2::Float)) "s"
_ -> shows i "ms"
alignDiagnostic :: String -> String -> String
alignDiagnostic = alignWithPrefix "*** "
alignPlain :: String -> String -> String
alignPlain = alignWithPrefix ""
alignWithPrefix :: String -> String -> String -> String
alignWithPrefix pre tag multi = intercalate "\n" $ zipWith (++) (tag : repeat (pre ++ replicate (length tag - length pre) ' ')) (filter (not . null) (lines multi))
debug :: SMTConfig -> [String] -> IO ()
debug cfg
| not (verbose cfg) = const (return ())
| Just f <- redirectVerbose cfg = mapM_ (appendFile f . (++ "\n"))
| True = mapM_ putStrLn
mergeSExpr :: [String] -> [String]
mergeSExpr [] = []
mergeSExpr (x:xs)
| d == 0 = x : mergeSExpr xs
| True = let (f, r) = grab d xs in unlines (x:f) : mergeSExpr r
where d = parenDiff x
parenDiff :: String -> Int
parenDiff = go 0
where go i "" = i
go i ('(':cs) = let i'= i+1 in i' `seq` go i' cs
go i (')':cs) = let i'= i-1 in i' `seq` go i' cs
go i ('"':cs) = go i (skipString cs)
go i ('|':cs) = go i (skipBar cs)
go i (_ :cs) = go i cs
grab i ls
| i <= 0 = ([], ls)
grab _ [] = ([], [])
grab i (l:ls) = let (a, b) = grab (i+parenDiff l) ls in (l:a, b)
skipString ('"':'"':cs) = skipString cs
skipString ('"':cs) = cs
skipString (_:cs) = skipString cs
skipString [] = []
skipBar ('|':cs) = cs
skipBar (_:cs) = skipBar cs
skipBar [] = []
data SBVException = SBVException {
sbvExceptionDescription :: String
, sbvExceptionSent :: Maybe String
, sbvExceptionExpected :: Maybe String
, sbvExceptionReceived :: Maybe String
, sbvExceptionStdOut :: Maybe String
, sbvExceptionStdErr :: Maybe String
, sbvExceptionExitCode :: Maybe ExitCode
, sbvExceptionConfig :: SMTConfig
, sbvExceptionReason :: Maybe [String]
, sbvExceptionHint :: Maybe [String]
}
instance C.Exception SBVException
instance Show SBVException where
show SBVException { sbvExceptionDescription
, sbvExceptionSent
, sbvExceptionExpected
, sbvExceptionReceived
, sbvExceptionStdOut
, sbvExceptionStdErr
, sbvExceptionExitCode
, sbvExceptionConfig
, sbvExceptionReason
, sbvExceptionHint
}
= let grp1 = [ ""
, "*** Data.SBV: " ++ sbvExceptionDescription ++ ":"
]
grp2 = ["*** Sent : " `alignDiagnostic` snt | Just snt <- [sbvExceptionSent], not $ null snt ]
++ ["*** Expected : " `alignDiagnostic` excp | Just excp <- [sbvExceptionExpected], not $ null excp]
++ ["*** Received : " `alignDiagnostic` rcvd | Just rcvd <- [sbvExceptionReceived], not $ null rcvd]
grp3 = ["*** Stdout : " `alignDiagnostic` out | Just out <- [sbvExceptionStdOut], not $ null out ]
++ ["*** Stderr : " `alignDiagnostic` err | Just err <- [sbvExceptionStdErr], not $ null err ]
++ ["*** Exit code : " `alignDiagnostic` show ec | Just ec <- [sbvExceptionExitCode] ]
++ ["*** Executable: " `alignDiagnostic` executable (solver sbvExceptionConfig) ]
++ ["*** Options : " `alignDiagnostic` joinArgs (options (solver sbvExceptionConfig) sbvExceptionConfig) ]
grp4 = ["*** Reason : " `alignDiagnostic` unlines rsn | Just rsn <- [sbvExceptionReason]]
++ ["*** Hint : " `alignDiagnostic` unlines hnt | Just hnt <- [sbvExceptionHint ]]
join [] = []
join [x] = x
join (g:gs) = case join gs of
[] -> g
rest -> g ++ ["***"] ++ rest
in unlines $ join [grp1, grp2, grp3, grp4]