@@ -26,6 +26,7 @@ module SMT.SimpleSMT
2626 , simpleCommand
2727 , simpleCommandMaybe
2828 , loadFile
29+ , SolverException (.. )
2930
3031 -- ** S-Expressions
3132 , SExpr (.. )
@@ -151,12 +152,14 @@ module SMT.SimpleSMT
151152 , existsQ
152153 ) where
153154
154- import Prelude hiding
155+ import Prelude.Kore hiding
155156 ( abs
156157 , and
158+ , assert
157159 , concat
158160 , const
159161 , div
162+ , extract
160163 , mod
161164 , not
162165 , or
@@ -166,8 +169,13 @@ import qualified Colog
166169import Control.Concurrent
167170 ( forkIO
168171 )
172+ import Control.Exception
173+ ( AsyncException
174+ , SomeException (.. )
175+ )
169176import qualified Control.Exception as X
170177import qualified Control.Monad as Monad
178+ import qualified Control.Monad.Catch as Exception
171179import Data.Bits
172180 ( testBit
173181 )
@@ -176,6 +184,9 @@ import Data.Ratio
176184 , numerator
177185 , (%)
178186 )
187+ import Data.String
188+ ( fromString
189+ )
179190import Data.Text
180191 ( Text
181192 )
@@ -193,7 +204,7 @@ import Numeric
193204 )
194205import qualified Prelude
195206import System.Exit
196- ( ExitCode
207+ ( ExitCode ( .. )
197208 )
198209import System.IO
199210 ( Handle
@@ -203,6 +214,7 @@ import System.IO
203214 )
204215import System.Process
205216 ( ProcessHandle
217+ , getProcessExitCode
206218 , runInteractiveProcess
207219 , waitForProcess
208220 )
@@ -219,6 +231,7 @@ import Kore.Log.DebugSolver
219231 , logDebugSolverSendWith
220232 )
221233import qualified Log
234+ import qualified Pretty
222235import SMT.AST
223236
224237-- ---------------------------------------------------------------------
@@ -266,6 +279,37 @@ data SolverHandle = SolverHandle
266279 , hProc :: ! ProcessHandle
267280 }
268281
282+ data SolverException =
283+ SolverException
284+ { exitCode :: ! (Maybe ExitCode )
285+ , someException :: ! Exception. SomeException
286+ }
287+ deriving (Show , Typeable )
288+
289+ instance Exception. Exception SolverException where
290+ displayException SolverException { exitCode, someException } =
291+ (show . Pretty. vsep . catMaybes)
292+ [ Just " Error while communicating with the solver:"
293+ , Just $ Pretty. indent 4 $ prettyException someException
294+ , (Pretty. <+>) " Solver exit code:" . prettyExitCode <$> exitCode
295+ ]
296+ where
297+ prettyException =
298+ Pretty. vsep . map fromString . lines . Exception. displayException
299+ prettyExitCode ExitSuccess = " 0"
300+ prettyExitCode (ExitFailure code) = Pretty. pretty code
301+
302+ throwSolverException :: ProcessHandle -> SomeException -> IO a
303+ throwSolverException solverHandle someException
304+ | Just _ <- Exception. fromException someException :: Maybe AsyncException =
305+ Exception. throwM someException
306+ | otherwise = do
307+ exitCode <- getProcessExitCode solverHandle
308+ Exception. throwM SolverException { exitCode, someException }
309+
310+ trySolver :: ProcessHandle -> IO a -> IO a
311+ trySolver hProc = Exception. handle (throwSolverException hProc)
312+
269313-- | Start a new solver process.
270314newSolver
271315 :: FilePath -- ^ Executable
@@ -307,18 +351,20 @@ warn :: HasCallStack => Solver -> Text -> IO ()
307351warn = logMessageWith Log. Warning
308352
309353send :: Solver -> SExpr -> IO ()
310- send Solver { solverHandle = SolverHandle { hIn }, logger } command' = do
311- logDebugSolverSendWith logger command'
312- sendSExpr hIn command'
313- hPutChar hIn ' \n '
314- hFlush hIn
354+ send Solver { solverHandle = SolverHandle { hIn, hProc }, logger } command' =
355+ trySolver hProc $ do
356+ logDebugSolverSendWith logger command'
357+ sendSExpr hIn command'
358+ hPutChar hIn ' \n '
359+ hFlush hIn
315360
316361recv :: Solver -> IO SExpr
317- recv Solver { solverHandle = SolverHandle { hOut } , logger } = do
318- responseLines <- readResponse 0 []
319- let resp = Text. unlines (reverse responseLines)
320- logDebugSolverRecvWith logger resp
321- readSExpr resp
362+ recv Solver { solverHandle = SolverHandle { hOut, hProc } , logger } =
363+ trySolver hProc $ do
364+ responseLines <- readResponse 0 []
365+ let resp = Text. unlines (reverse responseLines)
366+ logDebugSolverRecvWith logger resp
367+ readSExpr resp
322368 where
323369 {-| Reads an SMT response.
324370
@@ -345,17 +391,17 @@ command solver c =
345391 recv solver
346392
347393stop :: Solver -> IO ExitCode
348- stop solver@ Solver { solverHandle = SolverHandle { hIn, hOut, hErr, hProc } } = do
349- send solver ( List [ Atom " exit " ])
350- ec <- waitForProcess hProc
351- let handler :: X. IOException -> IO ()
352- handler ex = (debug solver . Text. pack) ( show ex )
353- X. handle handler $ do
354- hClose hIn
355- hClose hOut
356- hClose hErr
357- return ec
358-
394+ stop solver@ Solver { solverHandle = SolverHandle { hIn, hOut, hErr, hProc } } =
395+ trySolver hProc $ do
396+ send solver ( List [ Atom " exit " ])
397+ ec <- waitForProcess hProc
398+ let handler :: X. IOException -> IO ( )
399+ handler ex = (debug solver . Text. pack) ( show ex)
400+ X. handle handler $ do
401+ hClose hIn
402+ hClose hOut
403+ hClose hErr
404+ return ec
359405
360406-- | Load the contents of a file.
361407loadFile :: Solver -> FilePath -> IO ()
@@ -366,7 +412,6 @@ loadFile s file = do
366412 Right exprs ->
367413 mapM_ (command s) exprs
368414
369-
370415-- | A command with no interesting result.
371416ackCommand :: Solver -> SExpr -> IO ()
372417ackCommand solver c =
0 commit comments