aboutsummaryrefslogtreecommitdiff
path: root/set/set.ha
diff options
context:
space:
mode:
Diffstat (limited to 'set/set.ha')
-rw-r--r--set/set.ha80
1 files changed, 80 insertions, 0 deletions
diff --git a/set/set.ha b/set/set.ha
new file mode 100644
index 0000000..2c56efe
--- /dev/null
+++ b/set/set.ha
@@ -0,0 +1,80 @@
+export type set = struct {
+ items: []size,
+};
+
+export type nosuchitem = !void;
+
+export fn add(s: *set, item: size) bool = {
+ for (let i = 0z; i < len(s.items); i += 1) {
+ if (s.items[i] == item) {
+ return false;
+ };
+ };
+ append(s.items, item);
+ return true;
+};
+
+export fn del(s: *set, item: size) bool = {
+ match (contains(*s, item)) {
+ case let i: size =>
+ delete(s.items[i]);
+ return true;
+ case nosuchitem =>
+ return false;
+ };
+};
+
+export fn contains(s: set, item: size) (size | nosuchitem) = {
+ for (let i = 0z; i < len(s.items); i += 1) {
+ if (s.items[i] == item) {
+ return i;
+ };
+ };
+ return nosuchitem;
+};
+
+// Clears all items
+export fn clear(s: *set) void = {
+ delete(s.items[..]);
+};
+
+@test fn add() void = {
+ let s = set {...};
+ assert(add(&s, 1z));
+ assert(len(s.items) == 1);
+ assert(!add(&s, 1z));
+ assert(len(s.items) == 1);
+};
+
+@test fn del() void = {
+ let s = set {...};
+ assert(add(&s, 1z));
+ assert(len(s.items) == 1);
+ assert(del(&s, 1z));
+ assert(len(s.items) == 0);
+ assert(!del(&s, 1z));
+ assert(len(s.items) == 0);
+};
+
+@test fn contains() void = {
+ let s = set {...};
+ assert(add(&s, 1z));
+ assert(!add(&s, 1z));
+ const c = contains(s, 1z);
+ assert(c is size);
+ assert(c as size == 0);
+ assert(add(&s, 2z));
+ const c = contains(s, 2z);
+ assert(c is size);
+ assert(c as size == 1);
+};
+
+@test fn clear() void = {
+ let s = set {...};
+ assert(add(&s, 1z));
+ assert(len(s.items) == 1);
+ assert(!add(&s, 1z));
+ assert(len(s.items) == 1);
+ clear(&s);
+ assert(len(s.items) == 0);
+};