Skip to content

Commit 02a79a0

Browse files
committed
Basic dictionaries
1 parent 0659bf4 commit 02a79a0

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

libraries/common/dictionary.effekt

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
module dictionary
2+
3+
import array
4+
import bytearray
5+
import stream
6+
7+
8+
type Dictionary[A] {
9+
Empty()
10+
Leaf(value: A)
11+
Branch(children: Array[Dictionary[A]])
12+
Node(value: A, children: Array[Dictionary[A]])
13+
}
14+
15+
def insert[A](trie: Dictionary[A], key: String, value: A): Dictionary[A] =
16+
insert(trie, key.fromString, value)
17+
18+
def insert[A](trie: Dictionary[A], key: ByteArray, value: A): Dictionary[A] = {
19+
def go(trie: Dictionary[A], i: Int): Dictionary[A] =
20+
if (i < key.size) {
21+
trie match {
22+
case Empty() =>
23+
val child = go(Empty(), i + 1)
24+
val children = array(256, Empty())
25+
children.unsafeSet(key.unsafeGet(i).toInt, child)
26+
Branch(children)
27+
case Leaf(existing) =>
28+
val child = go(Empty(), i + 1)
29+
val children = array(256, Empty())
30+
children.unsafeSet(key.unsafeGet(i).toInt, child)
31+
Node(existing, children)
32+
case Branch(children) =>
33+
val child = go(children.unsafeGet(key.unsafeGet(i).toInt), i + 1)
34+
children.unsafeSet(key.unsafeGet(i).toInt, child)
35+
Branch(children)
36+
case Node(existing, children) =>
37+
val child = go(children.unsafeGet(key.unsafeGet(i).toInt), i + 1)
38+
children.unsafeSet(key.unsafeGet(i).toInt, child)
39+
Node(existing, children)
40+
}
41+
} else {
42+
trie match {
43+
case Empty() => Leaf(value)
44+
case Leaf(_) => Leaf(value)
45+
case Node(_, children) => Node(value, children)
46+
case Branch(children) => Node(value, children)
47+
}
48+
}
49+
go(trie, 0)
50+
}
51+
52+
def lookup[A](trie: Dictionary[A], key: String): Option[A] =
53+
lookup(trie, key.fromString)
54+
55+
def lookup[A](trie: Dictionary[A], key: ByteArray): Option[A] = {
56+
def go(trie: Dictionary[A], i: Int): Option[A] =
57+
if (i < key.size) {
58+
trie match {
59+
case Empty() => None()
60+
case Leaf(_) => None()
61+
case Branch(children) => go(children.unsafeGet(key.unsafeGet(i).toInt), i + 1)
62+
case Node(_, children) => go(children.unsafeGet(key.unsafeGet(i).toInt), i + 1)
63+
}
64+
} else {
65+
trie match {
66+
case Empty() => None()
67+
case Leaf(value) => Some(value)
68+
case Branch(_) => None()
69+
case Node(value, _) => Some(value)
70+
}
71+
}
72+
go(trie, 0)
73+
}
74+
75+
76+
record Tagged[A](key: ByteArray, value: A)
77+
78+
def collectTrie[A] { stream: () => Unit / emit[Tagged[A]] }: Dictionary[A] = {
79+
var trie = Empty()
80+
for[Tagged[A]] { stream() } { case Tagged(bytes, value) =>
81+
trie = trie.insert(bytes, value)
82+
}
83+
return trie
84+
}
85+
86+
87+

0 commit comments

Comments
 (0)