implementation module Z3 import StdString import System.Process import Text :: Z3 = { handle :: ProcessHandle , stdIn :: WritePipe , stdOut :: ReadPipe , stdErr :: ReadPipe } startZ3 :: !*World -> (!Z3, !*World) startZ3 w # (err, w) = runProcessIO "z3" ["-smt2", "-in"] Nothing w # (handle, {ProcessIO | stdIn, stdOut, stdErr}) = fromOk err # z3 = { Z3 | handle = handle, stdIn = stdIn, stdOut = stdOut, stdErr = stdErr } = (z3, w) addAssert :: !Z3 !String !*World -> *World addAssert z3 s w # (_, w) = writePipe ("(assert " <+ s <+ ")\n") z3.Z3.stdIn w = w addVariable :: !Z3 !String !*World -> *World addVariable z3 s w # (_, w) = writePipe ("(declare-const " <+ s <+ " Real)\n") z3.Z3.stdIn w = w checkSat :: !Z3 !*World -> (!Bool, !*World) checkSat z3 w # (_, w) = writePipe "(check-sat)\n" z3.Z3.stdIn w # (out, w) = readPipeBlocking z3.Z3.stdOut w # out = fromOk out = (startsWith "sat" out, w) getModel :: !Z3 !*World -> (!String, !*World) getModel z3 w # (_, w) = writePipe "(get-model)\n" z3.Z3.stdIn w # (_, w) = writePipe "(exit)\n" z3.Z3.stdIn w # (_, w) = waitForProcess z3.Z3.handle w # (out, w) = readPipeNonBlocking z3.Z3.stdOut w # out = fromOk out = (out, w)