1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
use std::fmt::Debug;
use std::iter::ExactSizeIterator;
use crate::*;
/// An equivalence class of enodes.
#[non_exhaustive]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct EClass<L, D> {
/// This eclass's id.
pub id: Id,
/// The equivalent enodes in this equivalence class.
pub nodes: Vec<L>,
/// The analysis data associated with this eclass.
///
/// Modifying this field will _not_ cause changes to propagate through the e-graph.
/// Prefer [`EGraph::set_analysis_data`] instead.
pub data: D,
/// The parent enodes and their original Ids.
pub(crate) parents: Vec<(L, Id)>,
}
impl<L, D> EClass<L, D> {
/// Returns `true` if the `eclass` is empty.
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
/// Returns the number of enodes in this eclass.
pub fn len(&self) -> usize {
self.nodes.len()
}
/// Iterates over the enodes in this eclass.
pub fn iter(&self) -> impl ExactSizeIterator<Item = &L> {
self.nodes.iter()
}
/// Iterates over the parent enodes of this eclass.
pub fn parents(&self) -> impl ExactSizeIterator<Item = (&L, Id)> {
self.parents.iter().map(|(node, id)| (node, *id))
}
}
impl<L: Language, D> EClass<L, D> {
/// Iterates over the childless enodes in this eclass.
pub fn leaves(&self) -> impl Iterator<Item = &L> {
self.nodes.iter().filter(|&n| n.is_leaf())
}
/// Asserts that the childless enodes in this eclass are unique.
pub fn assert_unique_leaves(&self)
where
L: Language,
{
let mut leaves = self.leaves();
if let Some(first) = leaves.next() {
assert!(
leaves.all(|l| l == first),
"Different leaves in eclass {}: {:?}",
self.id,
self.leaves().collect::<crate::util::HashSet<_>>()
);
}
}
}