nomen-lang 0.0.7 → 0.0.8

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 (118) hide show
  1. package/NOMEN_AGENTS.md +235 -0
  2. package/core/System/Ansi.nm +150 -0
  3. package/core/System/Array.nm +358 -0
  4. package/core/System/BigInt.nm +887 -0
  5. package/core/System/Buffer.nm +526 -0
  6. package/core/System/Channel.nm +198 -0
  7. package/core/System/ClassBuffer.nm +229 -0
  8. package/core/System/Console.nm +211 -0
  9. package/core/System/Controls/Button.nm +138 -0
  10. package/core/System/Controls/CheckBox.nm +158 -0
  11. package/core/System/Controls/Container.nm +1562 -0
  12. package/core/System/Controls/Control.nm +28 -0
  13. package/core/System/Controls/Geometry.nm +101 -0
  14. package/core/System/Controls/Layout.nm +228 -0
  15. package/core/System/Controls/LayoutParams.nm +50 -0
  16. package/core/System/Controls/Text.nm +129 -0
  17. package/core/System/Controls/TextBox.nm +157 -0
  18. package/core/System/Controls/Window.nm +280 -0
  19. package/core/System/Disposable.nm +8 -0
  20. package/core/System/Enumerable.nm +10 -0
  21. package/core/System/Equatable.nm +10 -0
  22. package/core/System/Graph.nm +68 -0
  23. package/core/System/Hashable.nm +13 -0
  24. package/core/System/Init.nm +21 -0
  25. package/core/System/LinkedList.nm +64 -0
  26. package/core/System/List.nm +44 -0
  27. package/core/System/Map.nm +153 -0
  28. package/core/System/Math.nm +54 -0
  29. package/core/System/Mutex.nm +78 -0
  30. package/core/System/Nursery.nm +27 -0
  31. package/core/System/Sendable.nm +9 -0
  32. package/core/System/Set.nm +97 -0
  33. package/core/System/Stream/Directory.nm +176 -0
  34. package/core/System/Stream/File.nm +432 -0
  35. package/core/System/Stream/Http.nm +453 -0
  36. package/core/System/String.nm +154 -0
  37. package/core/System/StringBuilder.nm +249 -0
  38. package/core/System/Stringable.nm +8 -0
  39. package/core/System/Task.nm +263 -0
  40. package/core/System/Test.nm +241 -0
  41. package/core/System/Text/Json.nm +377 -0
  42. package/core/System/Text/JsonTree.nm +187 -0
  43. package/core/System/Text/Regex.nm +655 -0
  44. package/core/System/Time.nm +112 -0
  45. package/core/System/Tree.nm +70 -0
  46. package/core/System/Viewable.nm +27 -0
  47. package/core/System/bool.nm +66 -0
  48. package/core/System/char.nm +42 -0
  49. package/core/System/float.nm +43 -0
  50. package/core/System/int.nm +54 -0
  51. package/core/System/int64.nm +42 -0
  52. package/core/System/int8.nm +42 -0
  53. package/core/System/uint.nm +42 -0
  54. package/core/System/uint64.nm +42 -0
  55. package/core/System/uint8.nm +42 -0
  56. package/core/docs/System/Ansi.md +40 -0
  57. package/core/docs/System/Array.md +16 -0
  58. package/core/docs/System/BigInt.md +30 -0
  59. package/core/docs/System/Buffer.md +31 -0
  60. package/core/docs/System/Channel.md +10 -0
  61. package/core/docs/System/ClassBuffer.md +15 -0
  62. package/core/docs/System/Console.md +13 -0
  63. package/core/docs/System/Controls/Button.md +12 -0
  64. package/core/docs/System/Controls/CheckBox.md +15 -0
  65. package/core/docs/System/Controls/Container.md +82 -0
  66. package/core/docs/System/Controls/Control.md +5 -0
  67. package/core/docs/System/Controls/Geometry.md +26 -0
  68. package/core/docs/System/Controls/Layout.md +37 -0
  69. package/core/docs/System/Controls/LayoutParams.md +13 -0
  70. package/core/docs/System/Controls/Text.md +12 -0
  71. package/core/docs/System/Controls/TextBox.md +13 -0
  72. package/core/docs/System/Controls/Window.md +20 -0
  73. package/core/docs/System/Disposable.md +5 -0
  74. package/core/docs/System/Enumerable.md +5 -0
  75. package/core/docs/System/Graph.md +17 -0
  76. package/core/docs/System/Init.md +9 -0
  77. package/core/docs/System/LinkedList.md +16 -0
  78. package/core/docs/System/List.md +13 -0
  79. package/core/docs/System/Map.md +14 -0
  80. package/core/docs/System/Math.md +11 -0
  81. package/core/docs/System/Mutex.md +10 -0
  82. package/core/docs/System/Nursery.md +5 -0
  83. package/core/docs/System/Sendable.md +5 -0
  84. package/core/docs/System/Set.md +14 -0
  85. package/core/docs/System/Stream/Directory.md +12 -0
  86. package/core/docs/System/Stream/File.md +21 -0
  87. package/core/docs/System/String.md +14 -0
  88. package/core/docs/System/StringBuilder.md +12 -0
  89. package/core/docs/System/Stringable.md +5 -0
  90. package/core/docs/System/Task.md +15 -0
  91. package/core/docs/System/Text/Json.md +12 -0
  92. package/core/docs/System/Text/JsonTree.md +21 -0
  93. package/core/docs/System/Text/Regex.md +12 -0
  94. package/core/docs/System/Time.md +11 -0
  95. package/core/docs/System/Tree.md +18 -0
  96. package/core/docs/System/Viewable.md +5 -0
  97. package/core/docs/System/bool.md +9 -0
  98. package/core/docs/System/char.md +9 -0
  99. package/core/docs/System/float.md +9 -0
  100. package/core/docs/System/int.md +10 -0
  101. package/core/docs/System/int64.md +9 -0
  102. package/core/docs/System/int8.md +9 -0
  103. package/core/docs/System/uint.md +9 -0
  104. package/core/docs/System/uint64.md +9 -0
  105. package/core/docs/System/uint8.md +9 -0
  106. package/core/package.jsonc +4 -0
  107. package/dist/index.mjs +417 -5490
  108. package/package.json +33 -30
  109. package/src/args.ts +171 -0
  110. package/src/index.ts +53 -104
  111. package/src/init.ts +128 -0
  112. package/src/test.ts +6 -2
  113. package/test/fixtures/build/calc.test +0 -0
  114. package/test/fixtures/build/calc.test.c +0 -969
  115. package/test/fixtures/build/main.h +0 -170
  116. package/test/fixtures/calc.test.nm +0 -32
  117. package/tsconfig.json +0 -21
  118. package/vite.config.ts +0 -7
@@ -0,0 +1,249 @@
1
+ // StringBuilder: a growable byte buffer for incrementally building strings.
2
+ //
3
+ // Appending is O(1) amortized (geometric growth), and `to_string` finalizes
4
+ // the buffer in place (no extra copy). Used by Regex.replace_all and the
5
+ // Json parse/stringify paths to avoid the O(n^2) cost of repeated `string +`
6
+ // concatenation, where each `+` mallocs and copies the whole accumulator.
7
+
8
+ /**
9
+ * A growable byte buffer for incrementally building strings (O(1) amortized append)
10
+ **/
11
+ pub struct StringBuilder {
12
+ var uint64 data = 0
13
+ var len = 0
14
+ var cap = 0
15
+
16
+ // Ensure capacity for at least `needed` bytes. Grows geometrically.
17
+ func ensure = (ref self, int needed) {
18
+ ```
19
+ #arch: c
20
+ if (self->cap >= needed) return;
21
+ int new_cap = self->cap;
22
+ if (new_cap == 0) new_cap = 16;
23
+ while (new_cap < needed) new_cap *= 2;
24
+ self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, new_cap);
25
+ self->cap = new_cap;
26
+ ```
27
+ ```
28
+ #arch: aarch64
29
+ // x19 = self, x1 = needed
30
+ ldr x2, [x19, #24] // cap
31
+ cmp x2, x1
32
+ b.ge .Lsb_ensure_end
33
+ // pick new_cap
34
+ mov x3, #16
35
+ cmp x2, #0
36
+ csel x3, x3, x2, eq
37
+ .Lsb_ensure_loop:
38
+ cmp x3, x1
39
+ b.ge .Lsb_ensure_grow
40
+ lsl x3, x3, #1
41
+ b .Lsb_ensure_loop
42
+ .Lsb_ensure_grow:
43
+ // save needed (x1) and new_cap (x3) across realloc
44
+ sub sp, sp, #32
45
+ str x1, [sp, #0]
46
+ str x3, [sp, #8]
47
+ str x2, [sp, #16] // old cap (unused after, but keeps stack aligned)
48
+ ldr x0, [x19, #8] // data
49
+ mov x1, x3
50
+ bl _realloc
51
+ str x0, [sp, #24] // saved new data ptr
52
+ ldr x1, [sp, #8] // new_cap
53
+ str x1, [x19, #24] // cap = new_cap
54
+ ldr x0, [sp, #24]
55
+ str x0, [x19, #8] // data = realloc result
56
+ add sp, sp, #32
57
+ .Lsb_ensure_end:
58
+ ```
59
+ }
60
+
61
+ // Append a single byte (char).
62
+ func append_char = (ref self, char c) {
63
+ ```
64
+ #arch: c
65
+ int idx = self->len;
66
+ if (idx + 1 >= self->cap) {
67
+ int nc = self->cap;
68
+ if (nc == 0) nc = 16;
69
+ while (nc < idx + 2) nc *= 2;
70
+ self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, nc);
71
+ self->cap = nc;
72
+ }
73
+ ((unsigned char*)(unsigned long long)self->data)[idx] = (unsigned char)c;
74
+ self->len = idx + 1;
75
+ ```
76
+ ```
77
+ #arch: aarch64
78
+ // x19 = self, w1 = c (low byte)
79
+ // Save c across the ensure/grow call.
80
+ sub sp, sp, #16
81
+ str w1, [sp, #0]
82
+ ldr x1, [x19, #16] // len
83
+ add x1, x1, #2 // need len + 2 bytes (char + null terminator room)
84
+ // inline ensure
85
+ ldr x2, [x19, #24] // cap
86
+ cmp x2, x1
87
+ b.ge .Lsb_ac_store
88
+ mov x3, #16
89
+ cmp x2, #0
90
+ csel x3, x3, x2, eq
91
+ .Lsb_ac_loop:
92
+ cmp x3, x1
93
+ b.ge .Lsb_ac_grow
94
+ lsl x3, x3, #1
95
+ b .Lsb_ac_loop
96
+ .Lsb_ac_grow:
97
+ str x3, [x19, #24] // cap = new_cap
98
+ ldr x0, [x19, #8]
99
+ mov x1, x3
100
+ bl _realloc
101
+ str x0, [x19, #8]
102
+ .Lsb_ac_store:
103
+ ldr w1, [sp, #0] // c
104
+ ldr x0, [x19, #8] // data
105
+ ldr x2, [x19, #16] // len
106
+ strb w1, [x0, x2]
107
+ add x2, x2, #1
108
+ str x2, [x19, #16] // len = len + 1
109
+ add sp, sp, #16
110
+ ```
111
+ }
112
+
113
+ // Append a null-terminated string.
114
+ func append_string = (ref self, string s) {
115
+ ```
116
+ #arch: c
117
+ int sl = strlen(s);
118
+ int needed = self->len + sl + 1;
119
+ if (needed > self->cap) {
120
+ int nc = self->cap;
121
+ if (nc == 0) nc = 16;
122
+ while (nc < needed) nc *= 2;
123
+ self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, nc);
124
+ self->cap = nc;
125
+ }
126
+ memcpy((unsigned char*)(unsigned long long)self->data + self->len, s, sl);
127
+ self->len = self->len + sl;
128
+ ```
129
+ ```
130
+ #arch: aarch64
131
+ // x19 = self, x1 = s
132
+ // Save s across strlen/realloc.
133
+ mov x0, x1
134
+ sub sp, sp, #32
135
+ str x0, [sp, #0]
136
+ bl _strlen
137
+ str x0, [sp, #8] // sl
138
+ ldr x1, [x19, #16] // len
139
+ add x1, x1, x0 // len + sl
140
+ add x1, x1, #1 // +1 for null room
141
+ // inline ensure(x1)
142
+ ldr x2, [x19, #24]
143
+ cmp x2, x1
144
+ b.ge .Lsb_as_copy
145
+ mov x3, #16
146
+ cmp x2, #0
147
+ csel x3, x3, x2, eq
148
+ .Lsb_as_loop:
149
+ cmp x3, x1
150
+ b.ge .Lsb_as_grow
151
+ lsl x3, x3, #1
152
+ b .Lsb_as_loop
153
+ .Lsb_as_grow:
154
+ str x3, [x19, #24]
155
+ ldr x0, [x19, #8]
156
+ mov x1, x3
157
+ bl _realloc
158
+ str x0, [x19, #8]
159
+ .Lsb_as_copy:
160
+ // memcpy(data + len, s, sl)
161
+ ldr x1, [sp, #8] // sl
162
+ ldr x0, [x19, #8] // data
163
+ ldr x2, [x19, #16] // len
164
+ add x0, x0, x2 // dest = data + len
165
+ ldr x1, [sp, #0] // src = s
166
+ ldr x2, [sp, #8] // n = sl
167
+ bl _memcpy
168
+ // len = len + sl
169
+ ldr x0, [x19, #16]
170
+ ldr x1, [sp, #8]
171
+ add x0, x0, x1
172
+ str x0, [x19, #16]
173
+ add sp, sp, #32
174
+ ```
175
+ }
176
+
177
+ // Finalize: null-terminate, return the byte buffer as a string, and
178
+ // release ownership (sets `data` to 0 so the destructor won't free it).
179
+ func to_string = (ref self, out string) {
180
+ ```
181
+ #arch: c
182
+ int idx = self->len;
183
+ int needed = idx + 1;
184
+ if (needed > self->cap) {
185
+ int nc = self->cap;
186
+ if (nc == 0) nc = 16;
187
+ while (nc < needed) nc *= 2;
188
+ self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, nc);
189
+ self->cap = nc;
190
+ }
191
+ ((unsigned char*)(unsigned long long)self->data)[idx] = 0;
192
+ unsigned long long result = self->data;
193
+ self->data = 0;
194
+ return (char*)result;
195
+ ```
196
+ ```
197
+ #arch: aarch64
198
+ // x19 = self
199
+ ldr x1, [x19, #16] // len
200
+ add x1, x1, #1 // need len + 1
201
+ ldr x2, [x19, #24]
202
+ cmp x2, x1
203
+ b.ge .Lsb_ts_store
204
+ mov x3, #16
205
+ cmp x2, #0
206
+ csel x3, x3, x2, eq
207
+ .Lsb_ts_loop:
208
+ cmp x3, x1
209
+ b.ge .Lsb_ts_grow
210
+ lsl x3, x3, #1
211
+ b .Lsb_ts_loop
212
+ .Lsb_ts_grow:
213
+ str x3, [x19, #24]
214
+ ldr x0, [x19, #8]
215
+ mov x1, x3
216
+ bl _realloc
217
+ str x0, [x19, #8]
218
+ .Lsb_ts_store:
219
+ ldr x0, [x19, #8] // x0 = data (this is what we return)
220
+ ldr x1, [x19, #16] // len
221
+ strb wzr, [x0, x1] // data[len] = 0
222
+ // transfer ownership: clear self->data. x0 retains the old ptr.
223
+ str xzr, [x19, #8]
224
+ ```
225
+ }
226
+
227
+ // Drop the buffer without finalizing (free the byte buffer outright).
228
+ func #destroy = () {
229
+ ```
230
+ #arch: c
231
+ if (self->data) {
232
+ free((void*)(unsigned long long)self->data);
233
+ self->data = 0;
234
+ self->len = 0;
235
+ self->cap = 0;
236
+ }
237
+ ```
238
+ ```
239
+ #arch: aarch64
240
+ ldr x0, [x19, #8]
241
+ cbz x0, .Lsb_destroy_end
242
+ bl _free
243
+ str xzr, [x19, #8]
244
+ str xzr, [x19, #16]
245
+ str xzr, [x19, #24]
246
+ .Lsb_destroy_end:
247
+ ```
248
+ }
249
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A trait for values that can be converted to a string via `to_string`
3
+ **/
4
+ pub trait Stringable {
5
+ func to_string = (self, out string) {
6
+ return ""
7
+ }
8
+ }
@@ -0,0 +1,263 @@
1
+ // Task runtime — thread-pool-backed execution primitive.
2
+ //
3
+ // Spawned tasks run on a shared worker pool. The pool starts at a
4
+ // configurable size (default 4, via Task.set_pool_size before the first
5
+ // spawn) and grows on demand up to 64 workers when every worker is busy,
6
+ // preventing deadlocks from nested spawns. The pool drains and joins all
7
+ // workers at process exit; Task.shutdown_pool does this explicitly.
8
+ //
9
+ // The pool infrastructure (types, worker loop, submit, shutdown, cancel
10
+ // thread-local) lives in build_spawn_node and is emitted as file-scope C
11
+ // on the first spawn — not in Task's own methods — so that Task can be
12
+ // generic without duplicating the pool per instantiation.
13
+ //
14
+ // See ASYNC.md for the design.
15
+
16
+ /**
17
+ * A handle to an asynchronously-running computation, backed by a shared thread pool
18
+ **/
19
+ pub class Task<T> : Sendable {
20
+ pub var uint64 handle = 0
21
+ pub var done = false
22
+ pub var uint64 result_slot = 0
23
+ pub var uint64 cancel_flag = 0
24
+ pub var uint64 future = 0
25
+
26
+ // Block until the task finishes. Idempotent — calling twice is safe, and
27
+ // a Task captured from a nursery spawn can be waited on here AND joined
28
+ // by the nursery at block exit (both wait on the same shared future).
29
+ pub func wait = (ref self) {
30
+ ```
31
+ #arch: c
32
+ if (self->future) {
33
+ __nomen_future_wait((struct nomen_future *)self->future);
34
+ } else if (self->handle && !self->done) {
35
+ void *ret;
36
+ pthread_join((pthread_t)self->handle, &ret);
37
+ self->handle = 0;
38
+ self->done = 1;
39
+ }
40
+ ```
41
+ ```
42
+ #arch: aarch64
43
+ // if (self->future) goto wait_future
44
+ ldr x0, [x19, #40]
45
+ cbz x0, .Lwait_handle
46
+ bl ___nomen_future_wait
47
+ b .Lwait_done
48
+ .Lwait_handle:
49
+ // else if (self->handle && !self->done)
50
+ ldr x0, [x19, #8]
51
+ cbz x0, .Lwait_done
52
+ ldrb w1, [x19, #16]
53
+ cbnz w1, .Lwait_done
54
+ // pthread_join((pthread_t)self->handle, &ret)
55
+ sub sp, sp, #16
56
+ mov x1, sp
57
+ bl _pthread_join
58
+ add sp, sp, #16
59
+ // self->handle = 0; self->done = 1
60
+ str xzr, [x19, #8]
61
+ mov w0, #1
62
+ strb w0, [x19, #16]
63
+ .Lwait_done:
64
+ ```
65
+ }
66
+
67
+ // Block until the task finishes, then return its result as T.
68
+ // The spawn build phase allocates a heap slot (owned by the future) and
69
+ // the trampoline writes the function's return value there before exiting.
70
+ // For tasks with no return value (void functions), returns the zero value.
71
+ pub func result = (ref self, out T) {
72
+ ```
73
+ #arch: c
74
+ if (self->future) {
75
+ __nomen_future_wait((struct nomen_future *)self->future);
76
+ } else if (self->handle && !self->done) {
77
+ void *ret;
78
+ pthread_join((pthread_t)self->handle, &ret);
79
+ self->handle = 0;
80
+ self->done = 1;
81
+ }
82
+ return *(T *)self->result_slot;
83
+ ```
84
+ ```
85
+ #arch: aarch64
86
+ // Wait for completion (same as wait method)
87
+ ldr x0, [x19, #40]
88
+ cbz x0, .Lresult_handle
89
+ bl ___nomen_future_wait
90
+ b .Lresult_read
91
+ .Lresult_handle:
92
+ ldr x0, [x19, #8]
93
+ cbz x0, .Lresult_read
94
+ ldrb w1, [x19, #16]
95
+ cbnz w1, .Lresult_read
96
+ sub sp, sp, #16
97
+ mov x1, sp
98
+ bl _pthread_join
99
+ add sp, sp, #16
100
+ str xzr, [x19, #8]
101
+ mov w0, #1
102
+ strb w0, [x19, #16]
103
+ .Lresult_read:
104
+ // return *(T *)self->result_slot
105
+ ldr x0, [x19, #24]
106
+ ldr x0, [x0]
107
+ ```
108
+ }
109
+
110
+ // Block until the task finishes, then return its result as a uint64.
111
+ // Convenience for the common case; same as result() for uint64 tasks.
112
+ pub func result_uint64 = (ref self, out uint64) {
113
+ ```
114
+ #arch: c
115
+ if (self->future) {
116
+ __nomen_future_wait((struct nomen_future *)self->future);
117
+ } else if (self->handle && !self->done) {
118
+ void *ret;
119
+ pthread_join((pthread_t)self->handle, &ret);
120
+ self->handle = 0;
121
+ self->done = 1;
122
+ }
123
+ return *(unsigned long long *)self->result_slot;
124
+ ```
125
+ ```
126
+ #arch: aarch64
127
+ // Wait for completion
128
+ ldr x0, [x19, #40]
129
+ cbz x0, .Lru64_handle
130
+ bl ___nomen_future_wait
131
+ b .Lru64_read
132
+ .Lru64_handle:
133
+ ldr x0, [x19, #8]
134
+ cbz x0, .Lru64_read
135
+ ldrb w1, [x19, #16]
136
+ cbnz w1, .Lru64_read
137
+ sub sp, sp, #16
138
+ mov x1, sp
139
+ bl _pthread_join
140
+ add sp, sp, #16
141
+ str xzr, [x19, #8]
142
+ mov w0, #1
143
+ strb w0, [x19, #16]
144
+ .Lru64_read:
145
+ // return *(unsigned long long *)self->result_slot
146
+ ldr x0, [x19, #24]
147
+ ldr x0, [x0]
148
+ ```
149
+ }
150
+
151
+ // Request that the task stop. Cooperative — the task observes this via
152
+ // `Task.current_cancelled()` at its own checkpoints. No preemption.
153
+ pub func cancel = (ref self) {
154
+ ```
155
+ #arch: c
156
+ if (self->cancel_flag) {
157
+ *(unsigned long long *)self->cancel_flag = 1;
158
+ }
159
+ ```
160
+ ```
161
+ #arch: aarch64
162
+ // if (self->cancel_flag) *(self->cancel_flag) = 1
163
+ ldr x0, [x19, #32]
164
+ cbz x0, .Lcancel_done
165
+ mov x1, #1
166
+ str x1, [x0]
167
+ .Lcancel_done:
168
+ ```
169
+ }
170
+
171
+ // Has the currently-running task been asked to cancel? Returns false
172
+ // when called from outside any spawned task (e.g. main thread).
173
+ pub func current_cancelled = (out bool) {
174
+ ```
175
+ #arch: c
176
+ return __nomen_current_cancel_flag && *__nomen_current_cancel_flag;
177
+ ```
178
+ ```
179
+ #arch: aarch64_use_c
180
+ return __nomen_current_cancel_flag && *__nomen_current_cancel_flag;
181
+ ```
182
+ }
183
+
184
+ // Configure the worker pool size. Must be called before the first spawn
185
+ // — once the pool is initialized (lazily on first submit), the initial
186
+ // size is fixed (the pool still grows on demand up to 64 workers when
187
+ // every worker is busy). No-op if called after init (silent; check the
188
+ // return value to detect). Returns 1 if the size was set, 0 otherwise.
189
+ pub func set_pool_size = (int n, out int) {
190
+ ```
191
+ #arch: c
192
+ if (__nomen_pool_init || n <= 0) return 0;
193
+ __nomen_pool_size = n;
194
+ return 1;
195
+ ```
196
+ ```
197
+ #arch: aarch64
198
+ // x0 = n (first arg)
199
+ // if (__nomen_pool_init || n <= 0) return 0
200
+ adrp x1, ___nomen_pool_init@PAGE
201
+ add x1, x1, ___nomen_pool_init@PAGEOFF
202
+ ldr w2, [x1]
203
+ cbnz w2, .Lsps_zero
204
+ cmp x0, #0
205
+ b.le .Lsps_zero
206
+ // __nomen_pool_size = n
207
+ adrp x1, ___nomen_pool_size@PAGE
208
+ add x1, x1, ___nomen_pool_size@PAGEOFF
209
+ str w0, [x1]
210
+ mov x0, #1
211
+ b .Lsps_done
212
+ .Lsps_zero:
213
+ mov x0, #0
214
+ .Lsps_done:
215
+ ```
216
+ }
217
+
218
+ // Shut the worker pool down: drain the queue, join every worker, and
219
+ // free the pool. Runs automatically at process exit (registered via
220
+ // atexit on first submit), so outstanding fire-and-forget tasks always
221
+ // complete before exit. Call explicitly to join all outstanding tasks
222
+ // before continuing; the pool re-initializes on the next spawn.
223
+ // Do NOT call from a spawned task (a worker joining its coworkers
224
+ // deadlocks).
225
+ pub func shutdown_pool = () {
226
+ ```
227
+ #arch: c
228
+ __nomen_pool_shutdown();
229
+ ```
230
+ ```
231
+ #arch: aarch64
232
+ bl ___nomen_pool_shutdown
233
+ ```
234
+ }
235
+
236
+ // Release this handle's reference to the future. The future owns the
237
+ // result slot and cancel flag; it (and they) are freed only when the
238
+ // last reference — this handle, the running trampoline, or a tracking
239
+ // nursery — is released. The Task instance itself is freed by the
240
+ // auto-free pass after #destroy returns.
241
+ pub func #destroy = () {
242
+ ```
243
+ #arch: c
244
+ if (self->future) {
245
+ __nomen_future_release((struct nomen_future *)self->future);
246
+ self->future = 0;
247
+ self->result_slot = 0;
248
+ self->cancel_flag = 0;
249
+ }
250
+ ```
251
+ ```
252
+ #arch: aarch64
253
+ // if (self->future) { release; zero fields }
254
+ ldr x0, [x19, #40]
255
+ cbz x0, .Ldestroy_done
256
+ bl ___nomen_future_release
257
+ str xzr, [x19, #40]
258
+ str xzr, [x19, #24]
259
+ str xzr, [x19, #32]
260
+ .Ldestroy_done:
261
+ ```
262
+ }
263
+ }