diff --git a/src/snapshot_vec.rs b/src/snapshot_vec.rs index 1c3643d..7bb68a2 100644 --- a/src/snapshot_vec.rs +++ b/src/snapshot_vec.rs @@ -60,8 +60,10 @@ impl fmt::Debug for SnapshotVec // Snapshots are tokens that should be created/consumed linearly. pub struct Snapshot { + // Number of values at the time the snapshot was taken. + pub(crate) value_count: usize, // Length of the undo log at the time the snapshot was taken. - pub(crate) length: usize, + undo_len: usize, } pub trait SnapshotVecDelegate { @@ -173,27 +175,29 @@ impl SnapshotVec { } pub fn start_snapshot(&mut self) -> Snapshot { - let length = self.undo_log.len(); self.num_open_snapshots += 1; - Snapshot { length: length } + Snapshot { + value_count: self.values.len(), + undo_len: self.undo_log.len(), + } } pub fn actions_since_snapshot(&self, snapshot: &Snapshot) -> &[UndoLog] { - &self.undo_log[snapshot.length..] + &self.undo_log[snapshot.undo_len..] } fn assert_open_snapshot(&self, snapshot: &Snapshot) { // Failures here may indicate a failure to follow a stack discipline. - assert!(self.undo_log.len() >= snapshot.length); + assert!(self.undo_log.len() >= snapshot.undo_len); assert!(self.num_open_snapshots > 0); } pub fn rollback_to(&mut self, snapshot: Snapshot) { - debug!("rollback_to({})", snapshot.length); + debug!("rollback_to({})", snapshot.undo_len); self.assert_open_snapshot(&snapshot); - while self.undo_log.len() > snapshot.length { + while self.undo_log.len() > snapshot.undo_len { match self.undo_log.pop().unwrap() { NewElem(i) => { self.values.pop(); @@ -216,7 +220,7 @@ impl SnapshotVec { /// Commits all changes since the last snapshot. Of course, they /// can still be undone if there is a snapshot further out. pub fn commit(&mut self, snapshot: Snapshot) { - debug!("commit({})", snapshot.length); + debug!("commit({})", snapshot.undo_len); self.assert_open_snapshot(&snapshot); @@ -224,7 +228,7 @@ impl SnapshotVec { // The root snapshot. It's safe to clear the undo log because // there's no snapshot further out that we might need to roll back // to. - assert!(snapshot.length == 0); + assert!(snapshot.undo_len == 0); self.undo_log.clear(); } diff --git a/src/unify/backing_vec.rs b/src/unify/backing_vec.rs index e3e91ca..ea4cca5 100644 --- a/src/unify/backing_vec.rs +++ b/src/unify/backing_vec.rs @@ -1,8 +1,7 @@ #[cfg(feature = "persistent")] use dogged::DVec; use snapshot_vec as sv; -use std::ops; -use std::ops::RangeInclusive; +use std::ops::{self, Range}; use std::marker::PhantomData; use super::{VarValue, UnifyKey, UnifyValue}; @@ -11,19 +10,15 @@ use super::{VarValue, UnifyKey, UnifyValue}; #[allow(type_alias_bounds)] type Key = ::Key; -pub trait Measurable { - fn len(&self) -> usize; -} - /// Largely internal trait implemented by the unification table /// backing store types. The most common such type is `InPlace`, /// which indicates a standard, mutable unification table. pub trait UnificationStore: - ops::Index>> + Measurable + Clone + Default + ops::Index>> + Clone + Default { type Key: UnifyKey; type Value: UnifyValue; - type Snapshot: Measurable; + type Snapshot; fn start_snapshot(&mut self) -> Self::Snapshot; @@ -31,15 +26,15 @@ pub trait UnificationStore: fn commit(&mut self, snapshot: Self::Snapshot); - fn values_since_snapshot(&mut self, snapshot: &Self::Snapshot) -> RangeInclusive { - snapshot.len()..=self.len() - } + fn values_since_snapshot(&self, snapshot: &Self::Snapshot) -> Range; fn reset_unifications( &mut self, value: impl FnMut(u32) -> VarValue, ); + fn len(&self) -> usize; + fn push(&mut self, value: VarValue); fn reserve(&mut self, num_new_values: usize); @@ -66,20 +61,6 @@ impl Default for InPlace { } } -impl Measurable for sv::Snapshot { - #[inline] - fn len(&self) -> usize { - self.length - } -} - -impl Measurable for InPlace { - #[inline] - fn len(&self) -> usize { - self.values.len() - } -} - impl UnificationStore for InPlace { type Key = K; type Value = K::Value; @@ -100,6 +81,11 @@ impl UnificationStore for InPlace { self.values.commit(snapshot); } + #[inline] + fn values_since_snapshot(&self, snapshot: &Self::Snapshot) -> Range { + snapshot.value_count..self.len() + } + #[inline] fn reset_unifications( &mut self, @@ -108,6 +94,10 @@ impl UnificationStore for InPlace { self.values.set_all(|i| value(i as u32)); } + fn len(&self) -> usize { + self.values.len() + } + #[inline] fn push(&mut self, value: VarValue) { self.values.push(value); @@ -159,14 +149,6 @@ impl Default for Persistent { } } -#[cfg(feature = "persistent")] -impl Measurable for Persistent { - #[inline] - fn len(&self) -> usize { - self.values.len() - } -} - #[cfg(feature = "persistent")] impl UnificationStore for Persistent { type Key = K; @@ -184,7 +166,11 @@ impl UnificationStore for Persistent { } #[inline] - fn commit(&mut self, _snapshot: Self::Snapshot) { + fn commit(&mut self, _snapshot: Self::Snapshot) {} + + #[inline] + fn values_since_snapshot(&self, snapshot: &Self::Snapshot) -> Range { + snapshot.len()..self.len() } #[inline] @@ -200,6 +186,10 @@ impl UnificationStore for Persistent { } } + fn len(&self) -> usize { + self.values.len() + } + #[inline] fn push(&mut self, value: VarValue) { self.values.push(value); diff --git a/src/unify/mod.rs b/src/unify/mod.rs index d8e871a..dbef13a 100644 --- a/src/unify/mod.rs +++ b/src/unify/mod.rs @@ -33,6 +33,7 @@ use std::marker; use std::fmt::Debug; +use std::ops::Range; mod backing_vec; pub use self::backing_vec::{InPlace, UnificationStore}; @@ -299,6 +300,15 @@ impl UnificationTable { self.values.len() } + /// Returns the keys of all variables created since the `snapshot`. + pub fn vars_since_snapshot( + &self, + snapshot: &Snapshot, + ) -> Range { + let range = self.values.values_since_snapshot(&snapshot.snapshot); + S::Key::from_index(range.start as u32)..S::Key::from_index(range.end as u32) + } + /// Obtains the current value for a particular key. /// Not for end-users; they can use `probe_value`. fn value(&self, key: S::Key) -> &VarValue {