use serde::{Deserialize, Serialize};
use crate::abstr::{Abstr, AbstractValue};
use crate::bitvector::bound::{CBound, RBound};
use crate::concr::{ConcreteBitvector, SignedBitvector, UnsignedBitvector};
use crate::misc::{BitvectorBound, Join, MetaEq};
use std::fmt::Display;
use std::hash::Hash;
pub mod combination;
pub mod combined;
pub mod dual_interval;
pub mod eq_domain;
pub mod three_valued;
pub trait BitvectorDomain: Clone + Copy + Hash + Join + MetaEq {
type Bound: BitvectorBound;
type General<X: BitvectorBound>: BitvectorDomain<Bound = X>;
fn bound(&self) -> Self::Bound;
fn single_value(value: ConcreteBitvector<Self::Bound>) -> Self;
fn top(bound: Self::Bound) -> Self;
fn meet(self, other: &Self) -> Option<Self>;
fn umin(&self) -> UnsignedBitvector<Self::Bound>;
fn umax(&self) -> UnsignedBitvector<Self::Bound>;
fn smin(&self) -> SignedBitvector<Self::Bound>;
fn smax(&self) -> SignedBitvector<Self::Bound>;
fn concrete_value(&self) -> Option<ConcreteBitvector<Self::Bound>>;
fn display(&self) -> BitvectorDisplay;
fn get_tracker(&self) -> Option<u32> {
None
}
fn assign_tracker(&mut self, _tracker: Option<u32>) {}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DomainDisplay {
Value(String),
Tracker(u32),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BitvectorDisplay {
domains: Vec<DomainDisplay>,
}
pub trait CBitvectorDomain: BitvectorDomain {
type Concrete;
fn from_concrete_bitvector(value: Self::Concrete) -> Self;
fn from_runtime_bitvector(value: Self::General<RBound>) -> Self;
fn as_runtime_bitvector(&self) -> Self::General<RBound>;
}
#[cfg(all(not(feature = "Zdual_interval"), not(feature = "Zeq_domain")))]
pub type Bitvector<B> = three_valued::ThreeValuedBitvector<B>;
#[cfg(all(feature = "Zdual_interval", not(feature = "Zeq_domain")))]
pub type Bitvector<B> = combined::CombinedBitvector<B, combination::TVDICombination<B>>;
#[cfg(all(not(feature = "Zdual_interval"), feature = "Zeq_domain"))]
pub type Bitvector<B> = combined::CombinedBitvector<B, combination::TVEQCombination<B>>;
#[cfg(all(feature = "Zdual_interval", feature = "Zeq_domain"))]
pub type Bitvector<B> = combined::CombinedBitvector<B, combination::TVDIEQCombination<B>>;
pub type RBitvector = Bitvector<RBound>;
pub type CBitvector<const W: u32> = Bitvector<CBound<W>>;
pub type PanicBitvector = Bitvector<CBound<32>>;
impl<const W: u32> Abstr<super::concr::Bitvector<CBound<W>>> for Bitvector<CBound<W>> {
fn from_concrete(value: super::concr::Bitvector<CBound<W>>) -> Self {
Self::from_concrete_bitvector(value)
}
fn from_runtime(value: &AbstractValue) -> Self {
Self::from_runtime_bitvector(*value.expect_bitvector())
}
fn to_runtime(&self) -> AbstractValue {
AbstractValue::Bitvector(self.as_runtime_bitvector())
}
}
impl Display for BitvectorDisplay {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.domains.is_empty() {
return write!(f, "⊤");
}
let mut first = true;
for domain in &self.domains {
if first {
first = false;
} else {
write!(f, " ∩ ")?;
}
match domain {
DomainDisplay::Value(value) => write!(f, "{}", value),
DomainDisplay::Tracker(tracker) => write!(f, "Eq(#{})", tracker),
}?;
}
Ok(())
}
}