use std::num::NonZeroU8;
use serde::{Deserialize, Serialize};
use crate::{
abstr::{self},
backward::Bitwise,
misc::{Meta, MetaEq},
ParamValuation, ThreeValued,
};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Boolean(u8);
impl Boolean {
pub fn new_unmarked() -> Self {
Self(0)
}
pub fn new_marked(importance: NonZeroU8) -> Self {
Self(importance.get())
}
pub fn new_marked_unimportant() -> Self {
Self(1)
}
pub fn importance(&self) -> u8 {
self.0
}
pub fn apply_refin(&mut self, offer: &Self) -> bool {
if offer.0 != 0 && self.0 == 0 {
self.0 = offer.0;
true
} else {
false
}
}
pub fn apply_join(&mut self, other: &Self) {
self.0 = self.0.max(other.0);
}
pub fn to_condition(&self) -> Boolean {
*self
}
pub fn force_decay(&self, target: &mut super::abstr::Boolean) {
if self.0 == 0 {
*target = super::abstr::Boolean::from_three_valued(ThreeValued::Unknown);
}
}
pub fn limit(self, abstr: &abstr::Boolean) -> Self {
if !abstr.is_unknown() {
Self(0)
} else {
self
}
}
}
impl Meta<super::abstr::Boolean> for Boolean {
fn proto_first(&self) -> super::abstr::Boolean {
let result = if self.0 == 0 {
ThreeValued::Unknown
} else {
ThreeValued::False
};
super::abstr::Boolean::from_three_valued(result)
}
fn proto_increment(&self, proto: &mut super::abstr::Boolean) -> bool {
match proto.value() {
ParamValuation::False => {
*proto = super::abstr::Boolean::from_param_valuation(ParamValuation::True);
true
}
ParamValuation::True | ParamValuation::Dependent | ParamValuation::Unknown => {
false
}
}
}
}
impl Bitwise for abstr::Boolean {
type Mark = Boolean;
fn bit_not(_normal_input: (Self,), mark_later: Self::Mark) -> (Self::Mark,) {
(mark_later,)
}
fn bit_and(normal_input: (Self, Self), mark_later: Self::Mark) -> (Self::Mark, Self::Mark) {
(
mark_later.limit(&normal_input.0),
mark_later.limit(&normal_input.1),
)
}
fn bit_or(normal_input: (Self, Self), mark_later: Self::Mark) -> (Self::Mark, Self::Mark) {
(
mark_later.limit(&normal_input.0),
mark_later.limit(&normal_input.1),
)
}
fn bit_xor(normal_input: (Self, Self), mark_later: Self::Mark) -> (Self::Mark, Self::Mark) {
(
mark_later.limit(&normal_input.0),
mark_later.limit(&normal_input.1),
)
}
}
impl MetaEq for Boolean {
fn meta_eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}