copilot-theorem-4.8: src/Copilot/Theorem/Kind2/Prover.hs
{-# LANGUAGE Trustworthy #-}
-- | A prover backend based on Kind2.
module Copilot.Theorem.Kind2.Prover
( module Data.Default
, Options (..)
, kind2Prover
) where
import Copilot.Theorem.Prove
import Copilot.Theorem.Kind2.Output
import Copilot.Theorem.Kind2.PrettyPrint
import Copilot.Theorem.Kind2.Translate
-- It seems [IO.openTempFile] doesn't work on Mac OSX
import System.IO hiding (openTempFile)
import Copilot.Theorem.Misc.Utils (openTempFile)
import System.Process
import System.Directory
import Data.Default
import qualified Data.Map as Map
import qualified Copilot.Theorem.Misc.Error as Err
import qualified Copilot.Theorem.TransSys as TS
-- | Options for Kind2
data Options = Options
{ bmcMax :: Int -- ^ Upper bound on the number of unrolling that base and
-- step will perform (passed to Kind2 via its
-- @--unroll_max@ option). A value of 0 means /unlimited/.
}
-- | Default options with unlimited unrolling for base and step.
instance Default Options where
def = Options { bmcMax = 0 }
data ProverST = ProverST
{ options :: Options
, transSys :: TS.TransSys }
-- | A prover backend based on Kind2.
--
-- The executable @kind2@ must exist and its location be in the @PATH@. Kind2
-- version 1.0 or newer is required: the native input format and the
-- command-line options this prover uses were introduced in Kind2 1.0, and
-- remain supported as of Kind2 3.0.
kind2Prover :: Options -> Prover
kind2Prover opts = Prover
{ proverName = "Kind2"
, startProver = return . ProverST opts . TS.translate
, askProver = askKind2
, closeProver = const $ return () }
kind2Prog = "kind2"
kind2BaseOptions = ["--input_format", "native", "-xml"]
askKind2 :: ProverST -> [PropId] -> [PropId] -> IO Output
askKind2 (ProverST opts spec) assumptions toCheck = do
let kind2Input = prettyPrint . toKind2 assumptions toCheck $ spec
(tempName, tempHandle) <- openTempFile "." "out" "kind"
hPutStr tempHandle kind2Input
hClose tempHandle
let kind2Options =
kind2BaseOptions ++ ["--unroll_max", show $ bmcMax opts, tempName]
(_, output, _) <- readProcessWithExitCode kind2Prog kind2Options ""
removeFile tempName
let propId = head toCheck
propQuantifier = case Map.lookup propId (TS.specProps spec) of
Just (_, quantifier) ->
quantifier
Nothing ->
Err.impossible $
"askKind2: " ++ propId ++ " not in specProps"
return $ parseOutput propId propQuantifier output