blob: f1e720cd0c2b1cd08650478f3ed762d5b547d80e [file] [log] [blame]
#[cfg(feature = "persistent")]
use dogged::DVec;
use snapshot_vec as sv;
use std::ops;
use std::marker::PhantomData;
use super::{VarValue, UnifyKey, UnifyValue};
#[allow(dead_code)] // rustc BUG
#[allow(type_alias_bounds)]
type Key<S: UnificationStore> = <S as UnificationStore>::Key;
/// 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<usize, Output = VarValue<Key<Self>>> + Clone + Default
{
type Key: UnifyKey<Value = Self::Value>;
type Value: UnifyValue;
type Snapshot;
fn start_snapshot(&mut self) -> Self::Snapshot;
fn rollback_to(&mut self, snapshot: Self::Snapshot);
fn commit(&mut self, snapshot: Self::Snapshot);
fn reset_unifications(
&mut self,
value: impl FnMut(u32) -> VarValue<Self::Key>,
);
fn len(&self) -> usize;
fn push(&mut self, value: VarValue<Self::Key>);
fn reserve(&mut self, num_new_values: usize);
fn update<F>(&mut self, index: usize, op: F)
where F: FnOnce(&mut VarValue<Self::Key>);
fn tag() -> &'static str {
Self::Key::tag()
}
}
/// Backing store for an in-place unification table.
/// Not typically used directly.
#[derive(Clone, Debug)]
pub struct InPlace<K: UnifyKey> {
values: sv::SnapshotVec<Delegate<K>>
}
// HACK(eddyb) manual impl avoids `Default` bound on `K`.
impl<K: UnifyKey> Default for InPlace<K> {
fn default() -> Self {
InPlace { values: sv::SnapshotVec::new() }
}
}
impl<K: UnifyKey> UnificationStore for InPlace<K> {
type Key = K;
type Value = K::Value;
type Snapshot = sv::Snapshot;
#[inline]
fn start_snapshot(&mut self) -> Self::Snapshot {
self.values.start_snapshot()
}
#[inline]
fn rollback_to(&mut self, snapshot: Self::Snapshot) {
self.values.rollback_to(snapshot);
}
#[inline]
fn commit(&mut self, snapshot: Self::Snapshot) {
self.values.commit(snapshot);
}
#[inline]
fn reset_unifications(
&mut self,
mut value: impl FnMut(u32) -> VarValue<Self::Key>,
) {
self.values.set_all(|i| value(i as u32));
}
#[inline]
fn len(&self) -> usize {
self.values.len()
}
#[inline]
fn push(&mut self, value: VarValue<Self::Key>) {
self.values.push(value);
}
#[inline]
fn reserve(&mut self, num_new_values: usize) {
self.values.reserve(num_new_values);
}
#[inline]
fn update<F>(&mut self, index: usize, op: F)
where F: FnOnce(&mut VarValue<Self::Key>)
{
self.values.update(index, op)
}
}
impl<K> ops::Index<usize> for InPlace<K>
where K: UnifyKey
{
type Output = VarValue<K>;
fn index(&self, index: usize) -> &VarValue<K> {
&self.values[index]
}
}
#[derive(Copy, Clone, Debug)]
struct Delegate<K>(PhantomData<K>);
impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
type Value = VarValue<K>;
type Undo = ();
fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
}
#[cfg(feature = "persistent")]
#[derive(Clone, Debug)]
pub struct Persistent<K: UnifyKey> {
values: DVec<VarValue<K>>
}
// HACK(eddyb) manual impl avoids `Default` bound on `K`.
#[cfg(feature = "persistent")]
impl<K: UnifyKey> Default for Persistent<K> {
fn default() -> Self {
Persistent { values: DVec::new() }
}
}
#[cfg(feature = "persistent")]
impl<K: UnifyKey> UnificationStore for Persistent<K> {
type Key = K;
type Value = K::Value;
type Snapshot = Self;
#[inline]
fn start_snapshot(&mut self) -> Self::Snapshot {
self.clone()
}
#[inline]
fn rollback_to(&mut self, snapshot: Self::Snapshot) {
*self = snapshot;
}
#[inline]
fn commit(&mut self, _snapshot: Self::Snapshot) {
}
#[inline]
fn reset_unifications(
&mut self,
mut value: impl FnMut(u32) -> VarValue<Self::Key>,
) {
// Without extending dogged, there isn't obviously a more
// efficient way to do this. But it's pretty dumb. Maybe
// dogged needs a `map`.
for i in 0 .. self.values.len() {
self.values[i] = value(i as u32);
}
}
#[inline]
fn len(&self) -> usize {
self.values.len()
}
#[inline]
fn push(&mut self, value: VarValue<Self::Key>) {
self.values.push(value);
}
#[inline]
fn reserve(&mut self, _num_new_values: usize) {
// not obviously relevant to DVec.
}
#[inline]
fn update<F>(&mut self, index: usize, op: F)
where F: FnOnce(&mut VarValue<Self::Key>)
{
let p = &mut self.values[index];
op(p);
}
}
#[cfg(feature = "persistent")]
impl<K> ops::Index<usize> for Persistent<K>
where K: UnifyKey
{
type Output = VarValue<K>;
fn index(&self, index: usize) -> &VarValue<K> {
&self.values[index]
}
}