impl PropertyDomain {
#[must_use]
pub fn top() -> Self {
Self {
nullability: NullabilityLattice::Top,
bounds: IntervalLattice {
lower: None,
upper: None,
},
aliasing: AliasLattice::Top,
purity: PurityLattice::Top,
}
}
#[must_use]
pub fn join(&self, other: &Self) -> Self {
Self {
nullability: self.nullability.join(&other.nullability),
bounds: self.bounds.widen(&other.bounds),
aliasing: self.aliasing.join(&other.aliasing),
purity: self.purity.meet(&other.purity),
}
}
#[must_use]
pub fn widen(&self, other: &Self) -> Self {
Self {
nullability: self.nullability.join(&other.nullability),
bounds: self.bounds.widen(&other.bounds),
aliasing: self.aliasing.join(&other.aliasing),
purity: self.purity.meet(&other.purity),
}
}
#[must_use]
pub fn is_equal(&self, other: &Self) -> bool {
self.nullability == other.nullability
&& self.bounds.is_equal(&other.bounds)
&& self.aliasing == other.aliasing
&& self.purity == other.purity
}
}
impl NullabilityLattice {
#[must_use]
pub fn join(&self, other: &Self) -> Self {
use NullabilityLattice::{Bottom, MaybeNull, NotNull, Null, Top};
match (self, other) {
(Bottom, x) | (x, Bottom) => x.clone(),
(Top, _) | (_, Top) => Top,
(NotNull, NotNull) => NotNull,
(Null, Null) => Null,
(NotNull, Null) | (Null, NotNull) => Bottom, _ => MaybeNull,
}
}
}
impl IntervalLattice {
#[must_use]
pub fn widen(&self, other: &Self) -> Self {
let lower = match (self.lower, other.lower) {
(Some(a), Some(b)) if a > b => None, (l, _) => l,
};
let upper = match (self.upper, other.upper) {
(Some(a), Some(b)) if a < b => None, (u, _) => u,
};
Self { lower, upper }
}
#[must_use]
pub fn is_equal(&self, other: &Self) -> bool {
self.lower == other.lower && self.upper == other.upper
}
}
impl AliasLattice {
#[must_use]
pub fn join(&self, other: &Self) -> Self {
use AliasLattice::{Bottom, MayAlias, MustAlias, NoAlias, Top};
match (self, other) {
(Bottom, x) | (x, Bottom) => x.clone(),
(Top, _) | (_, Top) => Top,
(NoAlias, NoAlias) => NoAlias,
(MustAlias, MustAlias) => MustAlias,
_ => MayAlias,
}
}
}
impl PurityLattice {
#[must_use]
pub fn meet(&self, other: &Self) -> Self {
use PurityLattice::{Bottom, Pure, ReadOnly, Top, WriteGlobal, WriteLocal};
match (self, other) {
(Bottom, _) | (_, Bottom) => Bottom,
(WriteGlobal, _) | (_, WriteGlobal) => WriteGlobal,
(WriteLocal, _) | (_, WriteLocal) => WriteLocal,
(ReadOnly, ReadOnly) => ReadOnly,
(Pure, Pure) => Pure,
_ => Top,
}
}
}