use cvc5_sys::Cvc5InputLanguage as InputLanguage;
use cvc5_sys::parser::*;
use std::borrow::Borrow;
use std::ffi::CString;
use std::fmt;
use crate::{Solver, Sort, Term, TermManager};
pub struct SymbolManager {
pub(crate) inner: *mut Cvc5SymbolManager,
tm: TermManager,
}
impl SymbolManager {
pub fn new(tm: impl Borrow<TermManager>) -> Self {
let tm = tm.borrow().clone();
Self {
inner: unsafe { cvc5_symbol_manager_new(tm.ptr()) },
tm,
}
}
pub fn term_manager(&self) -> TermManager {
self.tm.clone()
}
pub fn is_logic_set(&self) -> bool {
unsafe { cvc5_sm_is_logic_set(self.inner) }
}
pub fn get_logic(&self) -> &str {
unsafe {
let s = cvc5_sm_get_logic(self.inner);
std::ffi::CStr::from_ptr(s).to_str().unwrap_or("")
}
}
pub fn get_declared_sorts(&self) -> Vec<Sort> {
let mut size = 0usize;
let ptr = unsafe { cvc5_sm_get_declared_sorts(self.inner, &mut size) };
(0..size)
.map(|i| Sort::from_raw(unsafe { *ptr.add(i) }))
.collect()
}
pub fn get_declared_terms(&self) -> Vec<Term> {
let mut size = 0usize;
let ptr = unsafe { cvc5_sm_get_declared_terms(self.inner, &mut size) };
(0..size)
.map(|i| Term::from_raw(unsafe { *ptr.add(i) }))
.collect()
}
pub fn get_named_terms(&self) -> Vec<(Term, String)> {
let mut size = 0usize;
let mut terms: *mut cvc5_sys::Cvc5Term = std::ptr::null_mut();
let mut names: *mut *const std::os::raw::c_char = std::ptr::null_mut();
unsafe { cvc5_sm_get_named_terms(self.inner, &mut size, &mut terms, &mut names) };
(0..size)
.map(|i| unsafe {
let t = Term::from_raw(*terms.add(i));
let n = std::ffi::CStr::from_ptr(*names.add(i))
.to_string_lossy()
.into_owned();
(t, n)
})
.collect()
}
}
impl Drop for SymbolManager {
fn drop(&mut self) {
unsafe { cvc5_symbol_manager_delete(self.inner) }
}
}
pub struct Command {
pub(crate) inner: Cvc5Command,
}
impl Command {
pub(crate) fn from_raw(raw: Cvc5Command) -> Self {
Self { inner: raw }
}
pub fn is_null(&self) -> bool {
self.inner.is_null()
}
pub fn invoke(&self, solver: &mut Solver, sm: &mut SymbolManager) -> String {
unsafe {
std::ffi::CStr::from_ptr(cvc5_cmd_invoke(self.inner, solver.inner, sm.inner))
.to_string_lossy()
.into_owned()
}
}
pub fn name(&self) -> &str {
unsafe {
let s = cvc5_cmd_get_name(self.inner);
std::ffi::CStr::from_ptr(s).to_str().unwrap_or("")
}
}
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = unsafe { cvc5_cmd_to_string(self.inner) };
let cs = unsafe { std::ffi::CStr::from_ptr(s) };
write!(f, "{}", cs.to_string_lossy())
}
}
impl fmt::Debug for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Command({self})")
}
}
pub struct InputParser {
pub(crate) inner: *mut Cvc5InputParser,
_tm: TermManager,
}
impl InputParser {
pub fn new(solver: &Solver, sm: Option<&SymbolManager>) -> Self {
let sm_ptr = sm.map_or(std::ptr::null_mut(), |s| s.inner);
Self {
inner: unsafe { cvc5_parser_new(solver.inner, sm_ptr) },
_tm: solver.tm.clone(),
}
}
pub fn set_file_input(&mut self, lang: InputLanguage, filename: &str) {
let f = CString::new(filename).unwrap();
unsafe { cvc5_parser_set_file_input(self.inner, lang, f.as_ptr()) }
}
pub fn set_str_input(&mut self, lang: InputLanguage, input: &str, name: &str) {
let i = CString::new(input).unwrap();
let n = CString::new(name).unwrap();
unsafe { cvc5_parser_set_str_input(self.inner, lang, i.as_ptr(), n.as_ptr()) }
}
pub fn set_inc_str_input(&mut self, lang: InputLanguage, name: &str) {
let n = CString::new(name).unwrap();
unsafe { cvc5_parser_set_inc_str_input(self.inner, lang, n.as_ptr()) }
}
pub fn append_inc_str_input(&mut self, input: &str) {
let i = CString::new(input).unwrap();
unsafe { cvc5_parser_append_inc_str_input(self.inner, i.as_ptr()) }
}
pub fn next_command(&mut self) -> std::result::Result<Option<Command>, String> {
let mut error_msg: *const std::os::raw::c_char = std::ptr::null();
let cmd = unsafe { cvc5_parser_next_command(self.inner, &mut error_msg) };
if !error_msg.is_null() {
let msg = unsafe { std::ffi::CStr::from_ptr(error_msg) }
.to_string_lossy()
.into_owned();
return Err(msg);
}
if cmd.is_null() {
Ok(None)
} else {
Ok(Some(Command::from_raw(cmd)))
}
}
pub fn next_term(&mut self) -> std::result::Result<Option<Term>, String> {
let mut error_msg: *const std::os::raw::c_char = std::ptr::null();
let term = unsafe { cvc5_parser_next_term(self.inner, &mut error_msg) };
if !error_msg.is_null() {
let msg = unsafe { std::ffi::CStr::from_ptr(error_msg) }
.to_string_lossy()
.into_owned();
return Err(msg);
}
if term.is_null() {
Ok(None)
} else {
Ok(Some(Term::from_raw(term)))
}
}
pub fn done(&self) -> bool {
unsafe { cvc5_parser_done(self.inner) }
}
}
impl Drop for InputParser {
fn drop(&mut self) {
unsafe { cvc5_parser_delete(self.inner) }
}
}