diff --git a/README.md b/README.md index 606f3dd..73349d2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,19 @@ -# UnificationTable +# disjoint-set + +## Introduction +The disjoint-set, also known as union-find, is a data structure that efficiently supports set union and find operations. It is widely used in various fields such as graph algorithms, type inference, and equivalence class management, and plays a key role in compiler implementation (e.g., for type unification and region analysis). + +## Features + +- Implements the classic union-find algorithm with path compression and union by rank. +- Supports set initialization, union, and finding the representative element (find). +- Supports dynamic elements (no need to pre-allocate the total number of elements). +- Optionally supports persistent (versioned) structures or undo operations. +- Optionally implements a "value merging" feature (e.g., for unifying types). +- Designed with a clean API for easy use in scenarios like compiler implementation, graph algorithms, and region analysis. + +## Example +### UnificationTable > **Note:** Snapshot operations should follow a stack-like (LIFO) order. > A root snapshot is required for snapshot operations. @@ -7,7 +22,7 @@ ```moonbit ///| test "UnificationTable::union_test" { - let table = new(capacity=5) + let table = UnificationTable::new(capacity=5) for i in 0..<5 { table.push(i) } @@ -23,12 +38,12 @@ test "UnificationTable::union_test" { } ``` -# Snapshot +### Snapshot ```moonbit ///| test "UnificationTable::snapshot_unite_test" { - let table = new(capacity=5) + let table = UnificationTable::new(capacity=5) let _ = table.start_snapshot() for i in 0..<5 { table.push(i) @@ -47,4 +62,7 @@ test "UnificationTable::snapshot_unite_test" { assert_false!(table.unioned(index1, index3)) assert_false!(table.unioned(index2, index1)) } -``` \ No newline at end of file +``` + +# Reference +[ena](https://github.com/rust-lang/ena) diff --git a/src/unify_table/unify_table.mbt b/disjoint_set.mbt similarity index 72% rename from src/unify_table/unify_table.mbt rename to disjoint_set.mbt index 1187aae..f621ef0 100644 --- a/src/unify_table/unify_table.mbt +++ b/disjoint_set.mbt @@ -1,12 +1,17 @@ -///| -pub struct UnificationTable[T] { - values : @snapshot_array.SnapshotArray[VarValue[T]] -} - -///| -pub struct Snapshot { - snapshot : @snapshot_array.Snapshot -} +/// Disjoint-set implementation. The main type is `UnificationTable`. +/// +/// It features an abstraction over "keys" and "values," enabling it +/// to handle not only classic set union and find operations but also +/// more complex unification needs, such as carrying information in +/// equivalence classes during type inference. +/// +/// Each equivalence set's representative element (root) can be associated +/// with a "value" to carry extra information for that set. For instance, +/// in constraint solving or typeunification, this value can store +/// known type information or constraint results, and these values are merged +/// when two keys are unified. If you only need the functionality of a "pure" +/// union-find data structure (grouping elements without extra information), +/// you can set the `Value` to `()`, indicating that no value is carried. ///| pub struct VarIndex { @@ -20,6 +25,16 @@ pub struct VarValue[T] { mut parent : VarIndex } +///| +pub struct UnificationTable[T] { + values : @snapshot_array.SnapshotArray[VarValue[T]] +} + +///| +pub struct Snapshot { + snapshot : @snapshot_array.Snapshot +} + ///| /// Creates a new variable value with the specified value, rank, and parent index. /// @@ -35,13 +50,13 @@ pub struct VarValue[T] { /// Example: /// /// ```moonbit -/// let index = new_index(0) -/// let var_value = new_var_value(42, 0, index) +/// let index = VarIndex::new(0) +/// let var_value = VarValue::new(42, 0, index) /// inspect(var_value.value, content="42") /// inspect(var_value.rank, content="0") /// inspect(var_value.parent.index, content="0") /// ``` -pub fn[T] new_var_value( +pub fn[T] VarValue::new( value : T, rank : Int, parent : VarIndex, @@ -59,14 +74,14 @@ pub fn[T] new_var_value( /// Example: /// /// ```moonbit -/// let old_parent = new_index(0) -/// let new_parent = new_index(1) -/// let var_value = new_var_value(42, 0, old_parent) +/// let old_parent = VarIndex::new(0) +/// let new_parent = VarIndex::new(1) +/// let var_value = VarValue::new(42, 0, old_parent) /// let var_value = var_value.redirect(new_parent) /// inspect(var_value.parent.index, content="1") /// ``` -pub fn[T] redirect(self : VarValue[T], to : VarIndex) -> VarValue[T] { - new_var_value(self.value, self.rank, to) +pub fn[T] VarValue::redirect(self : VarValue[T], to : VarIndex) -> VarValue[T] { + VarValue::new(self.value, self.rank, to) } ///| @@ -80,14 +95,18 @@ pub fn[T] redirect(self : VarValue[T], to : VarIndex) -> VarValue[T] { /// Example: /// /// ```moonbit -/// let index = new_index(0) -/// let var_value = new_var_value(42, 0, index) +/// let index = VarIndex::new(0) +/// let var_value = VarValue::new(42, 0, index) /// let var_value = var_value.root(1, 100) /// inspect(var_value.value, content="100") /// inspect(var_value.rank, content="1") /// ``` -pub fn[T] root(self : VarValue[T], rank : Int, value : T) -> VarValue[T] { - new_var_value(value, rank, self.parent) +pub fn[T] VarValue::root( + self : VarValue[T], + rank : Int, + value : T, +) -> VarValue[T] { + VarValue::new(value, rank, self.parent) } ///| @@ -98,8 +117,8 @@ pub fn[T] root(self : VarValue[T], rank : Int, value : T) -> VarValue[T] { /// /// Example: /// ```moonbit -/// let index = new_index(0) -/// let var_value = new_var_value(42, 0, index) +/// let index = VarIndex::new(0) +/// let var_value = VarValue::new(42, 0, index) /// var_value.modify(100) /// inspect(var_value.value, content="100") /// ``` @@ -109,7 +128,7 @@ pub fn[T] modify(self : VarValue[T], value : T) -> Unit { ///| /// Creates a new `VarIndex` with the specified index. -pub fn new_index(index : Int) -> VarIndex { +pub fn VarIndex::new(index : Int) -> VarIndex { { index, } } @@ -120,12 +139,12 @@ pub fn new_snapshot(snapshot : @snapshot_array.Snapshot) -> Snapshot { } ///| -pub impl[T : Eq] Eq for VarValue[T] with op_equal(self, other) { +pub impl[T : Eq] Eq for VarValue[T] with equal(self, other) { return self.value == other.value && self.parent == other.parent } ///| -impl Eq for VarIndex with op_equal(self, other) { +pub impl Eq for VarIndex with equal(self, other) { return self.index == other.index } @@ -140,11 +159,11 @@ impl Eq for VarIndex with op_equal(self, other) { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=10) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=10) /// inspect(table.values.length(), content="0") /// ``` -pub fn[T] new(capacity~ : Int) -> UnificationTable[T] { - { values: @snapshot_array.new(capacity~) } +pub fn[T] UnificationTable::new(capacity~ : Int) -> UnificationTable[T] { + { values: @snapshot_array.SnapshotArray::new(capacity~) } } ///| @@ -158,12 +177,16 @@ pub fn[T] new(capacity~ : Int) -> UnificationTable[T] { /// Example: /// /// ```moonbit -/// let table = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(1) /// assert_true(table.values.length() == 1) /// ``` -pub fn[T] push(self : UnificationTable[T], value : T) -> Unit { - self.values.push({ value, rank: 0, parent: new_index(self.values.length()) }) +pub fn[T] UnificationTable::push(self : UnificationTable[T], value : T) -> Unit { + self.values.push({ + value, + rank: 0, + parent: VarIndex::new(self.values.length()), + }) } ///| @@ -178,12 +201,15 @@ pub fn[T] push(self : UnificationTable[T], value : T) -> Unit { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) -/// let var_value = new_var_value(42, 0, new_index(0)) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) +/// let var_value = VarValue::new(42, 0, VarIndex::new(0)) /// table.push_var(var_value) /// inspect(table.values.length(), content="1") /// ``` -pub fn[T] push_var(self : UnificationTable[T], value : VarValue[T]) -> Unit { +pub fn[T] UnificationTable::push_var( + self : UnificationTable[T], + value : VarValue[T], +) -> Unit { self.values.push(value) } @@ -200,7 +226,7 @@ pub fn[T] push_var(self : UnificationTable[T], value : VarValue[T]) -> Unit { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) /// inspect( /// table.get(0), @@ -208,7 +234,10 @@ pub fn[T] push_var(self : UnificationTable[T], value : VarValue[T]) -> Unit { /// ) /// inspect(table.get(1), content="None") /// ``` -pub fn[T] get(self : UnificationTable[T], index : Int) -> VarValue[T]? { +pub fn[T] UnificationTable::get( + self : UnificationTable[T], + index : Int, +) -> VarValue[T]? { self.values.get(index) } @@ -227,11 +256,14 @@ pub fn[T] get(self : UnificationTable[T], index : Int) -> VarValue[T]? { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) /// inspect(table.index(0).index, content="0") /// ``` -pub fn[T] index(self : UnificationTable[T], index : Int) -> VarIndex { +pub fn[T] UnificationTable::index( + self : UnificationTable[T], + index : Int, +) -> VarIndex { if index < 0 || index >= self.values.length() { abort("Index out of bounds") } @@ -249,15 +281,18 @@ pub fn[T] index(self : UnificationTable[T], index : Int) -> VarIndex { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) -/// let index = new_index(0) +/// let index = VarIndex::new(0) /// inspect( /// table.value(index), /// content="VarValue { value: 42, rank: 0, parent: VarIndex { index: 0 } }", /// ) /// ``` -pub fn[T] value(self : UnificationTable[T], index : VarIndex) -> VarValue[T] { +pub fn[T] UnificationTable::value( + self : UnificationTable[T], + index : VarIndex, +) -> VarValue[T] { self.get(index.index).unwrap() } @@ -269,20 +304,20 @@ pub fn[T] value(self : UnificationTable[T], index : VarIndex) -> VarValue[T] { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=2) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=2) /// table.push(1) /// table.push(2) -/// let _ = table.unite(new_index(0), new_index(1), 42) +/// let _ = table.unite(VarIndex::new(0), VarIndex::new(1), 42) /// table.reset() /// inspect( -/// table.unioned(new_index(0), new_index(1)), +/// table.unioned(VarIndex::new(0), VarIndex::new(1)), /// content="false", /// ) /// ``` -pub fn[T] reset(self : UnificationTable[T]) -> Unit { +pub fn[T] UnificationTable::reset(self : UnificationTable[T]) -> Unit { for index, value in self.values.values { value.rank = 0 - value.parent = new_index(index) + value.parent = VarIndex::new(index) } self.values.commit_all() } @@ -299,16 +334,16 @@ pub fn[T] reset(self : UnificationTable[T]) -> Unit { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) -/// let new_value = new_var_value(100, 0, new_index(0)) -/// table.set(new_index(0), new_value) +/// let new_value = VarValue::new(100, 0, VarIndex::new(0)) +/// table.set(VarIndex::new(0), new_value) /// inspect( /// table.get(0), /// content="Some(VarValue { value: 100, rank: 0, parent: VarIndex { index: 0 } })", /// ) /// ``` -pub fn[T] set( +pub fn[T] UnificationTable::set( self : UnificationTable[T], index : VarIndex, value : VarValue[T], @@ -328,9 +363,9 @@ pub fn[T] set( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) -/// table.update(new_index(0), fn(val) { val.modify(100); val }) +/// table.update(VarIndex::new(0), fn(val) { val.modify(100); val }) /// inspect( /// table.get(0), /// content="Some(VarValue { value: 100, rank: 0, parent: VarIndex { index: 0 } })", @@ -359,13 +394,13 @@ pub fn[T] update( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=2) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=2) /// table.push(1) /// table.push(2) -/// table.redirect_root(1, new_index(0), new_index(1), 42) -/// inspect(table.find(new_index(0)).index, content="1") +/// table.redirect_root(1, VarIndex::new(0), VarIndex::new(1), 42) +/// inspect(table.find(VarIndex::new(0)).index, content="1") /// ``` -pub fn[T] redirect_root( +pub fn[T] UnificationTable::redirect_root( self : UnificationTable[T], new_rank : Int, old_index : VarIndex, @@ -390,16 +425,16 @@ pub fn[T] redirect_root( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=2) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=2) /// table.push(1) /// table.push(2) /// let _ = table.unite(table.index(0),table.index(1), 42) /// inspect( -/// table.unioned(new_index(0), new_index(1)), +/// table.unioned(VarIndex::new(0), VarIndex::new(1)), /// content="true", /// ) /// ``` -pub fn[T] unioned( +pub fn[T] UnificationTable::unioned( self : UnificationTable[T], index1 : VarIndex, index2 : VarIndex, @@ -423,13 +458,13 @@ pub fn[T] unioned( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=2) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=2) /// table.push(1) /// table.push(2) /// let root = table.unite(table.index(0),table.index(1), 42) /// inspect(table.value(root).value, content="42") /// ``` -pub fn[T] unite( +pub fn[T] UnificationTable::unite( self : UnificationTable[T], index1 : VarIndex, index2 : VarIndex, @@ -468,7 +503,7 @@ pub fn[T] unite( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=3) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=3) /// table.push(1) /// table.push(2) /// table.push(3) @@ -476,7 +511,10 @@ pub fn[T] unite( /// let root = table.find(table.index(0)) /// inspect(root.index, content="0") /// ``` -pub fn[T] find(self : UnificationTable[T], index : VarIndex) -> VarIndex { +pub fn[T] UnificationTable::find( + self : UnificationTable[T], + index : VarIndex, +) -> VarIndex { let value = self.value(index) if value.parent == index { return index @@ -502,7 +540,7 @@ pub fn[T] find(self : UnificationTable[T], index : VarIndex) -> VarIndex { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=2) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=2) /// table.push(1) /// table.push(2) /// let _ = table.unite(table.index(0), table.index(1), 42) @@ -510,7 +548,7 @@ pub fn[T] find(self : UnificationTable[T], index : VarIndex) -> VarIndex { /// let root = table.find_root(value) /// inspect(root.value, content="42") /// ``` -pub fn[T] find_root( +pub fn[T] UnificationTable::find_root( self : UnificationTable[T], value : VarValue[T], ) -> VarValue[T] { @@ -526,11 +564,11 @@ pub fn[T] find_root( /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// let _ = table.start_snapshot() /// assert_true(table.in_snapshot()) /// ``` -pub fn[T] in_snapshot(self : UnificationTable[T]) -> Bool { +pub fn[T] UnificationTable::in_snapshot(self : UnificationTable[T]) -> Bool { self.values.in_snapshot() } @@ -542,14 +580,16 @@ pub fn[T] in_snapshot(self : UnificationTable[T]) -> Bool { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) /// let snapshot = table.start_snapshot() /// table.push(100) /// table.rollback_to(snapshot) /// inspect(table.values.length(), content="1") /// ``` -pub fn[T] start_snapshot(self : UnificationTable[T]) -> Snapshot { +pub fn[T] UnificationTable::start_snapshot( + self : UnificationTable[T], +) -> Snapshot { let snapshot = self.values.start_snapshot() new_snapshot(snapshot) } @@ -566,14 +606,17 @@ pub fn[T] start_snapshot(self : UnificationTable[T]) -> Snapshot { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) /// let snapshot = table.start_snapshot() /// table.push(100) /// table.rollback_to(snapshot) /// inspect(table.values.length(), content="1") /// ``` -pub fn[T] rollback_to(self : UnificationTable[T], snapshot : Snapshot) -> Unit { +pub fn[T] UnificationTable::rollback_to( + self : UnificationTable[T], + snapshot : Snapshot, +) -> Unit { self.values.rollback_to(snapshot.snapshot) } @@ -588,29 +631,35 @@ pub fn[T] rollback_to(self : UnificationTable[T], snapshot : Snapshot) -> Unit { /// Example: /// /// ```moonbit -/// let table : UnificationTable[Int] = new(capacity=5) +/// let table : UnificationTable[Int] = UnificationTable::new(capacity=5) /// table.push(42) /// let snapshot = table.start_snapshot() /// table.push(100) /// table.commit(snapshot) /// inspect(table.values.length(), content="2") /// ``` -pub fn[T] commit(self : UnificationTable[T], snapshot : Snapshot) -> Unit { +pub fn[T] UnificationTable::commit( + self : UnificationTable[T], + snapshot : Snapshot, +) -> Unit { self.values.commit(snapshot.snapshot) } ///| -pub fn[T] op_get(self : UnificationTable[T], index : Int) -> VarValue[T] { +pub fn[T] UnificationTable::op_get( + self : UnificationTable[T], + index : Int, +) -> VarValue[T] { return self.get(index).unwrap() } ///| -pub fn[T] op_set( +pub fn[T] UnificationTable::op_set( self : UnificationTable[T], index : Int, value : VarValue[T], ) -> Unit { - self.set(new_index(index), value) + self.set(VarIndex::new(index), value) } ///| diff --git a/src/unify_table/unify_table_test.mbt b/disjoint_set_test.mbt similarity index 65% rename from src/unify_table/unify_table_test.mbt rename to disjoint_set_test.mbt index 6ffc362..22e430e 100644 --- a/src/unify_table/unify_table_test.mbt +++ b/disjoint_set_test.mbt @@ -1,27 +1,27 @@ ///| test "UnificationTable::push" { - let table = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(1) assert_true(table.values.length() == 1) } ///| test "UnificationTable::new" { - let table : UnificationTable[Int] = new(capacity=10) + let table : UnificationTable[Int] = UnificationTable::new(capacity=10) inspect(table.values.length(), content="0") } ///| test "UnificationTable::push_var" { - let table : UnificationTable[Int] = new(capacity=5) - let var_value = new_var_value(42, 0, new_index(0)) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) + let var_value = VarValue::new(42, 0, VarIndex::new(0)) table.push_var(var_value) inspect(table.values.length(), content="1") } ///| test "UnificationTable::get" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) inspect( table.get(0), @@ -32,23 +32,23 @@ test "UnificationTable::get" { ///| test "UnificationTable::index" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) inspect(table.index(0).index, content="0") } ///| test "panic UnificationTable::index/out_of_bounds" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) let _ = table.index(-1) } ///| test "UnificationTable::value" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) - let index = new_index(0) + let index = VarIndex::new(0) inspect( table.value(index), content="VarValue { value: 42, rank: 0, parent: VarIndex { index: 0 } }", @@ -57,7 +57,7 @@ test "UnificationTable::value" { ///| test "UnificationTable::union_test" { - let table = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) for i in 0..<5 { table.push(i) } @@ -74,20 +74,20 @@ test "UnificationTable::union_test" { ///| test "UnificationTable::reset" { - let table : UnificationTable[Int] = new(capacity=2) + let table : UnificationTable[Int] = UnificationTable::new(capacity=2) table.push(1) table.push(2) - let _ = table.unite(new_index(0), new_index(1), 42) + let _ = table.unite(VarIndex::new(0), VarIndex::new(1), 42) table.reset() - inspect(table.unioned(new_index(0), new_index(1)), content="false") + inspect(table.unioned(VarIndex::new(0), VarIndex::new(1)), content="false") } ///| test "UnificationTable::set" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) - let new_value = new_var_value(100, 0, new_index(0)) - table.set(new_index(0), new_value) + let new_value = VarValue::new(100, 0, VarIndex::new(0)) + table.set(VarIndex::new(0), new_value) inspect( table.get(0), content="Some(VarValue { value: 100, rank: 0, parent: VarIndex { index: 0 } })", @@ -96,9 +96,9 @@ test "UnificationTable::set" { ///| test "UnificationTable::update" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) - table.update(new_index(0), fn(val) { val.root(val.rank, 100) }) + table.update(VarIndex::new(0), fn(val) { val.root(val.rank, 100) }) inspect( table.get(0), content="Some(VarValue { value: 100, rank: 0, parent: VarIndex { index: 0 } })", @@ -107,25 +107,25 @@ test "UnificationTable::update" { ///| test "UnificationTable::redirect_root" { - let table : UnificationTable[Int] = new(capacity=2) + let table : UnificationTable[Int] = UnificationTable::new(capacity=2) table.push(1) table.push(2) - table.redirect_root(1, new_index(0), new_index(1), 42) - inspect(table.find(new_index(0)).index, content="1") + table.redirect_root(1, VarIndex::new(0), VarIndex::new(1), 42) + inspect(table.find(VarIndex::new(0)).index, content="1") } ///| test "UnificationTable::unioned" { - let table : UnificationTable[Int] = new(capacity=2) + let table : UnificationTable[Int] = UnificationTable::new(capacity=2) table.push(1) table.push(2) let _ = table.unite(table.index(0), table.index(1), 42) - inspect(table.unioned(new_index(0), new_index(1)), content="true") + inspect(table.unioned(VarIndex::new(0), VarIndex::new(1)), content="true") } ///| test "UnificationTable::unite" { - let table : UnificationTable[Int] = new(capacity=2) + let table : UnificationTable[Int] = UnificationTable::new(capacity=2) table.push(1) table.push(2) let root = table.unite(table.index(0), table.index(1), 42) @@ -134,7 +134,7 @@ test "UnificationTable::unite" { ///| test "UnificationTable::find" { - let table : UnificationTable[Int] = new(capacity=3) + let table : UnificationTable[Int] = UnificationTable::new(capacity=3) table.push(1) table.push(2) table.push(3) @@ -145,7 +145,7 @@ test "UnificationTable::find" { ///| test "UnificationTable::find_2" { - let table = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) for i in 0..<5 { table.push(i) } @@ -164,7 +164,7 @@ test "UnificationTable::find_2" { ///| test "UnificationTable::find_root" { - let table : UnificationTable[Int] = new(capacity=2) + let table : UnificationTable[Int] = UnificationTable::new(capacity=2) table.push(1) table.push(2) let _ = table.unite(table.index(0), table.index(1), 42) @@ -175,14 +175,14 @@ test "UnificationTable::find_root" { ///| test "UnificationTable::in_snapshot" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) let _ = table.start_snapshot() assert_true(table.in_snapshot()) } ///| test "UnificationTable::start_snapshot/rollback_to" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) let snapshot = table.start_snapshot() table.push(100) @@ -192,7 +192,7 @@ test "UnificationTable::start_snapshot/rollback_to" { ///| test "UnificationTable::commit" { - let table : UnificationTable[Int] = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) table.push(42) let snapshot = table.start_snapshot() table.push(100) @@ -201,9 +201,9 @@ test "UnificationTable::commit" { } ///| -test "VarValue::new_var_value" { - let index = new_index(0) - let var_value = new_var_value(42, 0, index) +test "VarValue::new" { + let index = VarIndex::new(0) + let var_value = VarValue::new(42, 0, index) inspect(var_value.value, content="42") inspect(var_value.rank, content="0") inspect(var_value.parent.index, content="0") @@ -211,17 +211,17 @@ test "VarValue::new_var_value" { ///| test "VarValue::redirect" { - let old_parent = new_index(0) - let new_parent = new_index(1) - let var_value = new_var_value(42, 0, old_parent) + let old_parent = VarIndex::new(0) + let new_parent = VarIndex::new(1) + let var_value = VarValue::new(42, 0, old_parent) let var_value = var_value.redirect(new_parent) inspect(var_value.parent.index, content="1") } ///| test "VarValue::root" { - let index = new_index(0) - let var_value = new_var_value(42, 0, index) + let index = VarIndex::new(0) + let var_value = VarValue::new(42, 0, index) let var_value = var_value.root(1, 100) inspect(var_value.value, content="100") inspect(var_value.rank, content="1") @@ -229,15 +229,15 @@ test "VarValue::root" { ///| test "VarValue::modify" { - let index = new_index(0) - let var_value = new_var_value(42, 0, index) + let index = VarIndex::new(0) + let var_value = VarValue::new(42, 0, index) var_value.modify(100) inspect(var_value.value, content="100") } ///| test "UnificationTable::snapshot_unite_test" { - let table = new(capacity=5) + let table : UnificationTable[Int] = UnificationTable::new(capacity=5) let _ = table.start_snapshot() for i in 0..<5 { table.push(i) diff --git a/internal/snapshot_array/moon.pkg.json b/internal/snapshot_array/moon.pkg.json new file mode 100644 index 0000000..ca3f3dc --- /dev/null +++ b/internal/snapshot_array/moon.pkg.json @@ -0,0 +1,3 @@ +{ + "import": ["chaijie/disjoint-set/internal/undo_logs"] +} \ No newline at end of file diff --git a/src/snapshot_array/snapshot_array.mbti b/internal/snapshot_array/pkg.generated.mbti similarity index 76% rename from src/snapshot_array/snapshot_array.mbti rename to internal/snapshot_array/pkg.generated.mbti index e77332c..b19b1ed 100644 --- a/src/snapshot_array/snapshot_array.mbti +++ b/internal/snapshot_array/pkg.generated.mbti @@ -1,22 +1,17 @@ // Generated using `moon info`, DON'T EDIT IT -package "BigOrangeQWQ/unification_table/snapshot_array" +package "chaijie/disjoint-set/internal/snapshot_array" import( - "BigOrangeQWQ/unification_table/undo_logs" + "chaijie/disjoint-set/internal/undo_logs" ) // Values -fn[T] from_iter(Iter[T], capacity? : Int) -> SnapshotArray[T] - -fn[T] new(capacity? : Int) -> SnapshotArray[T] - -fn[T] of(FixedArray[T]) -> SnapshotArray[T] // Errors // Types and methods pub struct Snapshot { - undo_count : Int + undo_len : Int } pub struct SnapshotArray[T] { @@ -27,14 +22,18 @@ fn[T] SnapshotArray::action_since_snapshot(Self[T], Snapshot) -> ArrayView[@undo fn[T] SnapshotArray::commit(Self[T], Snapshot) -> Unit fn[T] SnapshotArray::commit_all(Self[T]) -> Unit fn[T] SnapshotArray::extend(Self[T], Iter[T]) -> Unit +fn[T] SnapshotArray::from_iter(Iter[T], capacity? : Int) -> Self[T] fn[T] SnapshotArray::get(Self[T], Int) -> T? fn[T] SnapshotArray::in_snapshot(Self[T]) -> Bool fn[T] SnapshotArray::length(Self[T]) -> Int +fn[T] SnapshotArray::new(capacity? : Int) -> Self[T] +fn[T] SnapshotArray::of(FixedArray[T]) -> Self[T] fn[T] SnapshotArray::op_get(Self[T], Int) -> T fn[T] SnapshotArray::op_set(Self[T], Int, T) -> Unit fn[T] SnapshotArray::push(Self[T], T) -> Unit fn[T] SnapshotArray::record(Self[T], @undo_logs.Undo[T]) -> Bool fn[T] SnapshotArray::reset(Self[T]) -> Unit +fn[T] SnapshotArray::rollback(Self[T]) -> Unit fn[T] SnapshotArray::rollback_to(Self[T], Snapshot) -> Unit fn[T] SnapshotArray::set(Self[T], Int, T) -> Unit fn[T] SnapshotArray::set_all(Self[T], (T) -> T) -> Unit diff --git a/src/snapshot_array/snapshot_array.mbt b/internal/snapshot_array/snapshot_array.mbt similarity index 77% rename from src/snapshot_array/snapshot_array.mbt rename to internal/snapshot_array/snapshot_array.mbt index 02bcd89..dc589aa 100644 --- a/src/snapshot_array/snapshot_array.mbt +++ b/internal/snapshot_array/snapshot_array.mbt @@ -1,12 +1,12 @@ ///| pub struct SnapshotArray[T] { - logs : @logs.UndoLogs[T] + logs : @undo_logs.UndoLogs[T] values : Array[T] } ///| pub struct Snapshot { - undo_count : Int + undo_len : Int } ///| @@ -14,23 +14,26 @@ pub struct Snapshot { /// /// Example: /// ```moonbit -/// let arr : SnapshotArray[Int] = new(capacity=5) +/// let arr : SnapshotArray[Int] = SnapshotArray::new(capacity=5) /// assert_true(arr.length() == 0) /// ``` -pub fn[T] new(capacity? : Int = 0) -> SnapshotArray[T] { - { logs: @logs.new(), values: Array::new(capacity~) } +pub fn[T] SnapshotArray::new(capacity? : Int = 0) -> SnapshotArray[T] { + { logs: @undo_logs.UndoLogs::new(), values: Array::new(capacity~) } } ///| -pub fn[T] from_iter(iter : Iter[T], capacity? : Int = 0) -> SnapshotArray[T] { - let arr = new(capacity~) +pub fn[T] SnapshotArray::from_iter( + iter : Iter[T], + capacity? : Int = 0, +) -> SnapshotArray[T] { + let arr = SnapshotArray::new(capacity~) arr.extend(iter) arr } ///| -pub fn[T] of(values : FixedArray[T]) -> SnapshotArray[T] { - let arr = new(capacity=values.length()) +pub fn[T] SnapshotArray::of(values : FixedArray[T]) -> SnapshotArray[T] { + let arr = SnapshotArray::new(capacity=values.length()) arr.extend(values.iter()) arr } @@ -40,12 +43,12 @@ pub fn[T] of(values : FixedArray[T]) -> SnapshotArray[T] { /// /// Example: /// ```moonbit -/// let arr = new(capacity=5) +/// let arr = SnapshotArray::new(capacity=5) /// assert_eq(arr.length(), 0) /// arr.push(1) /// assert_eq(arr.length(), 1) /// ``` -pub fn[T] length(self : SnapshotArray[T]) -> Int { +pub fn[T] SnapshotArray::length(self : SnapshotArray[T]) -> Int { self.values.length() } @@ -54,13 +57,13 @@ pub fn[T] length(self : SnapshotArray[T]) -> Int { /// /// Example: /// ```moonbit -/// let arr = new(capacity=5) +/// let arr = SnapshotArray::new(capacity=5) /// arr.push(1) /// arr.push(2) /// assert_eq(arr.get(0).unwrap(), 1) /// assert_eq(arr.get(1).unwrap(), 2) /// ``` -pub fn[T] get(self : SnapshotArray[T], index : Int) -> T? { +pub fn[T] SnapshotArray::get(self : SnapshotArray[T], index : Int) -> T? { self.values.get(index) } @@ -69,14 +72,14 @@ pub fn[T] get(self : SnapshotArray[T], index : Int) -> T? { /// /// Example: /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// let snapshot = arr.start_snapshot() /// arr.push(1) /// arr.push(2) /// arr.rollback_to(snapshot) /// inspect(arr.length(), content="0") /// ``` -fn[T] rollback(self : SnapshotArray[T]) -> Unit { +pub fn[T] SnapshotArray::rollback(self : SnapshotArray[T]) -> Unit { let undo = self.logs.pop().unwrap() match undo { NewElem(idx) => { @@ -96,7 +99,7 @@ fn[T] rollback(self : SnapshotArray[T]) -> Unit { /// Example: /// /// ```moonbit -/// let arr : SnapshotArray[Int] = new() +/// let arr : SnapshotArray[Int] = SnapshotArray::new() /// inspect(arr.in_snapshot(), content="false") /// let _ = arr.start_snapshot() /// inspect(arr.in_snapshot(), content="true") @@ -112,7 +115,7 @@ pub fn[T] in_snapshot(self : SnapshotArray[T]) -> Bool { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// let snapshot = arr.start_snapshot() /// arr.push(1) /// inspect(arr.length(), content="1") @@ -120,11 +123,11 @@ pub fn[T] in_snapshot(self : SnapshotArray[T]) -> Bool { /// arr.rollback_to(snapshot) /// inspect(arr.length(), content="0") /// ``` -pub fn[T] push(self : SnapshotArray[T], elem : T) -> Unit { +pub fn[T] SnapshotArray::push(self : SnapshotArray[T], elem : T) -> Unit { let len = self.values.length() self.values.push(elem) if self.in_snapshot() { - self.logs.push(@logs.newElem(len)) + self.logs.push(@undo_logs.Undo::NewElem(len)) } } @@ -136,14 +139,14 @@ pub fn[T] push(self : SnapshotArray[T], elem : T) -> Unit { /// Example: /// /// ```moonbit -/// let arr : SnapshotArray[Int] = new() +/// let arr : SnapshotArray[Int] = SnapshotArray::new() /// arr.push(1) /// arr.push(2) /// inspect(arr.length(), content="2") /// arr.reset() /// inspect(arr.length(), content="0") /// ``` -pub fn[T] reset(self : SnapshotArray[T]) -> Unit { +pub fn[T] SnapshotArray::reset(self : SnapshotArray[T]) -> Unit { self.values.clear() self.logs.clear() } @@ -154,7 +157,7 @@ pub fn[T] reset(self : SnapshotArray[T]) -> Unit { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// arr.extend([1, 2, 3].iter()) /// inspect(arr.length(), content="3") /// inspect(arr.get(0).unwrap(), content="1") @@ -172,7 +175,7 @@ pub fn[T] extend(self : SnapshotArray[T], iter : Iter[T]) -> Unit { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// arr.push(1) /// let snapshot = arr.start_snapshot() /// arr.set(0, 42) @@ -187,7 +190,7 @@ pub fn[T] set(self : SnapshotArray[T], index : Int, value : T) -> Unit { let old_value = self.values[index] self.values[index] = value if self.in_snapshot() { - self.logs.push(@logs.setElem(index, old_value)) + self.logs.push(@undo_logs.Undo::SetElem(index, old_value)) } } @@ -198,7 +201,7 @@ pub fn[T] set(self : SnapshotArray[T], index : Int, value : T) -> Unit { /// /// Example: /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// arr.extend([1, 2, 3].iter()) /// let snapshot = arr.start_snapshot() /// arr.set_all(fn(x) { x * 2 }) @@ -206,11 +209,14 @@ pub fn[T] set(self : SnapshotArray[T], index : Int, value : T) -> Unit { /// arr.rollback_to(snapshot) /// inspect(arr.get(0).unwrap(), content="1") /// ``` -pub fn[T] set_all(self : SnapshotArray[T], func : (T) -> T) -> Unit { +pub fn[T] SnapshotArray::set_all( + self : SnapshotArray[T], + func : (T) -> T, +) -> Unit { if self.in_snapshot() { for i in 0.. T) -> Unit { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// arr.push(1) /// let snapshot = arr.start_snapshot() /// arr.push(2) @@ -237,7 +243,7 @@ pub fn[T] set_all(self : SnapshotArray[T], func : (T) -> T) -> Unit { /// inspect(arr.length(), content="1") /// ``` pub fn[T] start_snapshot(self : SnapshotArray[T]) -> Snapshot { - { undo_count: self.logs.start_snapshot() } + { undo_len: self.logs.start_snapshot() } } ///| @@ -247,17 +253,17 @@ pub fn[T] start_snapshot(self : SnapshotArray[T]) -> Snapshot { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// let snapshot = arr.start_snapshot() /// arr.push(1) /// arr.push(2) /// inspect(arr.action_since_snapshot(snapshot).length(), content="2") /// ``` -pub fn[T] action_since_snapshot( +pub fn[T] SnapshotArray::action_since_snapshot( self : SnapshotArray[T], snapshot : Snapshot, -) -> ArrayView[@logs.Undo[T]] { - self.logs.action_since_snapshot(snapshot.undo_count) +) -> ArrayView[@undo_logs.Undo[T]] { + self.logs.action_since_snapshot(snapshot.undo_len) } ///| @@ -269,7 +275,7 @@ pub fn[T] action_since_snapshot( /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// arr.push(1) /// let snapshot = arr.start_snapshot() /// arr.push(2) @@ -278,7 +284,10 @@ pub fn[T] action_since_snapshot( /// inspect(arr.length(), content="1") /// inspect(arr.get(0).unwrap(), content="1") /// ``` -pub fn[T] rollback_to(self : SnapshotArray[T], snapshot : Snapshot) -> Unit { +pub fn[T] SnapshotArray::rollback_to( + self : SnapshotArray[T], + snapshot : Snapshot, +) -> Unit { let actions = self.action_since_snapshot(snapshot) let count = actions.length() for _ in 0.. Unit { /// Example: /// /// ```moonbit -/// let arr : SnapshotArray[Int] = new() +/// let arr : SnapshotArray[Int] = SnapshotArray::new() /// let snapshot = arr.start_snapshot() -/// let _ = arr.record(@logs.newElem(0)) +/// let _ = arr.record(@undo_logs.Undo::NewElem(0)) /// inspect(arr.action_since_snapshot(snapshot).length(), content="1") /// ``` -pub fn[T] record(self : SnapshotArray[T], undo : @logs.Undo[T]) -> Bool { +pub fn[T] SnapshotArray::record( + self : SnapshotArray[T], + undo : @undo_logs.Undo[T], +) -> Bool { if self.in_snapshot() { self.logs.push(undo) return true @@ -329,7 +341,7 @@ pub fn[T] record(self : SnapshotArray[T], undo : @logs.Undo[T]) -> Bool { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// let snapshot1 = arr.start_snapshot() /// arr.push(1) /// let snapshot2 = arr.start_snapshot() @@ -340,8 +352,11 @@ pub fn[T] record(self : SnapshotArray[T], undo : @logs.Undo[T]) -> Bool { /// arr.rollback_to(snapshot1) /// inspect(arr.length(), content="0") /// ``` -pub fn[T] commit(self : SnapshotArray[T], snapshot : Snapshot) -> Unit { - self.logs.commit(snapshot.undo_count) +pub fn[T] SnapshotArray::commit( + self : SnapshotArray[T], + snapshot : Snapshot, +) -> Unit { + self.logs.commit(snapshot.undo_len) } ///| @@ -356,7 +371,7 @@ pub fn[T] commit(self : SnapshotArray[T], snapshot : Snapshot) -> Unit { /// Example: /// /// ```moonbit -/// let arr = new() +/// let arr = SnapshotArray::new() /// let _snapshot = arr.start_snapshot() /// arr.push(1) /// arr.push(2) @@ -365,7 +380,7 @@ pub fn[T] commit(self : SnapshotArray[T], snapshot : Snapshot) -> Unit { /// inspect(arr.in_snapshot(), content="false") /// inspect(arr.length(), content="2") /// ``` -pub fn[T] commit_all(self : SnapshotArray[T]) -> Unit { +pub fn[T] SnapshotArray::commit_all(self : SnapshotArray[T]) -> Unit { self.logs.clear() } diff --git a/src/snapshot_array/snapshot_array_test.mbt b/internal/snapshot_array/snapshot_array_test.mbt similarity index 85% rename from src/snapshot_array/snapshot_array_test.mbt rename to internal/snapshot_array/snapshot_array_test.mbt index d424cae..49ec1ae 100644 --- a/src/snapshot_array/snapshot_array_test.mbt +++ b/internal/snapshot_array/snapshot_array_test.mbt @@ -1,6 +1,6 @@ ///| test "SnapshotArray::new" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) assert_true(arr.length() == 0) let _ = arr.start_snapshot() arr.push(1) @@ -10,7 +10,7 @@ test "SnapshotArray::new" { ///| test "SnapshotArray::length" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) assert_eq(arr.length(), 0) arr.push(1) assert_eq(arr.length(), 1) @@ -18,7 +18,7 @@ test "SnapshotArray::length" { ///| test "SnapshotArray::get" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) arr.push(1) arr.push(2) assert_eq(arr.get(0).unwrap(), 1) @@ -27,7 +27,7 @@ test "SnapshotArray::get" { ///| test "SnapshotArray::get" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) let s1 = arr.start_snapshot() arr.push(1) arr.push(2) @@ -40,7 +40,7 @@ test "SnapshotArray::get" { ///| test "SnapshotArray::in_snapshot" { - let arr : SnapshotArray[Int] = new() + let arr : SnapshotArray[Int] = SnapshotArray::new() inspect(arr.in_snapshot(), content="false") let _ = arr.start_snapshot() inspect(arr.in_snapshot(), content="true") @@ -48,7 +48,7 @@ test "SnapshotArray::in_snapshot" { ///| test "SnapshotArray::rollback" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) let _ = arr.start_snapshot() arr.push(1) let s2 = arr.start_snapshot() @@ -60,7 +60,7 @@ test "SnapshotArray::rollback" { ///| test "SnapshotArray::push" { - let arr = new() + let arr = SnapshotArray::new() let snapshot = arr.start_snapshot() arr.push(1) inspect(arr.length(), content="1") @@ -71,7 +71,7 @@ test "SnapshotArray::push" { ///| test "SnapshotArray::extend" { - let arr = new() + let arr = SnapshotArray::new() arr.extend([1, 2, 3].iter()) inspect(arr.length(), content="3") inspect(arr.get(0).unwrap(), content="1") @@ -79,7 +79,7 @@ test "SnapshotArray::extend" { ///| test "SnapshotArray::set" { - let arr = new() + let arr = SnapshotArray::new() arr.push(1) let snapshot = arr.start_snapshot() arr.set(0, 42) @@ -90,7 +90,7 @@ test "SnapshotArray::set" { ///| test "SnapshotArray::set_and_get" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) arr.push(1) arr.push(2) arr.set(0, 3) @@ -105,7 +105,7 @@ test "SnapshotArray::set_and_get" { ///| test "SnapshotArray::set_all" { - let arr = new() + let arr = SnapshotArray::new() arr.extend([1, 2, 3].iter()) let snapshot = arr.start_snapshot() arr.set_all(fn(x) { x * 2 }) @@ -116,7 +116,7 @@ test "SnapshotArray::set_all" { ///| test "SnapshotArray::set_all_with_snapshot" { - let arr = new(capacity=5) + let arr = SnapshotArray::new(capacity=5) let _ = arr.start_snapshot() let s1 = arr.start_snapshot() arr.push(1) @@ -136,7 +136,7 @@ test "SnapshotArray::set_all_with_snapshot" { ///| test "SnapshotArray::start_snapshot" { - let arr = new() + let arr = SnapshotArray::new() arr.push(1) let snapshot = arr.start_snapshot() arr.push(2) @@ -146,7 +146,7 @@ test "SnapshotArray::start_snapshot" { ///| test "SnapshotArray::action_since_snapshot" { - let arr = new() + let arr = SnapshotArray::new() let snapshot = arr.start_snapshot() arr.push(1) arr.push(2) @@ -155,7 +155,7 @@ test "SnapshotArray::action_since_snapshot" { ///| test "SnapshotArray::rollback_to" { - let arr = new() + let arr = SnapshotArray::new() arr.push(1) let snapshot = arr.start_snapshot() arr.push(2) diff --git a/internal/undo_logs/moon.pkg.json b/internal/undo_logs/moon.pkg.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/internal/undo_logs/moon.pkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/undo_logs/undo_logs.mbti b/internal/undo_logs/pkg.generated.mbti similarity index 82% rename from src/undo_logs/undo_logs.mbti rename to internal/undo_logs/pkg.generated.mbti index d358c56..29336ba 100644 --- a/src/undo_logs/undo_logs.mbti +++ b/internal/undo_logs/pkg.generated.mbti @@ -1,19 +1,13 @@ // Generated using `moon info`, DON'T EDIT IT -package "BigOrangeQWQ/unification_table/undo_logs" +package "chaijie/disjoint-set/internal/undo_logs" // Values fn[T] from_iter(Iter[Undo[T]], capacity? : Int) -> UndoLogs[T] -fn[T] new(capacity? : Int) -> UndoLogs[T] - -fn[T] newElem(Int) -> Undo[T] - -fn[T] setElem(Int, T) -> Undo[T] - // Errors // Types and methods -pub enum Undo[T] { +pub(all) enum Undo[T] { NewElem(Int) SetElem(Int, T) } @@ -33,12 +27,12 @@ fn[T] UndoLogs::in_snapshot(Self[T]) -> Bool fn[T] UndoLogs::iter(Self[T]) -> Iter[Undo[T]] fn[T] UndoLogs::last(Self[T]) -> Undo[T]? fn[T] UndoLogs::length(Self[T]) -> Int +fn[T] UndoLogs::new(capacity? : Int) -> Self[T] fn[T] UndoLogs::num_open_snapshots(Self[T]) -> Int fn[T] UndoLogs::pop(Self[T]) -> Undo[T]? fn[T] UndoLogs::push(Self[T], Undo[T]) -> Unit fn[T] UndoLogs::rollback_to(Self[T], Int) -> Array[Undo[T]] fn[T] UndoLogs::start_snapshot(Self[T]) -> Int -impl[T : Show] Show for UndoLogs[T] // Type aliases diff --git a/src/undo_logs/undo_logs.mbt b/internal/undo_logs/undo_logs.mbt similarity index 72% rename from src/undo_logs/undo_logs.mbt rename to internal/undo_logs/undo_logs.mbt index 2f953e8..ebe3bcb 100644 --- a/src/undo_logs/undo_logs.mbt +++ b/internal/undo_logs/undo_logs.mbt @@ -1,6 +1,6 @@ ///| /// Undo logs for tracking changes in a data structure. -pub enum Undo[T] { +pub(all) enum Undo[T] { NewElem(Int) SetElem(Int, T) } @@ -8,16 +8,6 @@ pub enum Undo[T] { ///| typealias Int as Snapshot -///| -pub fn[T] newElem(index : Int) -> Undo[T] { - NewElem(index) -} - -///| -pub fn[T] setElem(index : Int, value : T) -> Undo[T] { - SetElem(index, value) -} - ///| /// UndoLogs is a structure that keeps track of changes made to a data structure. pub struct UndoLogs[T] { @@ -26,27 +16,26 @@ pub struct UndoLogs[T] { } ///| -pub fn[T] new(capacity? : Int = 0) -> UndoLogs[T] { +pub fn[T] UndoLogs::new(capacity? : Int = 0) -> UndoLogs[T] { { logs: Array::new(capacity~), num_open_snapshots: 0 } } ///| pub fn[T] from_iter(iter : Iter[Undo[T]], capacity? : Int = 0) -> UndoLogs[T] { - let logs = new(capacity~) + let logs = UndoLogs::new(capacity~) logs.extend(iter) logs } ///| -/// Checks UndoLogs for an open snapshot. -/// Returns true if there is at least one open snapshot. +/// True if a snapshot has started, false otherwise /// /// Example: /// /// ```moonbit -/// let logs = new() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// let logs = UndoLogs::new() +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// assert_false(logs.in_snapshot()) /// let _ = logs.start_snapshot() /// assert_true(logs.in_snapshot()) @@ -61,9 +50,9 @@ pub fn[T] in_snapshot(self : UndoLogs[T]) -> Bool { /// Example: /// /// ```moonbit -/// let logs = new() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// let logs = UndoLogs::new() +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// assert_eq(logs.length(), 2) /// ``` pub fn[T] length(self : UndoLogs[T]) -> Int { @@ -71,17 +60,17 @@ pub fn[T] length(self : UndoLogs[T]) -> Int { } ///| -/// Returns the number of open snapshots. +/// How many open snapshots this undo log currently has /// /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let _ = logs.start_snapshot() /// assert_true(logs.num_open_snapshots() == 1) -/// logs.push(newElem(0)) +/// logs.push(NewElem(0)) /// let s1 = logs.start_snapshot() -/// logs.push(setElem(1, "test")) +/// logs.push(Undo::SetElem(1, "test")) /// logs.commit(s1) /// ``` pub fn[T] num_open_snapshots(self : UndoLogs[T]) -> Int { @@ -89,14 +78,14 @@ pub fn[T] num_open_snapshots(self : UndoLogs[T]) -> Int { } ///| -/// Pushes a new undo log entry onto the logs. +/// Pushes a new "undo item" onto the logs. /// /// Example: /// /// ```moonbit -/// let logs = new() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// let logs = UndoLogs::new() +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// assert_eq(logs.length(), 2) /// ``` pub fn[T] push(self : UndoLogs[T], log : Undo[T]) -> Unit { @@ -109,11 +98,11 @@ pub fn[T] push(self : UndoLogs[T], log : Undo[T]) -> Unit { /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let _ = logs.start_snapshot() -/// logs.push(newElem(0)) +/// logs.push(NewElem(0)) /// let _ = logs.start_snapshot() -/// logs.push(setElem(1, "test")) +/// logs.push(Undo::SetElem(1, "test")) /// logs.clear() /// assert_true(logs.logs.length() == 0) /// assert_true(logs.num_open_snapshots == 0) @@ -129,8 +118,8 @@ pub fn[T] clear(self : UndoLogs[T]) -> Unit { /// Example: /// /// ```moonbit -/// let logs = new() -/// let new_logs = [newElem(0), setElem(1, "test")] +/// let logs = UndoLogs::new() +/// let new_logs = [Undo::NewElem(0), Undo::SetElem(1, "test")] /// logs.extend(new_logs.iter()) /// assert_true(logs.logs.length() == 2) /// inspect(logs.logs[0], content="NewElem(0)") @@ -148,10 +137,10 @@ pub fn[T] extend(self : UndoLogs[T], logs : Iter[Undo[T]]) -> Unit { /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let s1 = logs.start_snapshot() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// let actions = logs.action_since_snapshot(s1) /// assert_eq(actions.length(), 2) /// inspect(actions[0], content="NewElem(0)") @@ -170,10 +159,10 @@ pub fn[T] action_since_snapshot( /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let s1 = logs.start_snapshot() /// assert_false(logs.has_changes(s1)) -/// logs.push(setElem(2, "another_test")) +/// logs.push(Undo::SetElem(2, "another_test")) /// assert_true(logs.has_changes(s1)) /// ``` pub fn[T] has_changes(self : UndoLogs[T], snapshot : Snapshot) -> Bool { @@ -181,15 +170,18 @@ pub fn[T] has_changes(self : UndoLogs[T], snapshot : Snapshot) -> Bool { } ///| -/// Starts a new snapshot and returns its identifier. +/// Starts a new snapshot. That snapshot must eventually either be committed via a call to +/// commit or rollback via rollback_to. Snapshots can be nested (i.e., you can start a snapshot +/// whilst another snapshot is in progress) but you must then commit or rollback the inner +/// snapshot before attempting to commit or rollback the outer snapshot. /// /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let s1 = logs.start_snapshot() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// inspect(logs.action_since_snapshot(s1), content="[NewElem(0), SetElem(1, test)]") /// ``` pub fn[T] start_snapshot(self : UndoLogs[T]) -> Snapshot { @@ -211,10 +203,10 @@ fn[T] assert_valid_snapshot(self : UndoLogs[T], snapshot : Snapshot) -> Unit { /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let s1 = logs.start_snapshot() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// logs.commit(s1) /// assert_eq(logs.length(), 0) /// ``` @@ -236,13 +228,13 @@ pub fn[T] commit(self : UndoLogs[T], snapshot : Snapshot) -> Unit { /// Example: /// /// ```moonbit -/// let logs = new() +/// let logs = UndoLogs::new() /// let _ = logs.start_snapshot() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// let s3 = logs.start_snapshot() -/// logs.push(setElem(3, "another_rollback_test")) -/// logs.push(newElem(4)) +/// logs.push(Undo::SetElem(3, "another_rollback_test")) +/// logs.push(NewElem(4)) /// inspect( /// logs.rollback_to(s3), /// content="[SetElem(3, another_rollback_test), NewElem(4)]", @@ -254,10 +246,7 @@ pub fn[T] rollback_to( ) -> Array[Undo[T]] { self.assert_valid_snapshot(snapshot) let logs = self.action_since_snapshot(snapshot).to_array() - for _ in 0.. self.pop() |> ignore) logs } @@ -267,11 +256,11 @@ pub fn[T] rollback_to( /// Example: /// /// ```moonbit -/// let logs = new() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// let logs = UndoLogs::new() +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// let popped = logs.pop().unwrap() -/// assert_eq(popped, setElem(1, "test")) +/// assert_eq(popped, Undo::SetElem(1, "test")) /// assert_eq(logs.length(), 1) /// ``` pub fn[T] pop(self : UndoLogs[T]) -> Undo[T]? { @@ -284,11 +273,11 @@ pub fn[T] pop(self : UndoLogs[T]) -> Undo[T]? { /// Example: /// /// ```moonbit -/// let logs = new() -/// logs.push(newElem(0)) -/// logs.push(setElem(1, "test")) +/// let logs = UndoLogs::new() +/// logs.push(NewElem(0)) +/// logs.push(Undo::SetElem(1, "test")) /// let last = logs.last().unwrap() -/// assert_eq(last, setElem(1, "test")) +/// assert_eq(last, Undo::SetElem(1, "test")) /// ``` pub fn[T] last(self : UndoLogs[T]) -> Undo[T]? { self.logs.last() @@ -300,7 +289,7 @@ pub fn[T] iter(self : UndoLogs[T]) -> Iter[Undo[T]] { } ///| -pub impl[T : Eq] Eq for Undo[T] with op_equal(self, other : Undo[T]) -> Bool { +pub impl[T : Eq] Eq for Undo[T] with equal(self, other : Undo[T]) -> Bool { match (self, other) { (NewElem(index1), NewElem(index2)) => index1 == index2 (SetElem(index1, value1), SetElem(index2, value2)) => diff --git a/src/undo_logs/undo_logs_test.mbt b/internal/undo_logs/undo_logs_test.mbt similarity index 56% rename from src/undo_logs/undo_logs_test.mbt rename to internal/undo_logs/undo_logs_test.mbt index b9a50e0..6b2214d 100644 --- a/src/undo_logs/undo_logs_test.mbt +++ b/internal/undo_logs/undo_logs_test.mbt @@ -1,15 +1,15 @@ ///| test "UndoLogs::new" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) } ///| test "UndoLogs::in_snapshot" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) assert_false(logs.in_snapshot()) let _ = logs.start_snapshot() assert_true(logs.in_snapshot()) @@ -17,38 +17,38 @@ test "UndoLogs::in_snapshot" { ///| test "UndoLogs::length" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) assert_eq(logs.length(), 2) } ///| test "UndoLogs::num_open_snapshots" { - let logs = new() + let logs = UndoLogs::new() let _ = logs.start_snapshot() assert_true(logs.num_open_snapshots() == 1) - logs.push(newElem(0)) + logs.push(Undo::NewElem(0)) let s1 = logs.start_snapshot() - logs.push(setElem(1, "test")) + logs.push(Undo::SetElem(1, "test")) logs.commit(s1) } ///| test "UndoLogs::push" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) assert_eq(logs.length(), 2) } ///| test "UndoLogs::clear" { - let logs = new() + let logs = UndoLogs::new() let _ = logs.start_snapshot() - logs.push(newElem(0)) + logs.push(Undo::NewElem(0)) let _ = logs.start_snapshot() - logs.push(setElem(1, "test")) + logs.push(Undo::SetElem(1, "test")) logs.clear() assert_true(logs.logs.length() == 0) assert_true(logs.num_open_snapshots == 0) @@ -56,8 +56,8 @@ test "UndoLogs::clear" { ///| test "UndoLogs::extend" { - let logs = new() - let new_logs = [newElem(0), setElem(1, "test")] + let logs = UndoLogs::new() + let new_logs = [Undo::NewElem(0), Undo::SetElem(1, "test")] logs.extend(new_logs.iter()) assert_true(logs.logs.length() == 2) inspect(logs.logs[0], content="NewElem(0)") @@ -66,22 +66,22 @@ test "UndoLogs::extend" { ///| test "UndoLogs::num_open_snapshots" { - let logs = new() + let logs = UndoLogs::new() let s1 = logs.start_snapshot() assert_true(logs.num_open_snapshots() == 1) - logs.push(newElem(0)) + logs.push(Undo::NewElem(0)) let s2 = logs.start_snapshot() - logs.push(setElem(1, "test")) + logs.push(Undo::SetElem(1, "test")) logs.commit(s2) logs.commit(s1) } ///| test "UndoLogs::action_since_snapshot" { - let logs = new() + let logs = UndoLogs::new() let s1 = logs.start_snapshot() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) let actions = logs.action_since_snapshot(s1) assert_eq(actions.length(), 2) inspect(actions[0], content="NewElem(0)") @@ -90,19 +90,19 @@ test "UndoLogs::action_since_snapshot" { ///| test "UndoLogs::has_changes" { - let logs = new() + let logs = UndoLogs::new() let s1 = logs.start_snapshot() assert_false(logs.has_changes(s1)) - logs.push(setElem(2, "another_test")) + logs.push(Undo::SetElem(2, "another_test")) assert_true(logs.has_changes(s1)) } ///| test "UndoLogs::start_snapshot" { - let logs = new() + let logs = UndoLogs::new() let s1 = logs.start_snapshot() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) inspect( logs.action_since_snapshot(s1), content="[NewElem(0), SetElem(1, test)]", @@ -111,15 +111,15 @@ test "UndoLogs::start_snapshot" { ///| test "UndoLogs::rollback_to" { - let logs = new() + let logs = UndoLogs::new() let _ = logs.start_snapshot() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) let _ = logs.start_snapshot() - logs.push(setElem(2, "rollback_test")) + logs.push(Undo::SetElem(2, "rollback_test")) let s3 = logs.start_snapshot() - logs.push(setElem(3, "another_rollback_test")) - logs.push(newElem(4)) + logs.push(Undo::SetElem(3, "another_rollback_test")) + logs.push(Undo::NewElem(4)) inspect( logs.rollback_to(s3), content="[SetElem(3, another_rollback_test), NewElem(4)]", @@ -128,29 +128,29 @@ test "UndoLogs::rollback_to" { ///| test "UndoLogs::pop" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) let popped = logs.pop().unwrap() - assert_eq(popped, setElem(1, "test")) + assert_eq(popped, Undo::SetElem(1, "test")) assert_eq(logs.length(), 1) } ///| test "UndoLogs::last" { - let logs = new() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + let logs = UndoLogs::new() + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) let last = logs.last().unwrap() - assert_eq(last, setElem(1, "test")) + assert_eq(last, Undo::SetElem(1, "test")) } ///| test "UndoLogs::commit" { - let logs = new() + let logs = UndoLogs::new() let s1 = logs.start_snapshot() - logs.push(newElem(0)) - logs.push(setElem(1, "test")) + logs.push(Undo::NewElem(0)) + logs.push(Undo::SetElem(1, "test")) logs.commit(s1) assert_eq(logs.length(), 0) } diff --git a/moon.mod.json b/moon.mod.json index 49f5707..bf5142e 100644 --- a/moon.mod.json +++ b/moon.mod.json @@ -1,10 +1,9 @@ { - "name": "BigOrangeQWQ/unification_table", - "version": "0.1.2", + "name": "chaijie/disjoint-set", + "version": "0.1.3", "readme": "README.md", - "repository": "https://github.com/BigOrangeQWQ/UnificationTable", + "repository": "https://github.com/chaijie2018/disjoint-set", "license": "Apache-2.0", - "keywords": ["data-structure", "algorithm", "unification", "table"], - "description": "A module for unification table operations in data structures and algorithms.", - "source": "src" + "keywords": ["disjoint-set", "union-find", "unification"], + "description": "A optimized implementation of union-find in MoonBit." } \ No newline at end of file diff --git a/moon.pkg.json b/moon.pkg.json new file mode 100644 index 0000000..da28c13 --- /dev/null +++ b/moon.pkg.json @@ -0,0 +1,3 @@ +{ + "import": ["chaijie/disjoint-set/internal/snapshot_array"] +} diff --git a/pkg.generated.mbti b/pkg.generated.mbti new file mode 100644 index 0000000..c95341a --- /dev/null +++ b/pkg.generated.mbti @@ -0,0 +1,65 @@ +// Generated using `moon info`, DON'T EDIT IT +package "chaijie/disjoint-set" + +import( + "chaijie/disjoint-set/internal/snapshot_array" +) + +// Values +fn new_snapshot(@snapshot_array.Snapshot) -> Snapshot + +// Errors + +// Types and methods +pub struct Snapshot { + snapshot : @snapshot_array.Snapshot +} + +pub struct UnificationTable[T] { + values : @snapshot_array.SnapshotArray[VarValue[T]] +} +fn[T] UnificationTable::commit(Self[T], Snapshot) -> Unit +fn[T] UnificationTable::find(Self[T], VarIndex) -> VarIndex +fn[T] UnificationTable::find_root(Self[T], VarValue[T]) -> VarValue[T] +fn[T] UnificationTable::get(Self[T], Int) -> VarValue[T]? +fn[T] UnificationTable::in_snapshot(Self[T]) -> Bool +fn[T] UnificationTable::index(Self[T], Int) -> VarIndex +fn[T] UnificationTable::new(capacity~ : Int) -> Self[T] +fn[T] UnificationTable::op_get(Self[T], Int) -> VarValue[T] +fn[T] UnificationTable::op_set(Self[T], Int, VarValue[T]) -> Unit +fn[T] UnificationTable::push(Self[T], T) -> Unit +fn[T] UnificationTable::push_var(Self[T], VarValue[T]) -> Unit +fn[T] UnificationTable::redirect_root(Self[T], Int, VarIndex, VarIndex, T) -> Unit +fn[T] UnificationTable::reset(Self[T]) -> Unit +fn[T] UnificationTable::rollback_to(Self[T], Snapshot) -> Unit +fn[T] UnificationTable::set(Self[T], VarIndex, VarValue[T]) -> Unit +fn[T] UnificationTable::start_snapshot(Self[T]) -> Snapshot +fn[T] UnificationTable::unioned(Self[T], VarIndex, VarIndex) -> Bool +fn[T] UnificationTable::unite(Self[T], VarIndex, VarIndex, T) -> VarIndex +fn[T] UnificationTable::update(Self[T], VarIndex, (VarValue[T]) -> VarValue[T]) -> Unit +fn[T] UnificationTable::value(Self[T], VarIndex) -> VarValue[T] +impl[T : Show] Show for UnificationTable[T] + +pub struct VarIndex { + index : Int +} +fn VarIndex::new(Int) -> Self +impl Eq for VarIndex +impl Show for VarIndex + +pub struct VarValue[T] { + mut value : T + mut rank : Int + mut parent : VarIndex +} +fn[T] VarValue::modify(Self[T], T) -> Unit +fn[T] VarValue::new(T, Int, VarIndex) -> Self[T] +fn[T] VarValue::redirect(Self[T], VarIndex) -> Self[T] +fn[T] VarValue::root(Self[T], Int, T) -> Self[T] +impl[T : Eq] Eq for VarValue[T] +impl[T : Show] Show for VarValue[T] + +// Type aliases + +// Traits + diff --git a/src/snapshot_array/moon.pkg.json b/src/snapshot_array/moon.pkg.json deleted file mode 100644 index 6627c3f..0000000 --- a/src/snapshot_array/moon.pkg.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "BigOrangeQWQ/unification_table/snapshot_array", - "import": [ - { "path": "BigOrangeQWQ/unification_table/undo_logs", "alias": "logs"} - ] -} \ No newline at end of file diff --git a/src/undo_logs/moon.pkg.json b/src/undo_logs/moon.pkg.json deleted file mode 100644 index b52ad3d..0000000 --- a/src/undo_logs/moon.pkg.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "BigOrangeQWQ/unification_table/undo_logs" -} \ No newline at end of file diff --git a/src/unify_table/moon.pkg.json b/src/unify_table/moon.pkg.json deleted file mode 100644 index e06c8c4..0000000 --- a/src/unify_table/moon.pkg.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "BigOrangeQWQ/unification_table/unify_table", - "import": [ - "BigOrangeQWQ/unification_table/snapshot_array" - ] -} \ No newline at end of file diff --git a/src/unify_table/unify_table.mbti b/src/unify_table/unify_table.mbti deleted file mode 100644 index de4808b..0000000 --- a/src/unify_table/unify_table.mbti +++ /dev/null @@ -1,67 +0,0 @@ -// Generated using `moon info`, DON'T EDIT IT -package "BigOrangeQWQ/unification_table/unify_table" - -import( - "BigOrangeQWQ/unification_table/snapshot_array" -) - -// Values -fn[T : Eq] new(capacity~ : Int) -> UnificationTable[T] - -fn new_index(Int) -> VarIndex - -fn new_snapshot(@snapshot_array.Snapshot) -> Snapshot - -fn[T : Eq] new_var_value(T, Int, VarIndex) -> VarValue[T] - -// Errors - -// Types and methods -pub struct Snapshot { - snapshot : @snapshot_array.Snapshot -} - -pub struct UnificationTable[T] { - values : @snapshot_array.SnapshotArray[VarValue[T]] -} -fn[T] UnificationTable::commit(Self[T], Snapshot) -> Unit -fn[T : Eq] UnificationTable::find(Self[T], VarIndex) -> VarIndex -fn[T : Eq] UnificationTable::find_root(Self[T], VarValue[T]) -> VarValue[T] -fn[T : Eq] UnificationTable::get(Self[T], Int) -> VarValue[T]? -fn[T] UnificationTable::in_snapshot(Self[T]) -> Bool -fn[T : Eq] UnificationTable::index(Self[T], Int) -> VarIndex -fn[T : Eq] UnificationTable::op_get(Self[T], Int) -> VarValue[T] -fn[T : Eq] UnificationTable::op_set(Self[T], Int, VarValue[T]) -> Unit -fn[T : Eq] UnificationTable::push(Self[T], T) -> Unit -fn[T : Eq] UnificationTable::push_var(Self[T], VarValue[T]) -> Unit -fn[T : Eq] UnificationTable::redirect_root(Self[T], Int, VarIndex, VarIndex, T) -> Unit -fn[T : Eq] UnificationTable::reset(Self[T]) -> Unit -fn[T] UnificationTable::rollback_to(Self[T], Snapshot) -> Unit -fn[T : Eq] UnificationTable::set(Self[T], VarIndex, VarValue[T]) -> Unit -fn[T] UnificationTable::start_snapshot(Self[T]) -> Snapshot -fn[T : Eq] UnificationTable::unioned(Self[T], VarIndex, VarIndex) -> Bool -fn[T : Eq] UnificationTable::unite(Self[T], VarIndex, VarIndex, T) -> VarIndex -fn[T : Eq] UnificationTable::update(Self[T], VarIndex, (VarValue[T]) -> VarValue[T]) -> Unit -fn[T : Eq] UnificationTable::value(Self[T], VarIndex) -> VarValue[T] -impl[T : Show] Show for UnificationTable[T] - -pub struct VarIndex { - index : Int -} -impl Show for VarIndex - -pub struct VarValue[T] { - mut value : T - mut rank : Int - mut parent : VarIndex -} -fn[T : Eq] VarValue::modify(Self[T], T) -> Unit -fn[T : Eq] VarValue::redirect(Self[T], VarIndex) -> Self[T] -fn[T : Eq] VarValue::root(Self[T], Int, T) -> Self[T] -impl[T : Eq] Eq for VarValue[T] -impl[T : Show] Show for VarValue[T] - -// Type aliases - -// Traits -