diff --git a/src/relation.rs b/src/relation.rs index b671fe0..78aa848 100644 --- a/src/relation.rs +++ b/src/relation.rs @@ -11,8 +11,8 @@ use crate::{ /// A relation represents a fixed set of key-value pairs. In many places in a /// Datalog computation we want to be sure that certain relations are not able /// to vary (for example, in antijoins). -#[derive(Clone)] -pub struct Relation { +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Relation { /// Sorted list of distinct tuples. pub elements: Vec, } @@ -99,7 +99,7 @@ impl FromIterator for Relation { } } -impl<'tuple, Tuple: 'tuple + Copy + Ord> FromIterator<&'tuple Tuple> for Relation { +impl<'tuple, Tuple: 'tuple + Clone + Ord> FromIterator<&'tuple Tuple> for Relation { fn from_iter(iterator: I) -> Self where I: IntoIterator, @@ -108,7 +108,7 @@ impl<'tuple, Tuple: 'tuple + Copy + Ord> FromIterator<&'tuple Tuple> for Relatio } } -impl std::ops::Deref for Relation { +impl std::ops::Deref for Relation { type Target = [Tuple]; fn deref(&self) -> &Self::Target { &self.elements[..] diff --git a/src/variable.rs b/src/variable.rs index 4950488..537822c 100644 --- a/src/variable.rs +++ b/src/variable.rs @@ -36,7 +36,7 @@ pub(crate) trait VariableTrait { /// of performance. Such a variable cannot be relied on to terminate iterative computation, /// and it is important that any cycle of derivations have at least one de-duplicating /// variable on it. -pub struct Variable { +pub struct Variable { /// Should the variable be maintained distinctly. pub(crate) distinct: bool, /// A useful name for the variable. @@ -49,6 +49,26 @@ pub struct Variable { pub(crate) to_add: Rc>>>, } +impl Variable { + /// Returns the name used to create this variable. + pub fn name(&self) -> &str { + self.name.as_str() + } + + /// Returns the total number of "stable" tuples in this variable. + pub fn num_stable(&self) -> usize { + self.stable.borrow().iter().map(|x| x.len()).sum() + } + + /// Returns `true` if this variable contains only "stable" tuples. + /// + /// Calling `Iteration::changed()` on such `Variables` will not change them unless new tuples + /// are added. + pub fn is_stable(&self) -> bool { + self.recent.borrow().is_empty() && self.to_add.borrow().is_empty() + } +} + // Operator implementations. impl Variable { /// Adds tuples that result from joining `input1` and `input2` -- @@ -251,7 +271,7 @@ impl Variable { } } -impl Clone for Variable { +impl Clone for Variable { fn clone(&self) -> Self { Variable { distinct: self.distinct, @@ -304,8 +324,7 @@ impl Variable { /// asserts that iteration has completed, in that `self.recent` and /// `self.to_add` should both be empty. pub fn complete(self) -> Relation { - assert!(self.recent.borrow().is_empty()); - assert!(self.to_add.borrow().is_empty()); + assert!(self.is_stable()); let mut result: Relation = Vec::new().into(); while let Some(batch) = self.stable.borrow_mut().pop() { result = result.merge(batch);