implementation module Z3 import StdList import StdMisc import StdString import System.Process import Text import StdDebug from Data.Func import $ trace_id x = trace x x :: 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 (trace_id $ "(assert " <+ s <+ ")\n") z3.Z3.stdIn w = w addMinimize :: !Z3 !String !*World -> *World addMinimize z3 s w # (_, w) = writePipe (trace_id $ "(minimize " <+ s <+ ")\n") z3.Z3.stdIn w = w addVariable :: !Z3 !String !String !*World -> *World addVariable z3 type s w # (_, w) = writePipe (trace_id $ "(declare-const " <+ s <+ " " <+ type <+ ")\n") z3.Z3.stdIn w = w checkSat :: !Z3 !*World -> (!Satisfaction, !*World) checkSat z3 w # (_, w) = writePipe "(check-sat)\n" z3.Z3.stdIn w # (out, w) = readPipeBlocking z3.Z3.stdOut w # out = fromOk out # out = trace_id out = (case last $ init $ split "\n" out of "sat" -> Sat "unsat" -> Unsat "unknown" -> Unknown _ -> abort "Z3 failed\n", 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)