import system.io import .builder import .syntax import .solvers.z3 inductive smt2.response | sat | unsat | unknown | other : string → smt2.response meta def parse_smt2_result (str : string) : smt2.response := if str = "sat\n" then smt2.response.sat else if str = "unsat\n" then smt2.response.unsat else if str = "unknown\n" then smt2.response.unknown else smt2.response.other str meta def cmds_to_string (cmds : list smt2.cmd) : string := to_string $ format.join $ list.intersperse "\n" $ list.map (λ c, to_fmt c) cmds.reverse meta def smt2 [io.interface] (build : smt2.builder unit) (log_query : option string := none) : io smt2.response := do z3 ← z3_instance.start, -- maybe we should have a primitive to go from fmt to char buffer let (exc, cmds) := build.run, match exc with | (except.error e) := io.fail $ "builder failed with: " ++ e -- TODO: better message | (except.ok v) := do let query := cmds_to_string cmds, match log_query with | none := return () | some fn := do file ← io.mk_file_handle fn io.mode.write, io.fs.write file (query.to_list.to_buffer) end, res ← z3.raw query, return $ parse_smt2_result res end