use std::{
cmp::Ordering,
fmt::Display,
ops::{BitAnd, BitOr, BitXor, Not},
};
use serde::{Deserialize, Serialize};
use crate::{misc::Join, value::ThreeValued};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum KnownParamValuation {
False,
True,
Dependent,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum ParamValuation {
False,
True,
Dependent,
Unknown,
}
impl Not for ParamValuation {
type Output = Self;
fn not(self) -> Self {
match self {
ParamValuation::False => ParamValuation::True,
ParamValuation::True => ParamValuation::False,
ParamValuation::Dependent => ParamValuation::Dependent,
ParamValuation::Unknown => ParamValuation::Unknown,
}
}
}
impl BitAnd for ParamValuation {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
if self.upward_bitand_ordering(&rhs).is_ge() {
self
} else {
rhs
}
}
}
impl BitOr for ParamValuation {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
if self.upward_bitor_ordering(&rhs).is_ge() {
self
} else {
rhs
}
}
}
impl BitXor for ParamValuation {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(ParamValuation::Dependent, _) | (_, ParamValuation::Dependent) => {
ParamValuation::Dependent
}
(ParamValuation::Unknown, _) | (_, ParamValuation::Unknown) => ParamValuation::Unknown,
(ParamValuation::False, ParamValuation::False)
| (ParamValuation::True, ParamValuation::True) => ParamValuation::True,
(ParamValuation::False, ParamValuation::True)
| (ParamValuation::True, ParamValuation::False) => ParamValuation::False,
}
}
}
impl ParamValuation {
pub fn from_bool(value: bool) -> Self {
if value {
Self::True
} else {
Self::False
}
}
pub fn from_three_valued(three_valued: ThreeValued) -> Self {
match three_valued {
ThreeValued::False => ParamValuation::False,
ThreeValued::True => ParamValuation::True,
ThreeValued::Unknown => ParamValuation::Unknown,
}
}
pub fn try_into_bool(self) -> Option<bool> {
match self {
ParamValuation::False => Some(false),
ParamValuation::True => Some(true),
ParamValuation::Dependent | ParamValuation::Unknown => None,
}
}
pub fn is_unknown(&self) -> bool {
matches!(self, ParamValuation::Unknown)
}
pub fn is_known(&self) -> bool {
!self.is_unknown()
}
pub fn can_be_true(&self) -> bool {
matches!(
self,
ParamValuation::True | ParamValuation::Dependent | ParamValuation::Unknown
)
}
pub fn can_be_false(&self) -> bool {
matches!(
self,
ParamValuation::False | ParamValuation::Dependent | ParamValuation::Unknown
)
}
pub fn upward_bitand_ordering(self, rhs: &Self) -> Ordering {
match (self, rhs) {
(ParamValuation::False, ParamValuation::False) => Ordering::Equal,
(ParamValuation::False, _) => Ordering::Greater,
(_, ParamValuation::False) => Ordering::Less,
(ParamValuation::Unknown, ParamValuation::Unknown) => Ordering::Equal,
(ParamValuation::Unknown, _) => Ordering::Greater,
(_, ParamValuation::Unknown) => Ordering::Less,
(ParamValuation::Dependent, ParamValuation::Dependent) => Ordering::Equal,
(ParamValuation::Dependent, ParamValuation::True) => Ordering::Greater,
(ParamValuation::True, ParamValuation::Dependent) => Ordering::Less,
(ParamValuation::True, ParamValuation::True) => Ordering::Equal,
}
}
pub fn upward_bitor_ordering(self, rhs: &Self) -> Ordering {
match (self, rhs) {
(ParamValuation::True, ParamValuation::True) => Ordering::Equal,
(ParamValuation::True, _) => Ordering::Greater,
(_, ParamValuation::True) => Ordering::Less,
(ParamValuation::Unknown, ParamValuation::Unknown) => Ordering::Equal,
(ParamValuation::Unknown, _) => Ordering::Greater,
(_, ParamValuation::Unknown) => Ordering::Less,
(ParamValuation::Dependent, ParamValuation::Dependent) => Ordering::Equal,
(ParamValuation::Dependent, ParamValuation::False) => Ordering::Greater,
(ParamValuation::False, ParamValuation::Dependent) => Ordering::Less,
(ParamValuation::False, ParamValuation::False) => Ordering::Equal,
}
}
}
impl Join for ParamValuation {
fn join(self, other: &Self) -> Self {
match (self, other) {
(ParamValuation::Dependent, _) | (_, ParamValuation::Dependent) => {
ParamValuation::Dependent
}
(ParamValuation::Unknown, _) | (_, ParamValuation::Unknown) => ParamValuation::Unknown,
(ParamValuation::False, ParamValuation::True)
| (ParamValuation::True, ParamValuation::False) => ParamValuation::Unknown,
(ParamValuation::False, ParamValuation::False) => ParamValuation::False,
(ParamValuation::True, ParamValuation::True) => ParamValuation::True,
}
}
}
impl Display for ParamValuation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
ParamValuation::False => "false",
ParamValuation::True => "true",
ParamValuation::Dependent => "dependent",
ParamValuation::Unknown => "unknown",
};
write!(f, "{}", str)
}
}