module Ersatz.Solver.Common
( withTempFiles
, resultOf
, trySolvers
, NoSolvers(..)
) where
import Control.Exception (Exception(..), throwIO)
import Control.Monad.IO.Class
import Ersatz.Solution
import System.Exit (ExitCode(..))
import System.IO.Error (isDoesNotExistError, tryIOError)
import System.IO.Temp (withSystemTempDirectory)
withTempFiles :: MonadIO m
=> FilePath
-> FilePath
-> (FilePath -> FilePath -> IO a) -> m a
withTempFiles problemExt solutionExt f = liftIO $
withSystemTempDirectory "ersatz" $ \dir -> do
let problemPath = dir ++ "/problem" ++ problemExt
solutionPath = dir ++ "/solution" ++ solutionExt
f problemPath solutionPath
resultOf :: ExitCode -> Result
resultOf (ExitFailure 10) = Satisfied
resultOf (ExitFailure 20) = Unsatisfied
resultOf _ = Unsolved
newtype NoSolvers = NoSolvers [IOError] deriving Show
instance Exception NoSolvers where
displayException _ = "no ersatz solvers were found"
trySolvers :: [Solver s IO] -> Solver s IO
trySolvers solvers problem = foldr runSolver noSolvers solvers []
where
noSolvers = throwIO . NoSolvers . reverse
runSolver solver next es =
do res <- tryIOError (solver problem)
case res of
Left e
| isDoesNotExistError e -> next (e:es)
| otherwise -> ioError e
Right x -> return x