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.
- package/core/System/Arena.nm +9 -7
- package/core/System/Array.nm +1 -1
- package/core/System/Atomic.nm +3 -3
- package/core/System/BigInt.nm +182 -23
- package/core/System/Buffer.nm +37 -35
- package/core/System/ClassBuffer.nm +18 -18
- package/core/System/Controls/Alert.nm +1 -1
- package/core/System/Controls/App.nm +5 -5
- package/core/System/Controls/Button.nm +1 -1
- package/core/System/Controls/CheckBox.nm +1 -1
- package/core/System/Controls/ColorPicker.nm +1 -1
- package/core/System/Controls/ComboBox.nm +1 -1
- package/core/System/Controls/Container.nm +34 -34
- package/core/System/Controls/DatePicker.nm +1 -1
- package/core/System/Controls/Form.nm +2 -2
- package/core/System/Controls/GroupBox.nm +1 -1
- package/core/System/Controls/ImageView.nm +1 -1
- package/core/System/Controls/Layout.nm +5 -5
- package/core/System/Controls/LevelIndicator.nm +1 -1
- package/core/System/Controls/ListView.nm +1 -1
- package/core/System/Controls/Menu.nm +1 -1
- package/core/System/Controls/NumberInput.nm +3 -3
- package/core/System/Controls/OtpInput.nm +2 -2
- package/core/System/Controls/OutlineView.nm +1 -1
- package/core/System/Controls/Pagination.nm +6 -6
- package/core/System/Controls/Popover.nm +1 -1
- package/core/System/Controls/Progress.nm +1 -1
- package/core/System/Controls/Radio.nm +1 -1
- package/core/System/Controls/Scrollable.nm +1 -1
- package/core/System/Controls/SearchField.nm +1 -1
- package/core/System/Controls/SecureField.nm +1 -1
- package/core/System/Controls/Segmented.nm +1 -1
- package/core/System/Controls/Select.nm +1 -1
- package/core/System/Controls/Separator.nm +1 -1
- package/core/System/Controls/Sheet.nm +1 -1
- package/core/System/Controls/Slider.nm +1 -1
- package/core/System/Controls/Spinner.nm +3 -3
- package/core/System/Controls/SplitView.nm +2 -2
- package/core/System/Controls/Stepper.nm +1 -1
- package/core/System/Controls/Switch.nm +1 -1
- package/core/System/Controls/Table.nm +1 -1
- package/core/System/Controls/Tabs.nm +1 -1
- package/core/System/Controls/Text.nm +1 -1
- package/core/System/Controls/TextBox.nm +1 -1
- package/core/System/Controls/TextView.nm +1 -1
- package/core/System/Controls/Toggle.nm +1 -1
- package/core/System/Controls/Toolbar.nm +1 -1
- package/core/System/Controls/Window.nm +11 -3
- package/core/System/Fiber.nm +16 -3
- package/core/System/Graph.nm +2 -2
- package/core/System/LinkedList.nm +8 -6
- package/core/System/List.nm +16 -13
- package/core/System/Map.nm +11 -9
- package/core/System/Random.nm +3 -3
- package/core/System/Set.nm +9 -7
- package/core/System/StableList.nm +7 -7
- package/core/System/Stream/File.nm +16 -16
- package/core/System/Stream/Http.nm +3 -3
- package/core/System/Stream/Tcp.nm +5 -5
- package/core/System/StringBuilder.nm +16 -16
- package/core/System/Task.nm +56 -64
- package/core/System/Test.nm +18 -18
- package/core/System/Text/Chars.nm +1 -1
- package/core/System/Text/Json.nm +12 -12
- package/core/System/Text/JsonTree.nm +8 -8
- package/core/System/Text/Regex.nm +20 -20
- package/core/System/Thread.nm +26 -3
- package/core/System/Tree.nm +19 -3
- package/dist/index.mjs +3036 -1845
- 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;
|
package/core/System/Task.nm
CHANGED
|
@@ -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, #
|
|
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.
|
|
75
|
-
//
|
|
76
|
-
|
|
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
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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, #
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, #
|
|
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
|
-
|
|
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
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
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, #
|
|
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, #
|
|
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, #
|
|
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, #
|
|
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, #
|
|
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, #
|
|
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, #
|
|
409
|
+
str xzr, [x19, #8]
|
|
410
|
+
str xzr, [x19, #16]
|
|
419
411
|
.Ldestroy_done:
|
|
420
412
|
```
|
|
421
413
|
}
|