use std::{
cmp::Ordering,
ops::{Index, IndexMut},
};
use ascent::Lattice;
use itertools::zip_eq;
use super::{AbstractValue, PartialValue};
#[derive(PartialEq, Clone, Debug, Eq, Hash)]
pub(super) struct ValueRow<V, N>(Vec<PartialValue<V, N>>);
impl<V: AbstractValue, N: Clone> ValueRow<V, N> {
pub fn new(len: usize) -> Self {
Self(vec![PartialValue::Bottom; len])
}
pub fn set(mut self, idx: usize, v: PartialValue<V, N>) -> Self {
*self.0.get_mut(idx).unwrap() = v;
self
}
pub fn singleton(v: PartialValue<V, N>) -> Self {
Self(vec![v])
}
pub fn unpack_first(
&self,
variant: usize,
len: usize,
) -> Option<impl Iterator<Item = PartialValue<V, N>> + use<V, N>> {
let vals = self[0].variant_values(variant, len)?;
Some(vals.into_iter().chain(self.0[1..].to_owned()))
}
}
impl<V, N> FromIterator<PartialValue<V, N>> for ValueRow<V, N> {
fn from_iter<T: IntoIterator<Item = PartialValue<V, N>>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl<V: PartialEq, N: PartialEq + PartialOrd> PartialOrd for ValueRow<V, N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<V: AbstractValue, N: PartialEq + PartialOrd> Lattice for ValueRow<V, N> {
fn join_mut(&mut self, other: Self) -> bool {
assert_eq!(self.0.len(), other.0.len());
let mut changed = false;
for (v1, v2) in zip_eq(self.0.iter_mut(), other.0) {
changed |= v1.join_mut(v2);
}
changed
}
fn meet_mut(&mut self, other: Self) -> bool {
assert_eq!(self.0.len(), other.0.len());
let mut changed = false;
for (v1, v2) in zip_eq(self.0.iter_mut(), other.0) {
changed |= v1.meet_mut(v2);
}
changed
}
}
impl<V, N> IntoIterator for ValueRow<V, N> {
type Item = PartialValue<V, N>;
type IntoIter = <Vec<PartialValue<V, N>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<V, N, Idx> Index<Idx> for ValueRow<V, N>
where
Vec<PartialValue<V, N>>: Index<Idx>,
{
type Output = <Vec<PartialValue<V, N>> as Index<Idx>>::Output;
fn index(&self, index: Idx) -> &Self::Output {
self.0.index(index)
}
}
impl<V, N, Idx> IndexMut<Idx> for ValueRow<V, N>
where
Vec<PartialValue<V, N>>: IndexMut<Idx>,
{
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
self.0.index_mut(index)
}
}