commit 00d693f55da3cb0edfdc2ebf25e0dd25a270217a
parent 4efce2e290a7d42d0a4eb1c3b50460af1e3cc8e6
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Wed, 13 May 2026 10:08:35 +0100
added allocators, although lots of memory bugs
im not even using them anymore, but ill keep it around i guess
Diffstat:
3 files changed, 119 insertions(+), 5 deletions(-)
diff --git a/allocate/alloc.ha b/allocate/alloc.ha
@@ -1,12 +1,22 @@
-export type createfn = fn(_: allocator, _: *opaque) (*opaque | nomem);
-export type destroyfn = fn(_: allocator, _: *opaque) void;
+export type createfn = fn(_: *allocator, _: *opaque, _: size) (*opaque | nomem);
+export type destroyfn = fn(_: *allocator, _: *opaque) void;
+export type finishfn = fn(_: *allocator) void;
export type vtable = struct {
create: *createfn,
- destroy: *destroyfn
+ destroy: *destroyfn,
+ finish: *finishfn
};
export type allocator = *vtable;
-export fn create(al: allocator, obj: *opaque) (*opaque | nomem) = al.create(al, obj);
-export fn destroy(al: allocator, obj: *opaque) (*opaque | nomem) = al.destroy(al, obj);
+export fn create(al: *allocator, obj: *opaque, s: size) (*opaque | nomem) = al.create(al, obj, s);
+export fn destroy(al: *allocator, obj: *opaque) void = al.destroy(al, obj);
+export fn finish(al: *allocator) void = al.finish(al);
+
+export fn copy(dst: *[*]u8, src: *[*]u8, s: size) void = {
+ for (let i = 0z; i < s; i += 1)
+ dst[i] = src[i];
+};
+
+export fn destroy_nothing(al: *allocator, obj: *opaque) void = return;
diff --git a/allocate/arena/+test.ha b/allocate/arena/+test.ha
@@ -0,0 +1,67 @@
+use allocate;
+
+@test
+fn SimpleAlloc() void = {
+ let al = &new(100)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &42: *int, size(int))!: *int;
+
+ assert(*ptr == 42);
+};
+
+@test
+fn TooSmallAlloc() void = {
+ let al = &new(5)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &[42, 43, 44]: *[]int, size(int) * 3);
+
+ assert(ptr is nomem);
+};
+
+@test
+fn ExactAlloc() void = {
+ let al = &new(size(int) * 3)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &[42, 43, 44]: *[]int, size(int) * 3): *[*]int;
+
+ assert(ptr[0] == 42);
+ assert(ptr[1] == 43);
+ assert(ptr[2] == 44);
+};
+
+@test
+fn OneSmallAlloc() void = {
+ let al = &new((size(int) * 3) - 1)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &[42, 43, 44]: *[]int, size(int) * 3);
+
+ assert(ptr is nomem);
+};
+
+@test
+fn OneBigAlloc() void = {
+ let al = &new((size(int) * 3) + 1)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &[42, 43, 44]: *[]int, size(int) * 3): *[*]int;
+
+ assert(ptr[0] == 42);
+ assert(ptr[1] == 43);
+ assert(ptr[2] == 44);
+};
+
+@test
+fn MultiAlloc() void = {
+ let al = &new(100)!;
+ defer allocate::finish(al);
+
+ let ptr = allocate::create(al, &42: *int, size(int)): *int;
+ let ptr2 = allocate::create(al, &123: *int, size(int)): *int;
+
+ assert(*ptr == 42);
+ assert(*ptr2 == 123);
+};
diff --git a/allocate/arena/arena.ha b/allocate/arena/arena.ha
@@ -0,0 +1,37 @@
+use allocate;
+
+export type arena = struct {
+ al: allocate::allocator,
+ heap: *[*]u8,
+ s: size,
+ pos: size
+};
+
+const vtable = allocate::vtable {
+ create = &create,
+ destroy = &allocate::destroy_nothing,
+ finish = &finish
+};
+
+fn create(al: *allocate::allocator, obj: *opaque, s: size) (*opaque | nomem) = {
+ let arena = al: *arena;
+ if (arena.pos + s > arena.s) return nomem;
+
+ allocate::copy(&arena.heap[arena.pos]: *[*]u8, obj: *[*]u8, s);
+ defer arena.pos += s;
+ return &arena.heap[arena.pos]: *opaque;
+};
+
+fn finish(al: *allocate::allocator) void = {
+ let arena = al: *arena;
+ free(arena.heap);
+};
+
+export fn new(s: size) (arena | nomem) = {
+ return arena{
+ al = &vtable,
+ heap: *[*]u8 = alloc([0...], s)?: *[*]u8,
+ s = s,
+ pos = 0z
+ };
+};