Skip to content

Commit 38a634b

Browse files
authored
Merge pull request #2 from nikomatsakis/persistent
introduce possibility of using persistent vectors
2 parents 5d93337 + 558771f commit 38a634b

File tree

8 files changed

+583
-205
lines changed

8 files changed

+583
-205
lines changed

.travis.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
language: rust
22
rust:
3+
- stable
34
- nightly
45
script:
5-
- cargo test
6+
- cargo test
7+
- |
8+
[ $TRAVIS_RUST_VERSION != nightly ] ||
9+
cargo test --all-features

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ authors = ["Niko Matsakis <niko@alum.mit.edu>"]
1010
[features]
1111
congruence-closure = [ "petgraph" ]
1212
bench = [ ]
13+
persistent = [ "dogged" ]
1314

1415
[dependencies]
16+
dogged = { version = "0.2.0", optional = true }
1517
log = "0.3"
1618
petgraph = { version = "0.4.5", optional = true }

src/cc/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ use petgraph::graph::{Graph, NodeIndex};
99
use std::collections::HashMap;
1010
use std::fmt::Debug;
1111
use std::hash::Hash;
12-
use unify::{NoError, UnifyKey, UnifyValue, UnificationTable, UnionedKeys};
12+
use unify::{NoError, InPlace, InPlaceUnificationTable, UnifyKey, UnifyValue, UnionedKeys};
1313

1414
#[cfg(test)]
1515
mod test;
1616

1717
pub struct CongruenceClosure<K: Key> {
1818
map: HashMap<K, Token>,
19-
table: UnificationTable<Token>,
19+
table: InPlaceUnificationTable<Token>,
2020
graph: Graph<K, ()>,
2121
}
2222

@@ -110,7 +110,7 @@ impl<K: Key> CongruenceClosure<K> {
110110
pub fn new() -> CongruenceClosure<K> {
111111
CongruenceClosure {
112112
map: HashMap::new(),
113-
table: UnificationTable::new(),
113+
table: InPlaceUnificationTable::new(),
114114
graph: Graph::new(),
115115
}
116116
}
@@ -276,7 +276,7 @@ impl<K: Key> CongruenceClosure<K> {
276276

277277
pub struct MergedKeys<'cc, K: Key + 'cc> {
278278
graph: &'cc Graph<K, ()>,
279-
iterator: UnionedKeys<'cc, Token>,
279+
iterator: UnionedKeys<'cc, InPlace<Token>>,
280280
}
281281

282282
impl<'cc, K: Key> Iterator for MergedKeys<'cc, K> {
@@ -293,7 +293,7 @@ impl<'cc, K: Key> Iterator for MergedKeys<'cc, K> {
293293

294294
struct Algorithm<'a, K: Key + 'a> {
295295
graph: &'a Graph<K, ()>,
296-
table: &'a mut UnificationTable<Token>,
296+
table: &'a mut InPlaceUnificationTable<Token>,
297297
}
298298

299299
impl<'a, K: Key> Algorithm<'a, K> {

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#[macro_use]
2121
extern crate log;
2222

23+
#[cfg(feature = "persistent")]
24+
extern crate dogged;
25+
2326
#[cfg(feature = "congruence-closure")]
2427
extern crate petgraph;
2528

src/snapshot_vec.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ impl<D: SnapshotVecDelegate> SnapshotVec<D> {
6767
}
6868
}
6969

70+
pub fn with_capacity(c: usize) -> SnapshotVec<D> {
71+
SnapshotVec {
72+
values: Vec::with_capacity(c),
73+
undo_log: Vec::new(),
74+
}
75+
}
76+
7077
fn in_snapshot(&self) -> bool {
7178
!self.undo_log.is_empty()
7279
}

src/unify/backing_vec.rs

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#[cfg(feature = "persistent")]
2+
use dogged::DVec;
3+
use snapshot_vec as sv;
4+
use std::ops;
5+
use std::marker::PhantomData;
6+
7+
use super::{VarValue, UnifyKey, UnifyValue};
8+
9+
#[allow(dead_code)] // rustc BUG
10+
type Key<S> = <S as UnificationStore>::Key;
11+
12+
/// Largely internal trait implemented by the unification table
13+
/// backing store types. The most common such type is `InPlace`,
14+
/// which indicates a standard, mutable unification table.
15+
pub trait UnificationStore: ops::Index<usize, Output = VarValue<Key<Self>>> + Clone {
16+
type Key: UnifyKey<Value = Self::Value>;
17+
type Value: UnifyValue;
18+
type Snapshot;
19+
20+
fn new() -> Self;
21+
22+
fn start_snapshot(&mut self) -> Self::Snapshot;
23+
24+
fn rollback_to(&mut self, snapshot: Self::Snapshot);
25+
26+
fn commit(&mut self, snapshot: Self::Snapshot);
27+
28+
fn len(&self) -> usize;
29+
30+
fn push(&mut self, value: VarValue<Self::Key>);
31+
32+
fn update<F>(&mut self, index: usize, op: F)
33+
where F: FnOnce(&mut VarValue<Self::Key>);
34+
35+
fn tag() -> &'static str {
36+
Self::Key::tag()
37+
}
38+
}
39+
40+
/// Backing store for an in-place unification table.
41+
/// Not typically used directly.
42+
#[derive(Clone)]
43+
pub struct InPlace<K: UnifyKey> {
44+
values: sv::SnapshotVec<Delegate<K>>
45+
}
46+
47+
impl<K: UnifyKey> UnificationStore for InPlace<K> {
48+
type Key = K;
49+
type Value = K::Value;
50+
type Snapshot = sv::Snapshot;
51+
52+
#[inline]
53+
fn new() -> Self {
54+
InPlace { values: sv::SnapshotVec::new() }
55+
}
56+
57+
#[inline]
58+
fn start_snapshot(&mut self) -> Self::Snapshot {
59+
self.values.start_snapshot()
60+
}
61+
62+
#[inline]
63+
fn rollback_to(&mut self, snapshot: Self::Snapshot) {
64+
self.values.rollback_to(snapshot);
65+
}
66+
67+
#[inline]
68+
fn commit(&mut self, snapshot: Self::Snapshot) {
69+
self.values.commit(snapshot);
70+
}
71+
72+
#[inline]
73+
fn len(&self) -> usize {
74+
self.values.len()
75+
}
76+
77+
#[inline]
78+
fn push(&mut self, value: VarValue<Self::Key>) {
79+
self.values.push(value);
80+
}
81+
82+
#[inline]
83+
fn update<F>(&mut self, index: usize, op: F)
84+
where F: FnOnce(&mut VarValue<Self::Key>)
85+
{
86+
self.values.update(index, op)
87+
}
88+
}
89+
90+
impl<K> ops::Index<usize> for InPlace<K>
91+
where K: UnifyKey
92+
{
93+
type Output = VarValue<K>;
94+
fn index(&self, index: usize) -> &VarValue<K> {
95+
&self.values[index]
96+
}
97+
}
98+
99+
#[derive(Copy, Clone)]
100+
struct Delegate<K>(PhantomData<K>);
101+
102+
impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
103+
type Value = VarValue<K>;
104+
type Undo = ();
105+
106+
fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
107+
}
108+
109+
#[cfg(feature = "persistent")]
110+
#[derive(Clone)]
111+
pub struct Persistent<K: UnifyKey> {
112+
values: DVec<VarValue<K>>
113+
}
114+
115+
#[cfg(feature = "persistent")]
116+
impl<K: UnifyKey> UnificationStore for Persistent<K> {
117+
type Key = K;
118+
type Value = K::Value;
119+
type Snapshot = Self;
120+
121+
#[inline]
122+
fn new() -> Self {
123+
Persistent { values: DVec::new() }
124+
}
125+
126+
#[inline]
127+
fn start_snapshot(&mut self) -> Self::Snapshot {
128+
self.clone()
129+
}
130+
131+
#[inline]
132+
fn rollback_to(&mut self, snapshot: Self::Snapshot) {
133+
*self = snapshot;
134+
}
135+
136+
#[inline]
137+
fn commit(&mut self, _snapshot: Self::Snapshot) {
138+
}
139+
140+
#[inline]
141+
fn len(&self) -> usize {
142+
self.values.len()
143+
}
144+
145+
#[inline]
146+
fn push(&mut self, value: VarValue<Self::Key>) {
147+
self.values.push(value);
148+
}
149+
150+
#[inline]
151+
fn update<F>(&mut self, index: usize, op: F)
152+
where F: FnOnce(&mut VarValue<Self::Key>)
153+
{
154+
let p = &mut self.values[index];
155+
op(p);
156+
}
157+
}
158+
159+
#[cfg(feature = "persistent")]
160+
impl<K> ops::Index<usize> for Persistent<K>
161+
where K: UnifyKey
162+
{
163+
type Output = VarValue<K>;
164+
fn index(&self, index: usize) -> &VarValue<K> {
165+
&self.values[index]
166+
}
167+
}

0 commit comments

Comments
 (0)