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
58pub 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