Skip to content

Commit 2e50b5a

Browse files
Se Rin YangSe Rin Yang
authored andcommitted
Implement execution of swine-z3 on SMT2 files
1 parent d4fd2ae commit 2e50b5a

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

z3rro/src/prover.rs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
//! Not a SAT solver, but a prover. There's a difference.
22
3-
use std::{fmt::Display, time::Duration};
3+
//use std::{fmt::Display, time::Duration};
4+
5+
use std::{collections::VecDeque, fmt::Display, io::Write, path::Path, process::Command, time::Duration};
6+
7+
use tempfile::NamedTempFile;
48

59
use z3::{
610
ast::{forall_const, Ast, Bool, Dynamic},
@@ -21,6 +25,68 @@ pub enum ProveResult<'ctx> {
2125
Unknown(ReasonUnknown),
2226
}
2327

28+
/// Find the swine-z3 file located under the dir directory, and execute swine-z3 on the file located at file_path
29+
fn execute_swine(dir: &Path, file_path: &Path) {
30+
let swine = "swine-z3";
31+
32+
let find_output = Command::new("find")
33+
.arg(dir)
34+
.arg("-name")
35+
.arg(swine)
36+
.output().unwrap();
37+
38+
if find_output.status.success() {
39+
let stdout = String::from_utf8_lossy(&find_output.stdout);
40+
41+
for line in stdout.lines().rev() {
42+
let path = Path::new(line);
43+
44+
if path.exists() && path.is_file() {
45+
let cmd_output = Command::new(path)
46+
.arg(file_path)
47+
.output().unwrap();
48+
49+
if cmd_output.status.success() {
50+
println!("{}", String::from_utf8_lossy(&cmd_output.stdout));
51+
break;
52+
} else {
53+
eprintln!("Failed to execute swine({}) command with status: {}", line, cmd_output.status);
54+
}
55+
}
56+
}
57+
} else {
58+
eprintln!("Find command execution failed");
59+
}
60+
}
61+
62+
fn remove_lines_for_swine(input: &str) -> String {
63+
let mut output = String::new();
64+
let mut tmp_buffer: VecDeque<char> = VecDeque::new();
65+
let mut input_buffer: VecDeque<char> = input.chars().collect();
66+
let mut cnt = 0;
67+
68+
while let Some(c) = input_buffer.pop_front() {
69+
tmp_buffer.push_back(c);
70+
match c {
71+
'(' => {
72+
cnt += 1;
73+
}
74+
')' => {
75+
cnt -= 1;
76+
if cnt == 0 {
77+
let tmp: String = tmp_buffer.iter().collect();
78+
if !tmp.contains("declare-fun exp") && !tmp.contains("forall") {
79+
output.push_str(&tmp);
80+
}
81+
tmp_buffer.clear();
82+
}
83+
}
84+
_ => {}
85+
}
86+
}
87+
output
88+
}
89+
2490
impl Display for ProveResult<'_> {
2591
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2692
match self {
@@ -94,6 +160,21 @@ impl<'ctx> Prover<'ctx> {
94160
if self.min_level_with_provables.is_none() {
95161
return ProveResult::Proof;
96162
}
163+
164+
let mut smtlib = self.get_smtlib();
165+
166+
smtlib.add_check_sat();
167+
168+
let smtlib = smtlib.into_string();
169+
let mut smt_file: NamedTempFile = NamedTempFile::new().unwrap();
170+
171+
smt_file.write_all(remove_lines_for_swine(&smtlib).as_bytes()).unwrap();
172+
173+
let file_path = smt_file.path();
174+
let start_dir = Path::new("../");
175+
176+
execute_swine(start_dir, file_path);
177+
97178
let res = if assumptions.is_empty() {
98179
self.solver.check()
99180
} else {

0 commit comments

Comments
 (0)