mt-lang 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +4 -4
  2. data/docs/index.html +4 -3
  3. data/lib/milk_tea/base.rb +1 -1
  4. data/std/asset_pack.mt +267 -0
  5. data/std/async/libuv_runtime.mt +539 -0
  6. data/std/async/mailbox.mt +191 -0
  7. data/std/async/runtime.mt +87 -0
  8. data/std/async.mt +87 -0
  9. data/std/base64.mt +185 -0
  10. data/std/behavior_tree.mt +396 -0
  11. data/std/binary.mt +314 -0
  12. data/std/binary_heap.mt +157 -0
  13. data/std/bitset.mt +239 -0
  14. data/std/box2d.mt +535 -0
  15. data/std/bytes.mt +46 -0
  16. data/std/c/box2d.mt +1254 -0
  17. data/std/c/cgltf.mt +647 -0
  18. data/std/c/cjson.mt +106 -0
  19. data/std/c/crypto.mt +11 -0
  20. data/std/c/crypto_support.h +51 -0
  21. data/std/c/ctype.mt +19 -0
  22. data/std/c/ctype_bindgen.h +29 -0
  23. data/std/c/curl.mt +1223 -0
  24. data/std/c/enet.mt +473 -0
  25. data/std/c/errno.mt +41 -0
  26. data/std/c/errno_bindgen.h +53 -0
  27. data/std/c/flecs.mt +2945 -0
  28. data/std/c/fs.linux.mt +43 -0
  29. data/std/c/fs.windows.mt +43 -0
  30. data/std/c/fs_support.h +954 -0
  31. data/std/c/gl.mt +2065 -0
  32. data/std/c/gl_registry_helpers.h +10748 -0
  33. data/std/c/glfw.mt +499 -0
  34. data/std/c/libc.mt +167 -0
  35. data/std/c/libuv.mt +1491 -0
  36. data/std/c/math.mt +22 -0
  37. data/std/c/math_bindgen.h +31 -0
  38. data/std/c/miniaudio.mt +3420 -0
  39. data/std/c/pcre2.mt +735 -0
  40. data/std/c/process.mt +58 -0
  41. data/std/c/process_support.h +1147 -0
  42. data/std/c/raygui.mt +1602 -0
  43. data/std/c/raylib.mt +1245 -0
  44. data/std/c/raymath.mt +163 -0
  45. data/std/c/rlgl.mt +434 -0
  46. data/std/c/rpng.mt +60 -0
  47. data/std/c/rres.mt +187 -0
  48. data/std/c/sdl3.mt +4132 -0
  49. data/std/c/sqlite3.mt +951 -0
  50. data/std/c/stb_image.mt +52 -0
  51. data/std/c/stb_image_resize2.mt +128 -0
  52. data/std/c/stb_image_write.mt +19 -0
  53. data/std/c/stb_rect_pack.mt +38 -0
  54. data/std/c/stb_truetype.mt +175 -0
  55. data/std/c/stb_vorbis.mt +31 -0
  56. data/std/c/stdio.mt +90 -0
  57. data/std/c/steamworks.h +5769 -0
  58. data/std/c/steamworks.mt +4771 -0
  59. data/std/c/string.mt +16 -0
  60. data/std/c/string_bindgen.h +36 -0
  61. data/std/c/sync.mt +33 -0
  62. data/std/c/sync_support.h +219 -0
  63. data/std/c/terminal.mt +24 -0
  64. data/std/c/terminal_support.h +408 -0
  65. data/std/c/time.mt +26 -0
  66. data/std/c/tls.mt +24 -0
  67. data/std/c/tls_support.h +626 -0
  68. data/std/c/tracy.mt +53 -0
  69. data/std/c/zlib.mt +20 -0
  70. data/std/c/zlib_support.h +239 -0
  71. data/std/c/zstd.mt +231 -0
  72. data/std/cell.mt +60 -0
  73. data/std/cgltf.mt +115 -0
  74. data/std/cjson.mt +90 -0
  75. data/std/cli.mt +768 -0
  76. data/std/cookie.mt +198 -0
  77. data/std/counter.mt +160 -0
  78. data/std/crypto.mt +74 -0
  79. data/std/cstring.mt +13 -0
  80. data/std/ctype.mt +52 -0
  81. data/std/curl/runtime.mt +261 -0
  82. data/std/curl.mt +38 -0
  83. data/std/deque.mt +348 -0
  84. data/std/encoding.mt +93 -0
  85. data/std/enet.mt +133 -0
  86. data/std/env.mt +41 -0
  87. data/std/errno.mt +47 -0
  88. data/std/flecs.mt +978 -0
  89. data/std/fmt.mt +271 -0
  90. data/std/fs.linux.mt +696 -0
  91. data/std/fs.windows.mt +711 -0
  92. data/std/fsm.mt +267 -0
  93. data/std/gl.mt +2062 -0
  94. data/std/glfw.mt +471 -0
  95. data/std/goap.mt +342 -0
  96. data/std/graph.mt +521 -0
  97. data/std/gzip.mt +77 -0
  98. data/std/hash.mt +429 -0
  99. data/std/http/server.mt +810 -0
  100. data/std/http.mt +1227 -0
  101. data/std/intern.mt +53 -0
  102. data/std/jobs.mt +288 -0
  103. data/std/json.mt +627 -0
  104. data/std/libc.mt +34 -0
  105. data/std/libuv.mt +554 -0
  106. data/std/linear_algebra.mt +243 -0
  107. data/std/linked_map.mt +372 -0
  108. data/std/linked_map_view.mt +49 -0
  109. data/std/linked_set.mt +117 -0
  110. data/std/log.mt +69 -0
  111. data/std/map.mt +418 -0
  112. data/std/math.mt +24 -0
  113. data/std/mem/arena.mt +137 -0
  114. data/std/mem/endian.mt +51 -0
  115. data/std/mem/heap.mt +298 -0
  116. data/std/mem/pool.mt +164 -0
  117. data/std/mem/stack.mt +47 -0
  118. data/std/mem/tracking.mt +119 -0
  119. data/std/miniaudio.mt +1299 -0
  120. data/std/multiset.mt +191 -0
  121. data/std/net/channel.mt +727 -0
  122. data/std/net/clock.mt +237 -0
  123. data/std/net/discovery.mt +277 -0
  124. data/std/net/lobby.mt +813 -0
  125. data/std/net/manager.mt +539 -0
  126. data/std/net/mux.mt +839 -0
  127. data/std/net/nat.mt +122 -0
  128. data/std/net/packet.mt +219 -0
  129. data/std/net/punch.mt +162 -0
  130. data/std/net/rpc.mt +119 -0
  131. data/std/net/session.mt +1157 -0
  132. data/std/net/stun.mt +252 -0
  133. data/std/net/sync.mt +183 -0
  134. data/std/net/turn.mt +459 -0
  135. data/std/net.mt +2944 -0
  136. data/std/oauth2.mt +408 -0
  137. data/std/option.mt +51 -0
  138. data/std/ordered_map.mt +497 -0
  139. data/std/ordered_set.mt +348 -0
  140. data/std/path.mt +368 -0
  141. data/std/pcre2/runtime.mt +35 -0
  142. data/std/pcre2.mt +78 -0
  143. data/std/priority_queue.mt +55 -0
  144. data/std/process.mt +837 -0
  145. data/std/queue.mt +55 -0
  146. data/std/random.mt +146 -0
  147. data/std/raygui.mt +99 -0
  148. data/std/raylib/debug_console.mt +71 -0
  149. data/std/raylib/easing.mt +388 -0
  150. data/std/raylib/packed_assets.mt +255 -0
  151. data/std/raylib/runtime.mt +30 -0
  152. data/std/raylib/tracy_gpu.mt +37 -0
  153. data/std/raylib.mt +1510 -0
  154. data/std/raymath.mt +153 -0
  155. data/std/result.mt +89 -0
  156. data/std/rlgl.mt +268 -0
  157. data/std/rpng.mt +46 -0
  158. data/std/rres.mt +36 -0
  159. data/std/sdl3/runtime.mt +54 -0
  160. data/std/sdl3.mt +1731 -0
  161. data/std/serialize.mt +68 -0
  162. data/std/set.mt +124 -0
  163. data/std/spatial.mt +176 -0
  164. data/std/sqlite3.mt +151 -0
  165. data/std/stack.mt +55 -0
  166. data/std/stb_image.mt +47 -0
  167. data/std/stb_image_resize2.mt +41 -0
  168. data/std/stb_image_write.mt +17 -0
  169. data/std/stb_rect_pack.mt +15 -0
  170. data/std/stb_truetype.mt +77 -0
  171. data/std/stb_vorbis.mt +16 -0
  172. data/std/stdio.mt +88 -0
  173. data/std/steamworks.mt +1542 -0
  174. data/std/str.mt +293 -0
  175. data/std/string.mt +234 -0
  176. data/std/sync.mt +194 -0
  177. data/std/tar.mt +704 -0
  178. data/std/terminal.mt +1002 -0
  179. data/std/testing.mt +266 -0
  180. data/std/thread.mt +120 -0
  181. data/std/time.mt +105 -0
  182. data/std/tls.mt +616 -0
  183. data/std/toml.mt +1310 -0
  184. data/std/tracy.mt +42 -0
  185. data/std/uri.mt +118 -0
  186. data/std/url.mt +372 -0
  187. data/std/vec.mt +433 -0
  188. data/std/zstd.mt +94 -0
  189. metadata +187 -2
data/std/mem/arena.mt ADDED
@@ -0,0 +1,137 @@
1
+ import std.mem.heap as heap
2
+
3
+ public type Mark = ptr_uint
4
+
5
+ public struct Arena:
6
+ memory: own[ubyte]?
7
+ capacity: ptr_uint
8
+ alignment: ptr_uint
9
+ offset: ptr_uint
10
+
11
+
12
+ public function create(capacity_bytes: ptr_uint) -> Arena:
13
+ return create_aligned(capacity_bytes, 1)
14
+
15
+
16
+ public function create_aligned(capacity_bytes: ptr_uint, alignment: ptr_uint) -> Arena:
17
+ let normalized_alignment = heap.normalize_alignment(alignment)
18
+ if normalized_alignment == 0:
19
+ fatal(c"arena.create_aligned requires a power-of-two alignment")
20
+
21
+ let memory = heap.alloc_bytes_aligned(capacity_bytes, normalized_alignment) else:
22
+ if capacity_bytes != 0:
23
+ fatal(c"arena.create_aligned out of memory")
24
+
25
+ return Arena(
26
+ memory = null,
27
+ capacity = 0,
28
+ alignment = normalized_alignment,
29
+ offset = 0,
30
+ )
31
+
32
+ return unsafe: Arena(
33
+ memory = own[ubyte]<-memory,
34
+ capacity = capacity_bytes,
35
+ alignment = normalized_alignment,
36
+ offset = 0
37
+ )
38
+
39
+
40
+ public function create_for[T](count: ptr_uint) -> Arena:
41
+ let element_size = ptr_uint<-size_of(T)
42
+ if heap.mul_overflows(count, element_size):
43
+ fatal(c"arena.create_for size overflow")
44
+
45
+ return create_aligned(count * element_size, align_of(T))
46
+
47
+
48
+ extending Arena:
49
+ public function mark() -> Mark:
50
+ return this.offset
51
+
52
+
53
+ public editable function reset(mark: Mark) -> void:
54
+ if mark > this.offset:
55
+ fatal(c"arena.reset invalid mark")
56
+
57
+ this.offset = mark
58
+
59
+
60
+ public function remaining_bytes() -> ptr_uint:
61
+ return this.capacity - this.offset
62
+
63
+
64
+ public editable function alloc_bytes(size_bytes: ptr_uint) -> ptr[ubyte]?:
65
+ return this.alloc_bytes_aligned(size_bytes, 1)
66
+
67
+
68
+ public editable function alloc_bytes_aligned(size_bytes: ptr_uint, alignment: ptr_uint) -> ptr[ubyte]?:
69
+ let backing = this.memory else:
70
+ return null
71
+ if alignment == 0:
72
+ return null
73
+ if (alignment & (alignment - 1)) != 0:
74
+ return null
75
+ if alignment > this.alignment:
76
+ return null
77
+
78
+ let mask = alignment - 1
79
+ if this.offset > heap.ptr_uint_max - mask:
80
+ return null
81
+
82
+ let aligned_offset = (this.offset + mask) & ~mask
83
+ if aligned_offset > this.capacity:
84
+ return null
85
+ if size_bytes > this.capacity - aligned_offset:
86
+ return null
87
+
88
+ let result = backing + aligned_offset
89
+ this.offset = aligned_offset + size_bytes
90
+ return result
91
+
92
+
93
+ public editable function alloc[T](count: ptr_uint) -> ptr[T]?:
94
+ let element_size = ptr_uint<-size_of(T)
95
+ if heap.mul_overflows(count, element_size):
96
+ return null
97
+
98
+ let memory = this.alloc_bytes_aligned(count * element_size, ptr_uint<-align_of(T)) else:
99
+ return null
100
+
101
+ return unsafe: ptr[T]<-memory
102
+
103
+
104
+ public editable function try_to_cstr(text: str) -> cstr?:
105
+ if text.len == heap.ptr_uint_max:
106
+ return null
107
+
108
+ let memory = this.alloc_bytes(text.len + 1) else:
109
+ return null
110
+
111
+ unsafe:
112
+ heap.copy_bytes(memory, ptr[ubyte]<-text.data, text.len)
113
+ let buffer = ptr[char]<-memory
114
+ read(buffer + text.len) = zero[char]
115
+ return cstr<-buffer
116
+
117
+
118
+ public editable function to_cstr(text: str) -> cstr:
119
+ if text.len == heap.ptr_uint_max:
120
+ fatal(c"arena.to_cstr size overflow")
121
+
122
+ let memory = this.alloc_bytes(text.len + 1) else:
123
+ fatal(c"arena.to_cstr out of memory")
124
+
125
+ unsafe:
126
+ heap.copy_bytes(memory, ptr[ubyte]<-text.data, text.len)
127
+ let buffer = ptr[char]<-memory
128
+ read(buffer + text.len) = zero[char]
129
+ return cstr<-buffer
130
+
131
+
132
+ public editable function release() -> void:
133
+ heap.release(this.memory)
134
+ this.memory = null
135
+ this.capacity = 0
136
+ this.alignment = 0
137
+ this.offset = 0
data/std/mem/endian.mt ADDED
@@ -0,0 +1,51 @@
1
+ public function swap_ushort(value: ushort) -> ushort:
2
+ return ushort<-(
3
+ ((uint<-value & 0x00ff) << 8) |
4
+ ((uint<-value & 0xff00) >> 8)
5
+ )
6
+
7
+
8
+ public function swap_uint(value: uint) -> uint:
9
+ return (
10
+ ((value & 0x000000ff) << 24) |
11
+ ((value & 0x0000ff00) << 8) |
12
+ ((value & 0x00ff0000) >> 8) |
13
+ ((value & 0xff000000) >> 24)
14
+ )
15
+
16
+
17
+ public function swap_ulong(value: ulong) -> ulong:
18
+ return (
19
+ ((value & 0x00000000000000fful) << 56) |
20
+ ((value & 0x000000000000ff00ul) << 40) |
21
+ ((value & 0x0000000000ff0000ul) << 24) |
22
+ ((value & 0x00000000ff000000ul) << 8) |
23
+ ((value & 0x000000ff00000000ul) >> 8) |
24
+ ((value & 0x0000ff0000000000ul) >> 24) |
25
+ ((value & 0x00ff000000000000ul) >> 40) |
26
+ ((value & 0xff00000000000000ul) >> 56)
27
+ )
28
+
29
+
30
+ public function hton_ushort(value: ushort) -> ushort:
31
+ return swap_ushort(value)
32
+
33
+
34
+ public function hton_uint(value: uint) -> uint:
35
+ return swap_uint(value)
36
+
37
+
38
+ public function hton_ulong(value: ulong) -> ulong:
39
+ return swap_ulong(value)
40
+
41
+
42
+ public function ntoh_ushort(value: ushort) -> ushort:
43
+ return swap_ushort(value)
44
+
45
+
46
+ public function ntoh_uint(value: uint) -> uint:
47
+ return swap_uint(value)
48
+
49
+
50
+ public function ntoh_ulong(value: ulong) -> ulong:
51
+ return swap_ulong(value)
data/std/mem/heap.mt ADDED
@@ -0,0 +1,298 @@
1
+ import std.c.libc as libc
2
+ import std.cstring as cstring
3
+
4
+ public const ptr_uint_max: ptr_uint = ~0
5
+ public const minimum_alignment: ptr_uint = size_of(ptr[void])
6
+
7
+
8
+ function valid_alignment(alignment: ptr_uint) -> bool:
9
+ if alignment == 0:
10
+ return false
11
+
12
+ return (alignment & (alignment - 1)) == 0
13
+
14
+
15
+ public function normalize_alignment(alignment: ptr_uint) -> ptr_uint:
16
+ if not valid_alignment(alignment):
17
+ return 0
18
+
19
+ let minimum = minimum_alignment
20
+ if alignment < minimum:
21
+ return minimum
22
+
23
+ return alignment
24
+
25
+
26
+ public function mul_overflows(left: ptr_uint, right: ptr_uint) -> bool:
27
+ if left != 0 and right > ptr_uint_max / left:
28
+ return true
29
+
30
+ return false
31
+
32
+
33
+ public function alloc_bytes(size_bytes: ptr_uint) -> ptr[void]?:
34
+ if size_bytes == 0:
35
+ return null
36
+
37
+ return libc.malloc(size_bytes)
38
+
39
+
40
+ public function must_alloc_bytes(size_bytes: ptr_uint) -> ptr[void]:
41
+ if size_bytes == 0:
42
+ fatal(c"heap.must_alloc_bytes requires size > 0")
43
+
44
+ let memory = alloc_bytes(size_bytes) else:
45
+ fatal(c"heap.must_alloc_bytes out of memory")
46
+
47
+ return memory
48
+
49
+
50
+ public function alloc_bytes_aligned(size_bytes: ptr_uint, alignment: ptr_uint) -> ptr[void]?:
51
+ if size_bytes == 0:
52
+ return null
53
+
54
+ let normalized_alignment = normalize_alignment(alignment)
55
+ if normalized_alignment == 0:
56
+ return null
57
+
58
+ let mask = normalized_alignment - 1
59
+ if size_bytes > ptr_uint_max - mask:
60
+ return null
61
+
62
+ let rounded_size = (size_bytes + mask) & ~mask
63
+ return libc.aligned_alloc(normalized_alignment, rounded_size)
64
+
65
+
66
+ public function must_alloc_bytes_aligned(size_bytes: ptr_uint, alignment: ptr_uint) -> ptr[void]:
67
+ if size_bytes == 0:
68
+ fatal(c"heap.must_alloc_bytes_aligned requires size > 0")
69
+
70
+ let normalized_alignment = normalize_alignment(alignment)
71
+ if normalized_alignment == 0:
72
+ fatal(c"heap.must_alloc_bytes_aligned requires a power-of-two alignment")
73
+
74
+ let memory = alloc_bytes_aligned(size_bytes, normalized_alignment) else:
75
+ fatal(c"heap.must_alloc_bytes_aligned out of memory")
76
+
77
+ return memory
78
+
79
+
80
+ public function alloc_zeroed_bytes(count: ptr_uint, element_size_bytes: ptr_uint) -> ptr[void]?:
81
+ if count == 0 or element_size_bytes == 0:
82
+ return null
83
+
84
+ if mul_overflows(count, element_size_bytes):
85
+ return null
86
+
87
+ return libc.calloc(count, element_size_bytes)
88
+
89
+
90
+ public function must_alloc_zeroed_bytes(count: ptr_uint, element_size_bytes: ptr_uint) -> ptr[void]:
91
+ if count == 0 or element_size_bytes == 0:
92
+ fatal(c"heap.must_alloc_zeroed_bytes requires count > 0 and element size > 0")
93
+
94
+ let memory = alloc_zeroed_bytes(count, element_size_bytes) else:
95
+ fatal(c"heap.must_alloc_zeroed_bytes out of memory")
96
+
97
+ return memory
98
+
99
+
100
+ public function copy_bytes(destination: ptr[ubyte]?, source: ptr[ubyte]?, size_bytes: ptr_uint) -> void:
101
+ if size_bytes == 0:
102
+ return
103
+
104
+ if destination == null or source == null:
105
+ fatal(c"heap.copy_bytes requires non-null pointers for non-empty copies")
106
+
107
+ var index: ptr_uint = 0
108
+ while index < size_bytes:
109
+ unsafe:
110
+ read(destination + index) = read(source + index)
111
+ index += 1
112
+
113
+
114
+ public function move_bytes(destination: ptr[ubyte]?, source: ptr[ubyte]?, size_bytes: ptr_uint) -> void:
115
+ if size_bytes == 0:
116
+ return
117
+
118
+ if destination == null or source == null:
119
+ fatal(c"heap.move_bytes requires non-null pointers for non-empty copies")
120
+
121
+ unsafe:
122
+ cstring.move_bytes(ptr[void]<-destination, ptr[void]<-source, size_bytes)
123
+
124
+
125
+ public function resize_bytes(memory: ptr[void]?, size_bytes: ptr_uint) -> ptr[void]?:
126
+ if size_bytes == 0:
127
+ release_bytes(memory)
128
+ return null
129
+
130
+ return libc.realloc(memory, size_bytes)
131
+
132
+
133
+ public function must_resize_bytes(memory: ptr[void]?, size_bytes: ptr_uint) -> ptr[void]:
134
+ if size_bytes == 0:
135
+ fatal(c"heap.must_resize_bytes requires size > 0")
136
+
137
+ let resized = resize_bytes(memory, size_bytes) else:
138
+ fatal(c"heap.must_resize_bytes out of memory")
139
+
140
+ return resized
141
+
142
+
143
+ ## Frees a raw memory allocation. The caller's binding is NOT nulled after
144
+ ## this call — a second `release_bytes` on the same pointer is a double-free.
145
+ ## This is inherent to by-value pointer parameters: the function cannot reach
146
+ ## the caller's binding to null it. For idempotent safe-release syntax, see
147
+ ## `release_and_null[T]` or use a scope-bound allocator such as `arena.Arena`.
148
+ public function release_bytes(memory: ptr[void]?) -> void:
149
+ libc.free(memory)
150
+
151
+
152
+ public function alloc[T](count: ptr_uint) -> own[T]?:
153
+ let alignment = ptr_uint<-align_of(T)
154
+ if alignment > minimum_alignment:
155
+ return null
156
+
157
+ let element_size = ptr_uint<-size_of(T)
158
+ if mul_overflows(count, element_size):
159
+ return null
160
+
161
+ let memory = alloc_bytes(count * element_size) else:
162
+ return null
163
+
164
+ return unsafe: own[T]<-memory
165
+
166
+
167
+ public function must_alloc[T](count: ptr_uint) -> own[T]:
168
+ if count == 0:
169
+ fatal(c"heap.must_alloc requires count > 0")
170
+
171
+ if ptr_uint<-align_of(T) > minimum_alignment:
172
+ fatal(c"heap.must_alloc does not support over-aligned types")
173
+
174
+ let element_size = ptr_uint<-size_of(T)
175
+ if mul_overflows(count, element_size):
176
+ fatal(c"heap.must_alloc size overflow")
177
+
178
+ let memory = alloc[T](count) else:
179
+ fatal(c"heap.must_alloc out of memory")
180
+
181
+ return memory
182
+
183
+
184
+ public function alloc_aligned[T](count: ptr_uint) -> own[T]?:
185
+ let element_size = ptr_uint<-size_of(T)
186
+ if mul_overflows(count, element_size):
187
+ return null
188
+
189
+ let memory = alloc_bytes_aligned(count * element_size, align_of(T)) else:
190
+ return null
191
+
192
+ return unsafe: own[T]<-memory
193
+
194
+
195
+ public function must_alloc_aligned[T](count: ptr_uint) -> own[T]:
196
+ if count == 0:
197
+ fatal(c"heap.must_alloc_aligned requires count > 0")
198
+
199
+ let element_size = ptr_uint<-size_of(T)
200
+ if mul_overflows(count, element_size):
201
+ fatal(c"heap.must_alloc_aligned size overflow")
202
+
203
+ let memory = alloc_aligned[T](count) else:
204
+ fatal(c"heap.must_alloc_aligned out of memory")
205
+
206
+ return memory
207
+
208
+
209
+ public function alloc_zeroed[T](count: ptr_uint) -> own[T]?:
210
+ let alignment = ptr_uint<-align_of(T)
211
+ if alignment > minimum_alignment:
212
+ return null
213
+
214
+ let memory = alloc_zeroed_bytes(count, size_of(T)) else:
215
+ return null
216
+
217
+ return unsafe: own[T]<-memory
218
+
219
+
220
+ public function must_alloc_zeroed[T](count: ptr_uint) -> own[T]:
221
+ if count == 0:
222
+ fatal(c"heap.must_alloc_zeroed requires count > 0")
223
+
224
+ if ptr_uint<-align_of(T) > minimum_alignment:
225
+ fatal(c"heap.must_alloc_zeroed does not support over-aligned types")
226
+
227
+ let element_size = ptr_uint<-size_of(T)
228
+ if mul_overflows(count, element_size):
229
+ fatal(c"heap.must_alloc_zeroed size overflow")
230
+
231
+ let memory = alloc_zeroed[T](count) else:
232
+ fatal(c"heap.must_alloc_zeroed out of memory")
233
+
234
+ return memory
235
+
236
+
237
+ public function resize[T](memory: ptr[T]?, count: ptr_uint) -> own[T]?:
238
+ let alignment = ptr_uint<-align_of(T)
239
+ if alignment > minimum_alignment:
240
+ return null
241
+
242
+ let element_size = ptr_uint<-size_of(T)
243
+ if mul_overflows(count, element_size):
244
+ return null
245
+
246
+ if memory == null:
247
+ let resized = resize_bytes(null, count * element_size) else:
248
+ return null
249
+
250
+ return unsafe: own[T]<-resized
251
+
252
+ unsafe:
253
+ let resized = resize_bytes(ptr[void]<-memory, count * element_size) else:
254
+ return null
255
+
256
+ return own[T]<-resized
257
+
258
+
259
+ public function must_resize[T](memory: ptr[T]?, count: ptr_uint) -> own[T]:
260
+ if count == 0:
261
+ fatal(c"heap.must_resize requires count > 0")
262
+
263
+ if ptr_uint<-align_of(T) > minimum_alignment:
264
+ fatal(c"heap.must_resize does not support over-aligned types")
265
+
266
+ let element_size = ptr_uint<-size_of(T)
267
+ if mul_overflows(count, element_size):
268
+ fatal(c"heap.must_resize size overflow")
269
+
270
+ let resized = resize[T](memory, count) else:
271
+ fatal(c"heap.must_resize out of memory")
272
+
273
+ return resized
274
+
275
+
276
+ ## Frees a typed heap allocation. The caller's binding is NOT nulled — a
277
+ ## second `release` on the same pointer is a double-free. Prefer
278
+ ## `release_and_null[T]` when you need the binding nulled after freeing,
279
+ ## or use a scope-bound allocator such as `arena.Arena` for bulk free.
280
+ public function release[T](memory: ptr[T]?) -> void:
281
+ unsafe: release_bytes(ptr[void]<-memory)
282
+
283
+
284
+ ## Frees a typed heap allocation and nulls the caller's binding so a second
285
+ ## release is a no-op. The binding is passed by `ref[ptr[T]?]` so the helper
286
+ ## can write `null` back into the caller's variable.
287
+ ##
288
+ ## var mem = heap.must_alloc[MyStruct](1)
289
+ ## heap.release_and_null(ref_of(mem)) # mem is now null
290
+ ## heap.release_and_null(ref_of(mem)) # safe — no-op
291
+ public function release_and_null[T](memory: ref[ptr[T]?]) -> void:
292
+ unsafe: release_bytes(ptr[void]<-read(memory))
293
+ read(memory) = null
294
+
295
+
296
+ public function bytes_of[T](value: ref[T]) -> span[ubyte]:
297
+ unsafe:
298
+ return span[ubyte](data = ptr[ubyte]<-ptr_of(value), len = size_of(T))
data/std/mem/pool.mt ADDED
@@ -0,0 +1,164 @@
1
+ import std.mem.heap as heap
2
+
3
+
4
+ function slot_alignment(slot_size_bytes: ptr_uint, base_alignment: ptr_uint) -> ptr_uint:
5
+ if slot_size_bytes == 0:
6
+ return base_alignment
7
+
8
+ var alignment = base_alignment
9
+ while alignment > 1 and (slot_size_bytes & (alignment - 1)) != 0:
10
+ alignment = alignment / 2
11
+
12
+ return alignment
13
+
14
+ public struct Pool:
15
+ memory: ptr[ubyte]?
16
+ occupancy: ptr[bool]?
17
+ slot_size: ptr_uint
18
+ slot_alignment: ptr_uint
19
+ slot_count: ptr_uint
20
+ used_count: ptr_uint
21
+
22
+
23
+ public function create(slot_size_bytes: ptr_uint, slot_count: ptr_uint) -> Pool:
24
+ return create_aligned(slot_size_bytes, slot_count, 1)
25
+
26
+
27
+ public function create_aligned(slot_size_bytes: ptr_uint, slot_count: ptr_uint, alignment: ptr_uint) -> Pool:
28
+ let normalized_alignment = heap.normalize_alignment(alignment)
29
+ if normalized_alignment == 0:
30
+ fatal(c"pool.create_aligned requires a power-of-two alignment")
31
+
32
+ if slot_count == 0:
33
+ return Pool(
34
+ memory = null,
35
+ occupancy = null,
36
+ slot_size = slot_size_bytes,
37
+ slot_alignment = slot_alignment(slot_size_bytes, normalized_alignment),
38
+ slot_count = 0,
39
+ used_count = 0
40
+ )
41
+
42
+ if slot_size_bytes == 0:
43
+ fatal(c"pool.create_aligned requires slot size > 0 when slot count > 0")
44
+
45
+ if heap.mul_overflows(slot_size_bytes, slot_count):
46
+ fatal(c"pool.create size overflow")
47
+
48
+ let total_size = slot_size_bytes * slot_count
49
+ let memory = heap.alloc_bytes_aligned(total_size, normalized_alignment) else:
50
+ fatal(c"pool.create_aligned out of memory")
51
+
52
+ let occupancy = heap.alloc_zeroed[bool](slot_count) else:
53
+ heap.release_bytes(memory)
54
+ fatal(c"pool.create occupancy out of memory")
55
+
56
+ return unsafe: Pool(
57
+ memory = ptr[ubyte]<-memory,
58
+ occupancy = occupancy,
59
+ slot_size = slot_size_bytes,
60
+ slot_alignment = slot_alignment(slot_size_bytes, normalized_alignment),
61
+ slot_count = slot_count,
62
+ used_count = 0
63
+ )
64
+
65
+
66
+ public function slot_size_for[T]() -> ptr_uint:
67
+ let size = ptr_uint<-size_of(T)
68
+ let alignment = ptr_uint<-align_of(T)
69
+ let mask = alignment - 1
70
+ if size > heap.ptr_uint_max - mask:
71
+ fatal(c"pool.slot_size_for overflow")
72
+
73
+ return (size + mask) & ~mask
74
+
75
+
76
+ public function create_for[T](slot_count: ptr_uint) -> Pool:
77
+ return create_aligned(slot_size_for[T](), slot_count, align_of(T))
78
+
79
+
80
+ extending Pool:
81
+ public function remaining_slots() -> ptr_uint:
82
+ return this.slot_count - this.used_count
83
+
84
+
85
+ public editable function alloc_bytes() -> ptr[ubyte]?:
86
+ let memory = this.memory else:
87
+ return null
88
+ let occupancy = this.occupancy else:
89
+ return null
90
+
91
+ var index: ptr_uint = 0
92
+ while index < this.slot_count:
93
+ unsafe:
94
+ let state_ptr = occupancy + index
95
+ if not (read(state_ptr)):
96
+ read(state_ptr) = true
97
+ this.used_count = this.used_count + 1
98
+ return memory + (index * this.slot_size)
99
+ index = index + 1
100
+
101
+ return null
102
+
103
+
104
+ public editable function alloc[T]() -> ptr[T]?:
105
+ let size = ptr_uint<-size_of(T)
106
+ let alignment = ptr_uint<-align_of(T)
107
+ let mask = alignment - 1
108
+ if size > heap.ptr_uint_max - mask:
109
+ return null
110
+
111
+ let slot_size = (size + mask) & ~mask
112
+ if this.slot_alignment < alignment:
113
+ return null
114
+ if this.slot_size < slot_size:
115
+ return null
116
+
117
+ let memory = this.alloc_bytes() else:
118
+ return null
119
+
120
+ return unsafe: ptr[T]<-memory
121
+
122
+
123
+ public editable function release_bytes(slot: ptr[ubyte]?) -> bool:
124
+ if slot == null:
125
+ return false
126
+
127
+ let memory = this.memory else:
128
+ return false
129
+ let occupancy = this.occupancy else:
130
+ return false
131
+
132
+ var index: ptr_uint = 0
133
+ while index < this.slot_count:
134
+ unsafe:
135
+ let candidate = memory + (index * this.slot_size)
136
+ if candidate == slot:
137
+ let state_ptr = occupancy + index
138
+ if not (read(state_ptr)):
139
+ return false
140
+
141
+ read(state_ptr) = false
142
+ this.used_count = this.used_count - 1
143
+ return true
144
+ index = index + 1
145
+
146
+ return false
147
+
148
+
149
+ public editable function release_slot[T](slot: ptr[T]?) -> bool:
150
+ if slot == null:
151
+ return false
152
+
153
+ return unsafe: this.release_bytes(ptr[ubyte]<-slot)
154
+
155
+
156
+ public editable function release() -> void:
157
+ heap.release(this.memory)
158
+ heap.release(this.occupancy)
159
+ this.memory = null
160
+ this.occupancy = null
161
+ this.slot_size = 0
162
+ this.slot_alignment = 0
163
+ this.slot_count = 0
164
+ this.used_count = 0
data/std/mem/stack.mt ADDED
@@ -0,0 +1,47 @@
1
+ import std.mem.arena as arena
2
+
3
+ public type Mark = arena.Mark
4
+
5
+ public struct Stack:
6
+ arena: arena.Arena
7
+
8
+
9
+ public function create(capacity_bytes: ptr_uint) -> Stack:
10
+ return create_aligned(capacity_bytes, 1)
11
+
12
+
13
+ public function create_aligned(capacity_bytes: ptr_uint, alignment: ptr_uint) -> Stack:
14
+ return Stack(arena = arena.create_aligned(capacity_bytes, alignment))
15
+
16
+
17
+ public function create_for[T](count: ptr_uint) -> Stack:
18
+ return Stack(arena = arena.create_for[T](count))
19
+
20
+
21
+ extending Stack:
22
+ public function mark() -> Mark:
23
+ return this.arena.mark()
24
+
25
+
26
+ public editable function reset(mark: Mark) -> void:
27
+ this.arena.reset(mark)
28
+
29
+
30
+ public function remaining_bytes() -> ptr_uint:
31
+ return this.arena.remaining_bytes()
32
+
33
+
34
+ public editable function alloc_bytes(size_bytes: ptr_uint) -> ptr[ubyte]?:
35
+ return this.arena.alloc_bytes(size_bytes)
36
+
37
+
38
+ public editable function alloc_bytes_aligned(size_bytes: ptr_uint, alignment: ptr_uint) -> ptr[ubyte]?:
39
+ return this.arena.alloc_bytes_aligned(size_bytes, alignment)
40
+
41
+
42
+ public editable function alloc[T](count: ptr_uint) -> ptr[T]?:
43
+ return this.arena.alloc[T](count)
44
+
45
+
46
+ public editable function release() -> void:
47
+ this.arena.release()