Skip to content

Commit 333d35f

Browse files
author
TheDevConnor
committed
Made an arena lib
1 parent 620652e commit 333d35f

1 file changed

Lines changed: 143 additions & 4 deletions

File tree

std/arena.lx

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,148 @@
11
@module "arena"
22

3-
@use "memory" as memory
3+
@use "string" as string
4+
@use "memory" as mem
5+
6+
const ARENA_DEFAULT_SIZE: int = 1024 * 1024;
47

58
pub const Arena -> struct {
6-
memory: *byte,
7-
offset: int,
8-
capacity: int,
9+
pub:
10+
buf: *byte,
11+
buf_len: int,
12+
prev_offset: int,
13+
curr_offset: int,
14+
15+
alloc_arena -> fn (size: int) *void {
16+
let alignment: int = 8;
17+
let padding: int = (alignment - (self.curr_offset % alignment)) % alignment;
18+
let aligned_offset: int = self.curr_offset + padding;
19+
20+
if (aligned_offset + size > self.buf_len) {
21+
let new_size: int = self.buf_len * 2;
22+
if (new_size < aligned_offset + size) {
23+
new_size = aligned_offset + size;
24+
}
25+
26+
let new_buf: *byte = cast<*byte>(mem::realloc(cast<*void>(self.buf), new_size));
27+
if (new_buf == cast<*byte>(0)) {
28+
return cast<*void>(0);
29+
}
30+
31+
self.buf = new_buf;
32+
self.buf_len = new_size;
33+
}
34+
35+
let ptr: *void = cast<*void>(cast<int>(self.buf) + aligned_offset);
36+
self.prev_offset = aligned_offset;
37+
self.curr_offset = aligned_offset + size;
38+
39+
return ptr;
40+
},
41+
42+
// Allocate with custom alignment (useful for SIMD, cache lines, etc.)
43+
alloc_arena_aligned -> fn (size: int, alignment: int) *void {
44+
let padding: int = (alignment - (self.curr_offset % alignment)) % alignment;
45+
let aligned_offset: int = self.curr_offset + padding;
46+
47+
if (aligned_offset + size > self.buf_len) {
48+
let new_size: int = self.buf_len * 2;
49+
if (new_size < aligned_offset + size) {
50+
new_size = aligned_offset + size;
51+
}
52+
53+
let new_buf: *byte = cast<*byte>(mem::realloc(cast<*void>(self.buf), new_size));
54+
if (new_buf == cast<*byte>(0)) {
55+
return cast<*void>(0);
56+
}
57+
58+
self.buf = new_buf;
59+
self.buf_len = new_size;
60+
}
61+
62+
let ptr: *void = cast<*void>(cast<int>(self.buf) + aligned_offset);
63+
self.prev_offset = aligned_offset;
64+
self.curr_offset = aligned_offset + size;
65+
66+
return ptr;
67+
},
68+
69+
// Allocate and zero memory (calloc equivalent)
70+
alloc_arena_zero -> fn (size: int) *void {
71+
let ptr: *void = self.alloc_arena(size);
72+
if (ptr != cast<*void>(0)) {
73+
mem::memzero(ptr, size);
74+
}
75+
return ptr;
76+
},
77+
78+
// Duplicate a memory block into arena
79+
alloc_arena_dup -> fn (src: *void, size: int) *void {
80+
let ptr: *void = self.alloc_arena(size);
81+
if (ptr != cast<*void>(0)) {
82+
mem::memcpy(ptr, src, size);
83+
}
84+
return ptr;
85+
},
86+
87+
// Duplicate a string into arena
88+
alloc_arena_string -> fn (source: *byte) *byte {
89+
let len: int = string::strlen(source) + 1; // +1 for null terminator
90+
let ptr: *byte = cast<*byte>(self.alloc_arena(len));
91+
if (ptr != cast<*byte>(0)) {
92+
string::copy(ptr, source);
93+
}
94+
return ptr;
95+
},
96+
97+
// Get current usage statistics
98+
get_usage -> fn () int { return self.curr_offset; },
99+
100+
get_capacity -> fn () int { return self.buf_len; },
101+
102+
get_remaining -> fn () int { return self.buf_len - self.curr_offset; },
103+
104+
// Check if pointer is within arena bounds (useful for debugging)
105+
contains_ptr -> fn (ptr: *void) bool {
106+
let addr: int = cast<int>(ptr);
107+
let start: int = cast<int>(self.buf);
108+
let end: int = start + self.buf_len;
109+
return (addr >= start && addr < end);
110+
},
111+
112+
// Rewind to a previous offset (checkpoint/restore pattern)
113+
save_checkpoint -> fn () int { return self.curr_offset; },
114+
115+
restore_checkpoint -> fn (checkpoint: int) void {
116+
if (checkpoint >= 0 && checkpoint <= self.buf_len) {
117+
self.curr_offset = checkpoint;
118+
}
119+
},
120+
121+
reset_arena -> fn () void {
122+
self.curr_offset = 0;
123+
self.prev_offset = 0;
124+
},
125+
126+
free_arena -> fn () void {
127+
free(self.buf);
128+
self.buf = cast<*byte>(0);
129+
self.buf_len = 0;
130+
self.curr_offset = 0;
131+
self.prev_offset = 0;
132+
}
9133
};
134+
135+
#returns_ownership
136+
pub const create_arena_sized -> fn (size: int) Arena {
137+
let a: Arena;
138+
a.buf = cast<*byte>(alloc(size));
139+
a.buf_len = size;
140+
a.curr_offset = 0;
141+
a.prev_offset = 0;
142+
return a;
143+
}
144+
145+
#returns_ownership
146+
pub const create_arena -> fn () Arena {
147+
return create_arena_sized(ARENA_DEFAULT_SIZE);
148+
}

0 commit comments

Comments
 (0)