nomen-lang 0.9.0 → 0.10.0

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 (70) hide show
  1. package/core/System/Arena.nm +9 -7
  2. package/core/System/Array.nm +1 -1
  3. package/core/System/Atomic.nm +3 -3
  4. package/core/System/BigInt.nm +182 -23
  5. package/core/System/Buffer.nm +37 -35
  6. package/core/System/ClassBuffer.nm +18 -18
  7. package/core/System/Controls/Alert.nm +1 -1
  8. package/core/System/Controls/App.nm +5 -5
  9. package/core/System/Controls/Button.nm +1 -1
  10. package/core/System/Controls/CheckBox.nm +1 -1
  11. package/core/System/Controls/ColorPicker.nm +1 -1
  12. package/core/System/Controls/ComboBox.nm +1 -1
  13. package/core/System/Controls/Container.nm +34 -34
  14. package/core/System/Controls/DatePicker.nm +1 -1
  15. package/core/System/Controls/Form.nm +2 -2
  16. package/core/System/Controls/GroupBox.nm +1 -1
  17. package/core/System/Controls/ImageView.nm +1 -1
  18. package/core/System/Controls/Layout.nm +5 -5
  19. package/core/System/Controls/LevelIndicator.nm +1 -1
  20. package/core/System/Controls/ListView.nm +1 -1
  21. package/core/System/Controls/Menu.nm +1 -1
  22. package/core/System/Controls/NumberInput.nm +3 -3
  23. package/core/System/Controls/OtpInput.nm +2 -2
  24. package/core/System/Controls/OutlineView.nm +1 -1
  25. package/core/System/Controls/Pagination.nm +6 -6
  26. package/core/System/Controls/Popover.nm +1 -1
  27. package/core/System/Controls/Progress.nm +1 -1
  28. package/core/System/Controls/Radio.nm +1 -1
  29. package/core/System/Controls/Scrollable.nm +1 -1
  30. package/core/System/Controls/SearchField.nm +1 -1
  31. package/core/System/Controls/SecureField.nm +1 -1
  32. package/core/System/Controls/Segmented.nm +1 -1
  33. package/core/System/Controls/Select.nm +1 -1
  34. package/core/System/Controls/Separator.nm +1 -1
  35. package/core/System/Controls/Sheet.nm +1 -1
  36. package/core/System/Controls/Slider.nm +1 -1
  37. package/core/System/Controls/Spinner.nm +3 -3
  38. package/core/System/Controls/SplitView.nm +2 -2
  39. package/core/System/Controls/Stepper.nm +1 -1
  40. package/core/System/Controls/Switch.nm +1 -1
  41. package/core/System/Controls/Table.nm +1 -1
  42. package/core/System/Controls/Tabs.nm +1 -1
  43. package/core/System/Controls/Text.nm +1 -1
  44. package/core/System/Controls/TextBox.nm +1 -1
  45. package/core/System/Controls/TextView.nm +1 -1
  46. package/core/System/Controls/Toggle.nm +1 -1
  47. package/core/System/Controls/Toolbar.nm +1 -1
  48. package/core/System/Controls/Window.nm +11 -3
  49. package/core/System/Fiber.nm +16 -3
  50. package/core/System/Graph.nm +2 -2
  51. package/core/System/LinkedList.nm +8 -6
  52. package/core/System/List.nm +16 -13
  53. package/core/System/Map.nm +11 -9
  54. package/core/System/Random.nm +3 -3
  55. package/core/System/Set.nm +9 -7
  56. package/core/System/StableList.nm +7 -7
  57. package/core/System/Stream/File.nm +16 -16
  58. package/core/System/Stream/Http.nm +3 -3
  59. package/core/System/Stream/Tcp.nm +5 -5
  60. package/core/System/StringBuilder.nm +16 -16
  61. package/core/System/Task.nm +56 -64
  62. package/core/System/Test.nm +18 -18
  63. package/core/System/Text/Chars.nm +1 -1
  64. package/core/System/Text/Json.nm +12 -12
  65. package/core/System/Text/JsonTree.nm +8 -8
  66. package/core/System/Text/Regex.nm +20 -20
  67. package/core/System/Thread.nm +26 -3
  68. package/core/System/Tree.nm +19 -3
  69. package/dist/index.mjs +3036 -1845
  70. package/package.json +1 -1
@@ -63,7 +63,7 @@ pub struct File {
63
63
 
64
64
  // Open the file at `path` with a C mode string ("r", "w", "a", …).
65
65
  // Stores the handle and records errno (0 on success) in `error`.
66
- func raw_open = (ref self, string path, string mode) {
66
+ func raw_open = (ref self {}, string path, string mode) {
67
67
  ```
68
68
  #arch: c
69
69
  #scope: file
@@ -99,7 +99,7 @@ pub struct File {
99
99
 
100
100
  // Open the file at `path` with a C mode string ("r", "w", "a", …).
101
101
  // `.ok(true)` on success; `.error(FileError)` otherwise.
102
- pub func open = (ref self, string path, string mode, out Result<bool, FileError>) {
102
+ pub func open = (ref self {}, string path, string mode, out Result<bool, FileError>) {
103
103
  self.raw_open(path, mode)
104
104
  if self.error == 0 {
105
105
  return Result.ok(true)
@@ -110,7 +110,7 @@ pub struct File {
110
110
  // Close the handle, recording errno in `error` (0 on success). Also
111
111
  // performed automatically by #destroy; calling close explicitly releases
112
112
  // the resource early.
113
- func raw_close = (ref self) {
113
+ func raw_close = (ref self {}) {
114
114
  ```
115
115
  #arch: c
116
116
  if (self->handle) {
@@ -147,7 +147,7 @@ pub struct File {
147
147
  // Close the handle. Also performed automatically by #destroy; calling
148
148
  // close explicitly releases the resource early. Closing an unopened (or
149
149
  // already closed) File is `.ok(true)`.
150
- pub func close = (ref self, out Result<bool, FileError>) {
150
+ pub func close = (ref self {}, out Result<bool, FileError>) {
151
151
  self.raw_close()
152
152
  if self.error == 0 {
153
153
  return Result.ok(true)
@@ -158,7 +158,7 @@ pub struct File {
158
158
  // Read every byte from the current position to EOF and return it. Sets
159
159
  // `eof` and `error`. Declared `mv out string`: the raw body mallocs a
160
160
  // fresh buffer and hands ownership to the caller.
161
- func raw_read_all = (ref self, mv out string) {
161
+ func raw_read_all = (ref self {}, mv out string) {
162
162
  ```
163
163
  #arch: c
164
164
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -222,7 +222,7 @@ pub struct File {
222
222
  // Read every byte from the current position to EOF. `.ok(text)` with the
223
223
  // remaining bytes (and `eof` set), or `.error(FileError)` — including
224
224
  // `not_open` when the handle was never opened.
225
- pub func readAll = (ref self, out Result<string, FileError>) {
225
+ pub func readAll = (ref self {}, out Result<string, FileError>) {
226
226
  const string body = self.raw_read_all()
227
227
  if self.error == 0 {
228
228
  return Result.ok(body)
@@ -231,7 +231,7 @@ pub struct File {
231
231
  }
232
232
 
233
233
  // Write a string at the current position.
234
- func raw_write_all = (ref self, string data) {
234
+ func raw_write_all = (ref self {}, string data) {
235
235
  ```
236
236
  #arch: c
237
237
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -261,7 +261,7 @@ pub struct File {
261
261
  // Write a string at the current position. `.ok(true)`, or
262
262
  // `.error(FileError)` — including `not_open` when the handle was never
263
263
  // opened.
264
- pub func writeAll = (ref self, string data, out Result<bool, FileError>) {
264
+ pub func writeAll = (ref self {}, string data, out Result<bool, FileError>) {
265
265
  self.raw_write_all(data)
266
266
  if self.error == 0 {
267
267
  return Result.ok(true)
@@ -272,7 +272,7 @@ pub struct File {
272
272
  // Read up to the next '\n' (the newline is not included). Sets `eof`
273
273
  // when the end of the file is reached and `error` on failure. The raw
274
274
  // body mallocs a fresh buffer — `mv out string` transfers it.
275
- func raw_read_line = (ref self, mv out string) {
275
+ func raw_read_line = (ref self {}, mv out string) {
276
276
  ```
277
277
  #arch: c
278
278
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -364,7 +364,7 @@ pub struct File {
364
364
 
365
365
  // Read up to the next '\n' (the newline is not included). `.ok(text)`
366
366
  // and `eof` set at end of file, or `.error(FileError)`.
367
- pub func readLine = (ref self, out Result<string, FileError>) {
367
+ pub func readLine = (ref self {}, out Result<string, FileError>) {
368
368
  const string line = self.raw_read_line()
369
369
  if self.error == 0 {
370
370
  return Result.ok(line)
@@ -373,7 +373,7 @@ pub struct File {
373
373
  }
374
374
 
375
375
  // Write a string followed by '\n'.
376
- func raw_write_line = (ref self, string data) {
376
+ func raw_write_line = (ref self {}, string data) {
377
377
  ```
378
378
  #arch: c
379
379
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -405,7 +405,7 @@ pub struct File {
405
405
  }
406
406
 
407
407
  // Write a string followed by '\n'. `.ok(true)`, or `.error(FileError)`.
408
- pub func writeLine = (ref self, string data, out Result<bool, FileError>) {
408
+ pub func writeLine = (ref self {}, string data, out Result<bool, FileError>) {
409
409
  self.raw_write_line(data)
410
410
  if self.error == 0 {
411
411
  return Result.ok(true)
@@ -416,7 +416,7 @@ pub struct File {
416
416
  // Read up to `size` bytes from the current position. Sets `eof` if fewer
417
417
  // than `size` bytes remain and `error` on failure. The raw body mallocs a
418
418
  // fresh buffer — `mv out string` transfers it.
419
- func raw_read_chunk = (ref self, int size, mv out string) {
419
+ func raw_read_chunk = (ref self {}, int size, mv out string) {
420
420
  ```
421
421
  #arch: c
422
422
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -468,7 +468,7 @@ pub struct File {
468
468
 
469
469
  // Read up to `size` bytes from the current position. `.ok(text)`
470
470
  // (`eof` set if fewer bytes remained), or `.error(FileError)`.
471
- pub func readChunk = (ref self, int size, out Result<string, FileError>) {
471
+ pub func readChunk = (ref self {}, int size, out Result<string, FileError>) {
472
472
  const string chunk = self.raw_read_chunk(size)
473
473
  if self.error == 0 {
474
474
  return Result.ok(chunk)
@@ -477,7 +477,7 @@ pub struct File {
477
477
  }
478
478
 
479
479
  // Write the first `size` bytes of `data` at the current position.
480
- func raw_write_chunk = (ref self, string data, int size) {
480
+ func raw_write_chunk = (ref self {}, string data, int size) {
481
481
  ```
482
482
  #arch: c
483
483
  FILE *f = (FILE*)(unsigned long long)self->handle;
@@ -505,7 +505,7 @@ pub struct File {
505
505
 
506
506
  // Write the first `size` bytes of `data` at the current position.
507
507
  // `.ok(true)`, or `.error(FileError)`.
508
- pub func writeChunk = (ref self, string data, int size, out Result<bool, FileError>) {
508
+ pub func writeChunk = (ref self {}, string data, int size, out Result<bool, FileError>) {
509
509
  self.raw_write_chunk(data, size)
510
510
  if self.error == 0 {
511
511
  return Result.ok(true)
@@ -58,7 +58,7 @@ pub struct Http {
58
58
  // (sends `body` and the Content-* headers). Sets self->status (0 on
59
59
  // failure) and self->error, and returns the response body (empty string
60
60
  // on failure).
61
- func raw_exchange = (ref self, string method, string url, string body, mv out string) {
61
+ func raw_exchange = (ref self {}, string method, string url, string body, mv out string) {
62
62
  // Parse the URL: [http://]host[:port][/path]
63
63
  var host_start = 0
64
64
  if url.starts_with("http://") {
@@ -145,7 +145,7 @@ pub struct Http {
145
145
  // Issue a GET request to `url`. `.ok(body)` with the response body and
146
146
  // `self.status` set to the response's status code, or
147
147
  // `.error(HttpError)` (`status` is 0).
148
- pub func get = (ref self, string url, out Result<string, HttpError>) {
148
+ pub func get = (ref self {}, string url, out Result<string, HttpError>) {
149
149
  const string response = self.raw_exchange("GET", url, "")
150
150
  if self.error == 0 {
151
151
  return Result.ok(response)
@@ -156,7 +156,7 @@ pub struct Http {
156
156
  // Issue a POST request to `url` with `body` as the payload.
157
157
  // `.ok(body)` with the response body and `self.status` set to the
158
158
  // response's status code, or `.error(HttpError)` (`status` is 0).
159
- pub func post = (ref self, string url, string body, out Result<string, HttpError>) {
159
+ pub func post = (ref self {}, string url, string body, out Result<string, HttpError>) {
160
160
  const string response = self.raw_exchange("POST", url, body)
161
161
  if self.error == 0 {
162
162
  return Result.ok(response)
@@ -59,7 +59,7 @@ pub mv struct Tcp {
59
59
  ```
60
60
  }
61
61
 
62
- pub func close = (ref self) {
62
+ pub func close = (ref self {}) {
63
63
  Tcp.close_fd(self.fd)
64
64
  self.fd = -1
65
65
  }
@@ -81,7 +81,7 @@ pub mv struct Tcp {
81
81
  // Accept the next connection, parking the fiber while the backlog is
82
82
  // empty. The returned socket is -1 if the listener was cancelled or
83
83
  // failed.
84
- pub func accept = (ref self, mv out Tcp) {
84
+ pub func accept = (ref self {}, mv out Tcp) {
85
85
  var int handle = Tcp.accept_fd(self.fd)
86
86
  var t = Tcp(handle)
87
87
  if handle < 0 {
@@ -114,18 +114,18 @@ pub mv struct Tcp {
114
114
 
115
115
  // Send every byte of `data`. Parks the fiber while the send buffer is
116
116
  // full. Returns false on error or cancellation.
117
- pub func send = (ref self, string data, out bool) {
117
+ pub func send = (ref self {}, string data, out bool) {
118
118
  return Tcp.send_all(self.fd, data)
119
119
  }
120
120
 
121
121
  // Receive up to `max` bytes. Parks the fiber until data arrives; returns
122
122
  // the empty string at end-of-stream, on error, or when cancelled.
123
- pub func recv = (ref self, int max, mv out string) {
123
+ pub func recv = (ref self {}, int max, mv out string) {
124
124
  return Tcp.recv_some(self.fd, max)
125
125
  }
126
126
 
127
127
  // Receive until the peer closes (how Connection: close HTTP works).
128
- pub func recv_all = (ref self, mv out string) {
128
+ pub func recv_all = (ref self {}, mv out string) {
129
129
  return Tcp.recv_until_close(self.fd)
130
130
  }
131
131
 
@@ -18,7 +18,7 @@ pub struct StringBuilder {
18
18
  // this doesn't even require an unsafe context.
19
19
  // `internal`: capacity plumbing for the builder's own appenders; not
20
20
  // part of the user surface.
21
- internal func ensure = (ref self, int needed) {
21
+ internal func ensure = (ref self {}, int needed) {
22
22
  if self.cap >= needed {
23
23
  return
24
24
  }
@@ -32,7 +32,7 @@ pub struct StringBuilder {
32
32
  }
33
33
 
34
34
  // Append a single byte (char).
35
- pub inline func append_char = (ref self, char c) {
35
+ pub inline func append_char = (ref self {}, char c) {
36
36
  ```
37
37
  #arch: c
38
38
  int idx = self->len;
@@ -89,7 +89,7 @@ pub struct StringBuilder {
89
89
  // plus the intermediate string's malloc/free collapse to a few
90
90
  // instructions against the buffer. The raw body is spliced per call site
91
91
  // (labels renamed by the splicer), so the digit loop is truly inline.
92
- pub inline func append_int = (ref self, int n) {
92
+ pub inline func append_int = (ref self {}, int n) {
93
93
  ```
94
94
  #arch: c
95
95
  long v = n;
@@ -196,7 +196,7 @@ pub struct StringBuilder {
196
196
  // Append a float with the SAME text `float.to_string` produces ("%f"):
197
197
  // one snprintf into a stack scratch, then a bulk copy into the buffer —
198
198
  // no sizing pass and no intermediate string allocation.
199
- pub inline func append_float = (ref self, float f) {
199
+ pub inline func append_float = (ref self {}, float f) {
200
200
  ```
201
201
  #arch: c
202
202
  char tmp[360];
@@ -276,22 +276,22 @@ pub struct StringBuilder {
276
276
  }
277
277
 
278
278
  // Append a borrowed view without materializing it.
279
- pub func append = (ref self, view string s) {
279
+ pub func append = (ref self {}, view string s) {
280
280
  self.append_string_view(s)
281
281
  }
282
282
 
283
283
  // Append an int without materializing a string (see `append_int`).
284
- pub func append = (ref self, int n) {
284
+ pub func append = (ref self {}, int n) {
285
285
  self.append_int(n)
286
286
  }
287
287
 
288
288
  // Append a float without materializing a string (see `append_float`).
289
- pub func append = (ref self, float f) {
289
+ pub func append = (ref self {}, float f) {
290
290
  self.append_float(f)
291
291
  }
292
292
 
293
293
  // Append a single byte. (Overload, so `sb.append(c)` works for chars.)
294
- pub func append = (ref self, char c) {
294
+ pub func append = (ref self {}, char c) {
295
295
  self.append_char(c)
296
296
  }
297
297
 
@@ -300,7 +300,7 @@ pub struct StringBuilder {
300
300
  // `internal`: a library-implementation append — user code appends with
301
301
  // `append_char` / `append_string_view`; the library's own structs (Json,
302
302
  // Regex) are on the trusted side of the boundary.
303
- internal func append_string = (ref self, string s) {
303
+ internal func append_string = (ref self {}, string s) {
304
304
  unsafe {
305
305
  var int sl = s.length
306
306
  self.ensure(self.len + sl + 1)
@@ -314,7 +314,7 @@ pub struct StringBuilder {
314
314
  // call. Views lower to the same (ptr, len) fat pair, so the bytes are
315
315
  // memcpy'd straight out of the borrowed buffer (used by
316
316
  // `string.replace_first`/`replace_all`).
317
- pub func append_string_view = (ref self, view string s) {
317
+ pub func append_string_view = (ref self {}, view string s) {
318
318
  unsafe {
319
319
  var int sl = s.length
320
320
  self.ensure(self.len + sl + 1)
@@ -327,7 +327,7 @@ pub struct StringBuilder {
327
327
  // way to start a StringBuilder from a slice without a `to_string()`
328
328
  // copy: the view's bytes are copied once into fresh storage, so the
329
329
  // result is owned and independent of the source.
330
- pub func seed = (ref self, view string s) {
330
+ pub func seed = (ref self {}, view string s) {
331
331
  unsafe {
332
332
  var int sl = s.length
333
333
  self.ensure(sl + 1)
@@ -346,7 +346,7 @@ pub struct StringBuilder {
346
346
  // Whether the buffer's current bytes end with `suffix` (an empty suffix
347
347
  // is always true). Reads the buffer tail in place — no copy of either
348
348
  // side (`view string` avoids materializing the checked suffix).
349
- pub func ends_with = (ref self, view string suffix, out bool) {
349
+ pub func ends_with = (ref self {}, view string suffix, out bool) {
350
350
  unsafe {
351
351
  var int sl = suffix.length
352
352
  if sl > self.len {
@@ -365,7 +365,7 @@ pub struct StringBuilder {
365
365
 
366
366
  // Truncate the buffer to `new_len` bytes (clamped to [0, len]). Capacity
367
367
  // is kept, so a subsequent append reuses the storage without a realloc.
368
- pub func truncate = (ref self, int new_len) {
368
+ pub func truncate = (ref self {}, int new_len) {
369
369
  var int n = new_len
370
370
  if n < 0 {
371
371
  n = 0
@@ -378,7 +378,7 @@ pub struct StringBuilder {
378
378
 
379
379
  // Drop the last byte (a no-op when the buffer is empty). The common
380
380
  // chomp-the-trailing-separator shape.
381
- pub func chomp = (ref self) {
381
+ pub func chomp = (ref self {}) {
382
382
  if self.len > 0 {
383
383
  self.len = self.len - 1
384
384
  }
@@ -391,7 +391,7 @@ pub struct StringBuilder {
391
391
  // to [0, len]; the returned string is always an independent allocation.
392
392
  // (`mv out string` — the raw body mallocs the result, so the caller
393
393
  // owns it by signature, like `Console.read_line`.)
394
- pub func take_since = (ref self, int mark, mv out string) {
394
+ pub func take_since = (ref self {}, int mark, mv out string) {
395
395
  ```
396
396
  #arch: c
397
397
  int start = mark;
@@ -459,7 +459,7 @@ pub struct StringBuilder {
459
459
  // Explicitly `pub`: struct members default to pub, but this is the
460
460
  // builder's primary read-back — the contract should not depend on the
461
461
  // default.
462
- pub func to_string = (ref self, out string) {
462
+ pub func to_string = (ref self {}, out string) {
463
463
  ```
464
464
  #arch: c
465
465
  int idx = self->len;
@@ -23,8 +23,6 @@
23
23
  * Conforms to `Awaitable`: `.wait()` may park the current execution context.
24
24
  **/
25
25
  pub mv struct Task<T> : Awaitable {
26
- pub var uint64 handle = 0
27
- pub var done = false
28
26
  pub var uint64 result_slot = 0
29
27
  pub var uint64 cancel_flag = 0
30
28
  pub var uint64 future = 0
@@ -46,8 +44,6 @@ pub mv struct Task<T> : Awaitable {
46
44
  // names. Struct receivers travel by address regardless (the raw body
47
45
  // reads `self->future`), so the ABI is unchanged; the bare spelling is
48
46
  // what lets the read-only `Awaitable` dispatch form typecheck.
49
- // The legacy `pthread_join` fallback is gone — `handle` has been
50
- // permanently zero since the pool migration.
51
47
  pub func wait = (self) {
52
48
  ```
53
49
  #arch: c
@@ -58,7 +54,7 @@ pub mv struct Task<T> : Awaitable {
58
54
  ```
59
55
  #arch: aarch64
60
56
  // if (self->future) __nomen_future_wait(self->future)
61
- ldr x0, [x19, #40]
57
+ ldr x0, [x19, #24]
62
58
  cbz x0, .Lwait_done
63
59
  bl ___nomen_future_wait
64
60
  .Lwait_done:
@@ -71,18 +67,22 @@ pub mv struct Task<T> : Awaitable {
71
67
  // trampoline writes the function's return value there before exiting.
72
68
  // The result is MOVED OUT: the slot is zeroed as the value leaves, and
73
69
  // `mv out T` marks the caller as the owner. Call it once; a second call
74
- // returns the zero value. For tasks with no return value (void
75
- // functions), returns the zero value.
76
- pub func result = (ref self, mv out T) {
70
+ // returns the zero value. An empty handle (never launched, machinery
71
+ // already destroyed) owns no slot — it also returns the zero value
72
+ // rather than reading through a null pointer. For tasks with no return
73
+ // value (void functions), returns the zero value.
74
+ pub func result = (ref self {}, mv out T) {
77
75
  ```
78
76
  #arch: c
79
77
  if (self->future) {
80
78
  __nomen_future_wait((struct nomen_future *)self->future);
81
- } else if (self->handle && !self->done) {
82
- void *ret;
83
- pthread_join((pthread_t)self->handle, &ret);
84
- self->handle = 0;
85
- self->done = 1;
79
+ }
80
+ // An empty or already-consumed handle owns no result cell — return
81
+ // the zero value instead of reading through a null slot.
82
+ if (!self->result_slot) {
83
+ T _z;
84
+ memset(&_z, 0, sizeof(T));
85
+ return _z;
86
86
  }
87
87
  T _r = *(T *)self->result_slot;
88
88
  memset((void *)self->result_slot, 0, sizeof(T));
@@ -91,72 +91,64 @@ pub mv struct Task<T> : Awaitable {
91
91
  ```
92
92
  #arch: aarch64
93
93
  // Wait for completion (same as wait method)
94
- ldr x0, [x19, #40]
95
- cbz x0, .Lresult_handle
96
- bl ___nomen_future_wait
97
- b .Lresult_read
98
- .Lresult_handle:
99
- ldr x0, [x19, #8]
94
+ ldr x0, [x19, #24]
100
95
  cbz x0, .Lresult_read
101
- ldrb w1, [x19, #16]
102
- cbnz w1, .Lresult_read
103
- sub sp, sp, #16
104
- mov x1, sp
105
- bl _pthread_join
106
- add sp, sp, #16
107
- str xzr, [x19, #8]
108
- mov w0, #1
109
- strb w0, [x19, #16]
96
+ bl ___nomen_future_wait
110
97
  .Lresult_read:
98
+ // An empty or already-consumed handle owns no result cell: return
99
+ // the zero T instead of reading through a null slot.
100
+ ldr x8, [x19, #8]
101
+ cbz x8, .Lresult_zero
111
102
  // The result cell is always 16 bytes (see the spawn build phase):
112
103
  // load the full pair — a fat string returns (ptr, len) in x0/x1, a
113
104
  // scalar returns its word in x0 — then zero the cell (the value is
114
105
  // moved out; a second call observes the zero).
115
- ldr x8, [x19, #24]
116
106
  ldr x0, [x8]
117
107
  ldr x1, [x8, #8]
118
108
  stp xzr, xzr, [x8]
109
+ b .Lresult_end
110
+ .Lresult_zero:
111
+ mov x0, #0
112
+ mov x1, #0
113
+ .Lresult_end:
119
114
  ```
120
115
  }
121
116
 
122
117
  // Block until the task finishes, then return its result as a uint64.
123
118
  // Convenience for the common case; same as result() for uint64 tasks.
124
- pub func result_uint64 = (ref self, out uint64) {
119
+ // Like result(), it zeroes the cell as the value leaves (one end state
120
+ // for a consumed handle), and an empty handle returns zero.
121
+ pub func result_uint64 = (ref self {}, out uint64) {
125
122
  ```
126
123
  #arch: c
127
124
  if (self->future) {
128
125
  __nomen_future_wait((struct nomen_future *)self->future);
129
- } else if (self->handle && !self->done) {
130
- void *ret;
131
- pthread_join((pthread_t)self->handle, &ret);
132
- self->handle = 0;
133
- self->done = 1;
134
126
  }
135
- return *(unsigned long long *)self->result_slot;
127
+ if (!self->result_slot) {
128
+ return 0;
129
+ }
130
+ unsigned long long _r = *(unsigned long long *)self->result_slot;
131
+ *(unsigned long long *)self->result_slot = 0;
132
+ return _r;
136
133
  ```
137
134
  ```
138
135
  #arch: aarch64
139
136
  // Wait for completion
140
- ldr x0, [x19, #40]
141
- cbz x0, .Lru64_handle
142
- bl ___nomen_future_wait
143
- b .Lru64_read
144
- .Lru64_handle:
145
- ldr x0, [x19, #8]
137
+ ldr x0, [x19, #24]
146
138
  cbz x0, .Lru64_read
147
- ldrb w1, [x19, #16]
148
- cbnz w1, .Lru64_read
149
- sub sp, sp, #16
150
- mov x1, sp
151
- bl _pthread_join
152
- add sp, sp, #16
153
- str xzr, [x19, #8]
154
- mov w0, #1
155
- strb w0, [x19, #16]
139
+ bl ___nomen_future_wait
156
140
  .Lru64_read:
157
- // return *(unsigned long long *)self->result_slot
158
- ldr x0, [x19, #24]
159
- ldr x0, [x0]
141
+ // An empty or already-consumed handle owns no result cell: return
142
+ // zero instead of reading through a null slot. Otherwise zero the
143
+ // cell as the value leaves (matching result()'s end state).
144
+ ldr x8, [x19, #8]
145
+ cbz x8, .Lru64_zero
146
+ ldr x0, [x8]
147
+ str xzr, [x8]
148
+ b .Lru64_end
149
+ .Lru64_zero:
150
+ mov x0, #0
151
+ .Lru64_end:
160
152
  ```
161
153
  }
162
154
 
@@ -165,7 +157,7 @@ pub mv struct Task<T> : Awaitable {
165
157
  // handle whose machinery was already consumed). The missing peek
166
158
  // between wait (blocking) and cancel (cooperative): event loops use it
167
159
  // to notice a finished task without parking the UI thread.
168
- pub func is_done = (ref self, out bool) {
160
+ pub func is_done = (ref self {}, out bool) {
169
161
  ```
170
162
  #arch: c
171
163
  return __nomen_future_is_done((struct nomen_future *)self->future);
@@ -173,14 +165,14 @@ pub mv struct Task<T> : Awaitable {
173
165
  ```
174
166
  #arch: aarch64
175
167
  // x0 = self->future; result in x0.
176
- ldr x0, [x19, #40]
168
+ ldr x0, [x19, #24]
177
169
  bl ___nomen_future_is_done
178
170
  ```
179
171
  }
180
172
 
181
173
  // Request that the task stop. Cooperative — the task observes this via
182
174
  // `Task.current_cancelled()` at its own checkpoints. No preemption.
183
- pub func cancel = (ref self) {
175
+ pub func cancel = (ref self {}) {
184
176
  ```
185
177
  #arch: c
186
178
  // Sets the flag and wakes any fiber parked on this task's future, so
@@ -195,12 +187,12 @@ pub mv struct Task<T> : Awaitable {
195
187
  #arch: aarch64
196
188
  // if (self->future) __nomen_future_cancel(self->future);
197
189
  // else if (self->cancel_flag) *(self->cancel_flag) = 1
198
- ldr x0, [x19, #40]
190
+ ldr x0, [x19, #24]
199
191
  cbz x0, .Lcancel_flag_path
200
192
  bl ___nomen_future_cancel
201
193
  b .Lcancel_done
202
194
  .Lcancel_flag_path:
203
- ldr x0, [x19, #32]
195
+ ldr x0, [x19, #16]
204
196
  cbz x0, .Lcancel_done
205
197
  mov x1, #1
206
198
  str x1, [x0]
@@ -393,12 +385,12 @@ pub mv struct Task<T> : Awaitable {
393
385
  ```
394
386
  #arch: aarch64
395
387
  // if (self->future) { free an unconsumed string result; release; zero fields }
396
- ldr x0, [x19, #40]
388
+ ldr x0, [x19, #24]
397
389
  cbz x0, .Ldestroy_done
398
390
  // An unconsumed string result: the cell still holds (ptr, len) —
399
391
  // result() zeroes it when it moves the value out. The T_FAT dispatch
400
392
  // folds to a constant branch after monomorphization.
401
- ldr x8, [x19, #24]
393
+ ldr x8, [x19, #8]
402
394
  mov x0, #T_FAT
403
395
  cmp x0, #0
404
396
  b.eq .Ldestroy_nofree
@@ -411,11 +403,11 @@ pub mv struct Task<T> : Awaitable {
411
403
  stp xzr, xzr, [x8]
412
404
  bl _free
413
405
  .Ldestroy_nofree:
414
- ldr x0, [x19, #40]
406
+ ldr x0, [x19, #24]
415
407
  bl ___nomen_future_release
416
- str xzr, [x19, #40]
417
408
  str xzr, [x19, #24]
418
- str xzr, [x19, #32]
409
+ str xzr, [x19, #8]
410
+ str xzr, [x19, #16]
419
411
  .Ldestroy_done:
420
412
  ```
421
413
  }