-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement execution of swine-z3 on SMT2 files #65
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
//! Not a SAT solver, but a prover. There's a difference. | ||
|
||
use std::{fmt::Display, time::Duration}; | ||
//use std::{fmt::Display, time::Duration}; | ||
|
||
use std::{collections::VecDeque, fmt::Display, io::Write, path::Path, process::Command, time::Duration}; | ||
|
||
use tempfile::NamedTempFile; | ||
|
||
use z3::{ | ||
ast::{forall_const, Ast, Bool, Dynamic}, | ||
|
@@ -21,6 +25,68 @@ pub enum ProveResult<'ctx> { | |
Unknown(ReasonUnknown), | ||
} | ||
|
||
/// Find the swine-z3 file located under the dir directory, and execute swine-z3 on the file located at file_path | ||
fn execute_swine(dir: &Path, file_path: &Path) { | ||
let swine = "swine-z3"; | ||
|
||
let find_output = Command::new("find") | ||
.arg(dir) | ||
.arg("-name") | ||
.arg(swine) | ||
.output().unwrap(); | ||
|
||
if find_output.status.success() { | ||
let stdout = String::from_utf8_lossy(&find_output.stdout); | ||
|
||
for line in stdout.lines().rev() { | ||
let path = Path::new(line); | ||
|
||
if path.exists() && path.is_file() { | ||
let cmd_output = Command::new(path) | ||
.arg(file_path) | ||
.output().unwrap(); | ||
|
||
if cmd_output.status.success() { | ||
println!("{}", String::from_utf8_lossy(&cmd_output.stdout)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The next step would be to parse the output of SWINE and return a SatResult. |
||
break; | ||
} else { | ||
eprintln!("Failed to execute swine({}) command with status: {}", line, cmd_output.status); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, return a |
||
} | ||
} | ||
} | ||
} else { | ||
eprintln!("Find command execution failed"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
} | ||
} | ||
|
||
fn remove_lines_for_swine(input: &str) -> String { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a doc comment saying which lines this removes. |
||
let mut output = String::new(); | ||
let mut tmp_buffer: VecDeque<char> = VecDeque::new(); | ||
let mut input_buffer: VecDeque<char> = input.chars().collect(); | ||
let mut cnt = 0; | ||
|
||
while let Some(c) = input_buffer.pop_front() { | ||
tmp_buffer.push_back(c); | ||
match c { | ||
'(' => { | ||
cnt += 1; | ||
} | ||
')' => { | ||
cnt -= 1; | ||
if cnt == 0 { | ||
let tmp: String = tmp_buffer.iter().collect(); | ||
if !tmp.contains("declare-fun exp") && !tmp.contains("forall") { | ||
output.push_str(&tmp); | ||
} | ||
tmp_buffer.clear(); | ||
} | ||
} | ||
_ => {} | ||
} | ||
} | ||
output | ||
} | ||
|
||
impl Display for ProveResult<'_> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match self { | ||
|
@@ -94,6 +160,21 @@ impl<'ctx> Prover<'ctx> { | |
if self.min_level_with_provables.is_none() { | ||
return ProveResult::Proof; | ||
} | ||
|
||
let mut smtlib = self.get_smtlib(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a next step, add an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can do this like we did it for |
||
|
||
smtlib.add_check_sat(); | ||
|
||
let smtlib = smtlib.into_string(); | ||
let mut smt_file: NamedTempFile = NamedTempFile::new().unwrap(); | ||
|
||
smt_file.write_all(remove_lines_for_swine(&smtlib).as_bytes()).unwrap(); | ||
|
||
let file_path = smt_file.path(); | ||
let start_dir = Path::new("../"); | ||
|
||
execute_swine(start_dir, file_path); | ||
|
||
let res = if assumptions.is_empty() { | ||
self.solver.check() | ||
} else { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why you'd be using
find
here? It should be sufficient to just do the call to swine directly.