Skip to content

Commit

Permalink
Merge pull request #6 from canscale/extract-types
Browse files Browse the repository at this point in the history
Extract BTree types into Types.mo to avoid cyclic dependencies
  • Loading branch information
ByronBecker authored Nov 20, 2022
2 parents a3e6f98 + a860de9 commit 119e46a
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 39 deletions.
30 changes: 6 additions & 24 deletions src/BTree.mo
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// The BTree module collection of functions and types

import Types "./Types";
import BS "./BinarySearch";
import AU "./ArrayUtil";

Expand All @@ -13,30 +14,11 @@ import Option "mo:base/Option";


module {
public type Node<K, V> = {
#leaf: Leaf<K, V>;
#internal: Internal<K, V>;
};

public type Data<K, V> = {
kvs: [var ?(K, V)];
var count: Nat;
};

public type Internal<K, V> = {
data: Data<K, V>;
children: [var ?Node<K, V>]
};

public type Leaf<K, V> = {
data: Data<K, V>;
};

public type BTree<K, V> = {
var root: Node<K, V>;
order: Nat;
};

public type BTree<K, V> = Types.BTree<K, V>;
public type Node<K, V> = Types.Node<K, V>;
public type Internal<K, V> = Types.Internal<K, V>;
public type Leaf<K, V> = Types.Leaf<K, V>;
public type Data<K, V> = Types.Data<K, V>;

// TODO - enforce BTrees to have order of at least 4
public func init<K, V>(order: Nat): BTree<K, V> = {
Expand Down
16 changes: 8 additions & 8 deletions src/Check.mo
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import O "mo:base/Order";
import Option "mo:base/Option";
import Result "mo:base/Result";

import BT "./BTree";
import Types "./Types";


module {
/// Checks a BTree for validity, checking for both key ordering and node height/depth equivalence
public func check<K, V>(t: BT.BTree<K, V>, compare: (K, K) -> O.Order): Bool {
public func check<K, V>(t: Types.BTree<K, V>, compare: (K, K) -> O.Order): Bool {
switch(checkTreeDepthIsValid(t)) {
case (#err) { return false };
case _ {}
Expand All @@ -28,11 +28,11 @@ module {
};

// Ensures that the Btree is balanced and all sibling/cousin nodes (at same level) have the same height
public func checkTreeDepthIsValid<K, V>(t: BT.BTree<K, V>): CheckDepthResult {
public func checkTreeDepthIsValid<K, V>(t: Types.BTree<K, V>): CheckDepthResult {
depthCheckerHelper(t.root)
};

func depthCheckerHelper<K, V>(node: BT.Node<K, V>): CheckDepthResult {
func depthCheckerHelper<K, V>(node: Types.Node<K, V>): CheckDepthResult {
switch(node) {
case (#leaf(_)) { #ok(1) };
case (#internal(internalNode)) {
Expand Down Expand Up @@ -75,7 +75,7 @@ module {
};

/// Ensures the ordering of all elements in the BTree is valid
public func checkDataOrderIsValid<K, V>(t : BT.BTree<K, V>, compare: (K, K) -> O.Order): CheckOrderResult {
public func checkDataOrderIsValid<K, V>(t : Types.BTree<K, V>, compare: (K, K) -> O.Order): CheckOrderResult {
// allow for empty root (valid)
switch(t.root) {
case (#leaf(leafNode)) {
Expand All @@ -89,14 +89,14 @@ module {
rec(t.root, t.order, infCompare(compare), #infmin, #infmax)
};

func rec<K, V>(node : BT.Node<K, V>, order: Nat, compare : InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
func rec<K, V>(node : Types.Node<K, V>, order: Nat, compare : InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
switch (node) {
case (#leaf(leafNode)) { checkData(leafNode.data, order, compare, lower, upper) };
case (#internal(internalNode)) { checkInternal(internalNode, order, compare, lower, upper) };
}
};

func checkData<K, V>(data : BT.Data<K, V>, order: Nat, compare : InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
func checkData<K, V>(data : Types.Data<K, V>, order: Nat, compare : InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
let expectedMaxKeys: Nat = order - 1;
if (data.kvs.size() != expectedMaxKeys) { return #err };

Expand Down Expand Up @@ -126,7 +126,7 @@ module {
#ok
};

func checkInternal<K, V>(internal : BT.Internal<K, V>, order: Nat, compare: InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
func checkInternal<K, V>(internal : Types.Internal<K, V>, order: Nat, compare: InfCompare<K>, lower : Inf<K>, upper : Inf<K>): CheckOrderResult {
if (
internal.children.size() != order
or
Expand Down
26 changes: 26 additions & 0 deletions src/Types.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

module {
public type Node<K, V> = {
#leaf: Leaf<K, V>;
#internal: Internal<K, V>;
};

public type Data<K, V> = {
kvs: [var ?(K, V)];
var count: Nat;
};

public type Internal<K, V> = {
data: Data<K, V>;
children: [var ?Node<K, V>]
};

public type Leaf<K, V> = {
data: Data<K, V>;
};

public type BTree<K, V> = {
var root: Node<K, V>;
order: Nat;
};
}
15 changes: 8 additions & 7 deletions test/CheckTest.mo
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Nat "mo:base/Nat";

import Check "../src/Check";
import BT "../src/BTree";
import Types "../src/Types";

let orderResultTestableItem = func(result: Check.CheckOrderResult): T.TestableItem<Check.CheckOrderResult> = {
display = func(r: Check.CheckOrderResult): Text = switch(r) {
Expand Down Expand Up @@ -97,7 +98,7 @@ let checkTreeDepthIsValidSuite = S.suite("checkTreeDepthIsValid", [
]),
S.test("uneven & invalid BTree depth",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), ?(15, 15), null];
Expand Down Expand Up @@ -207,7 +208,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
S.suite("are not valid btrees", [
S.test("if have invalid nested leaf data order",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), null, null];
Expand Down Expand Up @@ -238,7 +239,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
),
S.test("if have invalid internal node data order",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), ?(0, 0), null];
Expand Down Expand Up @@ -269,7 +270,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
),
S.test("if have a null before a non-null key-value pair in a leaf",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), null, null];
Expand Down Expand Up @@ -300,7 +301,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
),
S.test("if have a null before a non-null key-value pair in an internal",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var null, ?(6, 6), null];
Expand Down Expand Up @@ -331,7 +332,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
),
S.test("if invalid number of children",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), ?(0, 0), null];
Expand Down Expand Up @@ -363,7 +364,7 @@ let checkDataOrderIsValidSuite = S.suite("checkDataDepthIsValid", [
),
S.test("if invalid number of keys",
do {
let t: BT.BTree<Nat, Nat> = {
let t: Types.BTree<Nat, Nat> = {
var root = #internal({
data = {
kvs = [var ?(6, 6), ?(0, 0), null];
Expand Down

0 comments on commit 119e46a

Please sign in to comment.