use crate::driver::Config;
use crate::parser::Response;
use crate::solver::Solver;
use crate::term::{LogicError, Sort, Term};
pub struct MultiSolver {
pub configs: Vec<Config>,
pub asserts: Vec<Term>,
pub declares: Vec<(String, Sort)>,
}
impl MultiSolver {
pub fn new(configs: Vec<Config>) -> Self {
MultiSolver {
configs,
asserts: Vec::new(),
declares: Vec::new(),
}
}
pub fn assert(&mut self, term: &Term) {
self.asserts.push(term.clone());
}
pub fn declare(&mut self, name: &str, sort: &Sort) {
self.declares.push((name.to_string(), *sort));
}
#[cfg(not(feature = "tokio"))]
pub fn check(&mut self) -> Result<Response, LogicError> {
if self.configs.is_empty() {
return Err(LogicError::Solver("no solver configs provided".into()));
}
let mut last_error = None;
let max_attempts = self.configs.len();
for (idx, config) in self.configs.iter().enumerate() {
if idx >= max_attempts {
break;
}
match Solver::new(config.clone()) {
Ok(mut solver) => {
let mut setup_failed = false;
for (name, sort) in &self.declares {
if let Err(e) = solver.declare(name, sort) {
last_error = Some(e);
setup_failed = true;
break;
}
}
if setup_failed { continue; }
for term in &self.asserts {
if let Err(e) = solver.assert(term) {
last_error = Some(e);
setup_failed = true;
break;
}
}
if setup_failed { continue; }
match solver.check() {
Ok(response) => return Ok(response),
Err(e) => {
last_error = Some(e);
}
}
}
Err(e) => {
last_error = Some(e);
}
}
}
Err(last_error.unwrap_or_else(|| LogicError::Solver("all solvers failed".into())))
}
#[cfg(feature = "tokio")]
pub async fn check(&mut self) -> Result<Response, LogicError> {
if self.configs.is_empty() {
return Err(LogicError::Solver("no solver configs provided".into()));
}
let mut last_error = None;
let max_attempts = self.configs.len();
for (idx, config) in self.configs.iter().enumerate() {
if idx >= max_attempts {
break;
}
match Solver::new(config.clone()).await {
Ok(mut solver) => {
let mut failed = false;
for (name, sort) in &self.declares {
if let Err(e) = solver.declare(name, sort).await {
last_error = Some(e);
failed = true;
break;
}
}
if failed { continue; }
for term in &self.asserts {
if let Err(e) = solver.assert(term).await {
last_error = Some(e);
failed = true;
break;
}
}
if failed { continue; }
match solver.check().await {
Ok(response) => return Ok(response),
Err(e) => {
last_error = Some(e);
}
}
}
Err(e) => {
last_error = Some(e);
}
}
}
Err(last_error.unwrap_or_else(|| LogicError::Solver("all solvers failed".into())))
}
}