nomen-lang 0.8.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/audit_runtime.c +12 -2
- package/core/System/Arena.nm +14 -5
- 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 +392 -33
- package/core/System/ClassBuffer.nm +145 -13
- package/core/System/Controls/Alert.nm +3 -3
- package/core/System/Controls/App.nm +17 -17
- package/core/System/Controls/Button.nm +2 -2
- package/core/System/Controls/CheckBox.nm +3 -3
- package/core/System/Controls/ColorPicker.nm +2 -2
- package/core/System/Controls/ComboBox.nm +2 -2
- package/core/System/Controls/Container.nm +39 -33
- package/core/System/Controls/DatePicker.nm +1 -1
- package/core/System/Controls/Form.nm +2 -2
- package/core/System/Controls/GroupBox.nm +2 -2
- package/core/System/Controls/ImageView.nm +2 -2
- package/core/System/Controls/Layout.nm +5 -5
- package/core/System/Controls/LevelIndicator.nm +2 -2
- package/core/System/Controls/ListView.nm +2 -2
- package/core/System/Controls/Menu.nm +2 -2
- package/core/System/Controls/NumberInput.nm +3 -3
- package/core/System/Controls/OtpInput.nm +2 -2
- package/core/System/Controls/OutlineView.nm +2 -2
- package/core/System/Controls/Pagination.nm +14 -14
- package/core/System/Controls/Popover.nm +2 -2
- package/core/System/Controls/Progress.nm +2 -2
- package/core/System/Controls/Radio.nm +3 -3
- package/core/System/Controls/Scrollable.nm +1 -1
- package/core/System/Controls/SearchField.nm +2 -2
- package/core/System/Controls/SecureField.nm +2 -2
- package/core/System/Controls/Segmented.nm +2 -2
- package/core/System/Controls/Select.nm +2 -2
- package/core/System/Controls/Separator.nm +2 -2
- package/core/System/Controls/Sheet.nm +2 -2
- package/core/System/Controls/Slider.nm +2 -2
- package/core/System/Controls/Spinner.nm +5 -5
- package/core/System/Controls/SplitView.nm +3 -3
- package/core/System/Controls/Stepper.nm +2 -2
- package/core/System/Controls/Switch.nm +2 -2
- package/core/System/Controls/Table.nm +2 -2
- package/core/System/Controls/Tabs.nm +2 -2
- package/core/System/Controls/Text.nm +2 -2
- package/core/System/Controls/TextBox.nm +3 -3
- package/core/System/Controls/TextView.nm +2 -2
- package/core/System/Controls/Toggle.nm +3 -3
- package/core/System/Controls/Toolbar.nm +2 -2
- package/core/System/Controls/Window.nm +12 -5
- package/core/System/Fiber.nm +16 -3
- package/core/System/Graph.nm +2 -2
- package/core/System/LinkedList.nm +13 -4
- package/core/System/List.nm +76 -17
- package/core/System/Map.nm +179 -21
- package/core/System/Mutex.nm +4 -4
- package/core/System/Random.nm +6 -7
- package/core/System/Set.nm +99 -23
- package/core/System/StableList.nm +371 -0
- package/core/System/Stream/Directory.nm +2 -2
- package/core/System/Stream/File.nm +18 -18
- package/core/System/Stream/Http.nm +5 -5
- package/core/System/Stream/Tcp.nm +5 -5
- package/core/System/String.nm +10 -5
- package/core/System/StringBuilder.nm +223 -12
- package/core/System/Task.nm +56 -64
- package/core/System/Test.nm +18 -18
- package/core/System/Text/CharIndex.nm +9 -9
- package/core/System/Text/Chars.nm +1 -1
- package/core/System/Text/Json.nm +72 -58
- package/core/System/Text/JsonTree.nm +126 -98
- package/core/System/Text/Regex.nm +43 -38
- package/core/System/Text/Utf8.nm +5 -5
- package/core/System/Thread.nm +26 -3
- package/core/System/Tree.nm +19 -3
- package/core/System/float.nm +36 -22
- package/core/System/int.nm +80 -28
- package/core/System/int16.nm +11 -0
- package/core/System/int32.nm +11 -0
- package/core/System/int64.nm +11 -0
- package/core/System/int8.nm +11 -0
- package/core/System/uint.nm +11 -0
- package/core/System/uint16.nm +11 -0
- package/core/System/uint32.nm +11 -0
- package/core/System/uint64.nm +11 -0
- package/core/System/uint8.nm +11 -0
- package/core/docs/System/StringBuilder.md +6 -0
- package/core/docs/System/Text/JsonTree.md +3 -2
- package/dist/index.mjs +37622 -30603
- package/package.json +1 -1
- package/src/bench_loop.nm +9 -9
|
@@ -57,13 +57,13 @@ pub struct File {
|
|
|
57
57
|
return FileError.already_exists
|
|
58
58
|
}
|
|
59
59
|
} else {
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
return FileError.other
|
|
61
|
+
}
|
|
62
62
|
}
|
|
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)
|
|
@@ -49,8 +49,8 @@ pub struct Http {
|
|
|
49
49
|
return HttpError.connect
|
|
50
50
|
}
|
|
51
51
|
} else {
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
return HttpError.other
|
|
53
|
+
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Shared socket round-trip used by get/post. `method` is the request
|
|
@@ -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
|
|
package/core/System/String.nm
CHANGED
|
@@ -276,21 +276,26 @@ pub mv struct string: Stringable, Hashable, Equatable {
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
// Replace all non-overlapping occurrences of needle with replacement,
|
|
279
|
-
// left to right. Same edge behavior as replace_first.
|
|
279
|
+
// left to right. Same edge behavior as replace_first. Literal bytes
|
|
280
|
+
// between matches are copied in bulk runs (one `append_string_view` per
|
|
281
|
+
// run) — the old loop appended per byte.
|
|
280
282
|
pub func replace_all = (self, view string needle, view string replacement, out string) {
|
|
281
283
|
var sb = StringBuilder()
|
|
282
284
|
var i = 0
|
|
283
285
|
var int n = self.length
|
|
284
286
|
var int nlen = needle.length
|
|
285
|
-
|
|
286
|
-
|
|
287
|
+
var run_start = 0
|
|
288
|
+
while nlen > 0 && i + nlen <= n {
|
|
289
|
+
if match_at(self, needle, i) {
|
|
290
|
+
sb.append_string_view(self.slice(run_start, i))
|
|
287
291
|
sb.append_string_view(replacement)
|
|
288
292
|
i = i + nlen
|
|
293
|
+
run_start = i
|
|
289
294
|
} else {
|
|
290
|
-
|
|
291
|
-
i = i + 1
|
|
295
|
+
i += 1
|
|
292
296
|
}
|
|
293
297
|
}
|
|
298
|
+
sb.append_string_view(self.slice(run_start, n))
|
|
294
299
|
return sb.to_string()
|
|
295
300
|
}
|
|
296
301
|
|
|
@@ -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;
|
|
@@ -83,13 +83,224 @@ pub struct StringBuilder {
|
|
|
83
83
|
```
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
// Append a
|
|
86
|
+
// Append a base-10 integer WITHOUT materializing a string: the digits are
|
|
87
|
+
// written straight into the buffer (one capacity check, no malloc and no
|
|
88
|
+
// snprintf). The `sb.append(i.to_string())` shape's two snprintf passes
|
|
89
|
+
// plus the intermediate string's malloc/free collapse to a few
|
|
90
|
+
// instructions against the buffer. The raw body is spliced per call site
|
|
91
|
+
// (labels renamed by the splicer), so the digit loop is truly inline.
|
|
92
|
+
pub inline func append_int = (ref self {}, int n) {
|
|
93
|
+
```
|
|
94
|
+
#arch: c
|
|
95
|
+
long v = n;
|
|
96
|
+
char tmp[24];
|
|
97
|
+
int pos = 24;
|
|
98
|
+
// Magnitude via the two's-complement negate (u stays correct for
|
|
99
|
+
// INT64_MIN, whose positive counterpart is not representable).
|
|
100
|
+
unsigned long long u = v < 0 ? (unsigned long long)(-(v + 1)) + 1ULL : (unsigned long long)v;
|
|
101
|
+
do {
|
|
102
|
+
tmp[--pos] = (char)('0' + (int)(u % 10));
|
|
103
|
+
u /= 10;
|
|
104
|
+
} while (u != 0);
|
|
105
|
+
if (v < 0) tmp[--pos] = '-';
|
|
106
|
+
long sl = 24 - pos;
|
|
107
|
+
long idx = self->len;
|
|
108
|
+
if (idx + sl + 1 > self->cap) {
|
|
109
|
+
long nc = self->cap;
|
|
110
|
+
if (nc == 0) nc = 16;
|
|
111
|
+
while (nc < idx + sl + 1) nc *= 2;
|
|
112
|
+
self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, nc);
|
|
113
|
+
self->cap = nc;
|
|
114
|
+
}
|
|
115
|
+
memcpy((void*)((unsigned long long)self->data + (unsigned long long)idx), tmp + pos, (size_t)sl);
|
|
116
|
+
self->len = idx + sl;
|
|
117
|
+
```
|
|
118
|
+
```
|
|
119
|
+
#arch: aarch64
|
|
120
|
+
// x19 = self, x1 = n. Format into a 24-byte scratch at [sp+40..64)
|
|
121
|
+
// (20 chars for INT64_MIN), then copy into the buffer
|
|
122
|
+
// (capacity-checked inline, like append_char). Saves live below the
|
|
123
|
+
// scratch: [sp]=pos, [sp+8]=sl, [sp+16]=idx, [sp+24]=new_cap.
|
|
124
|
+
sub sp, sp, #64
|
|
125
|
+
mov x9, x1 // v = n
|
|
126
|
+
mov x10, x9
|
|
127
|
+
cmp x9, #0
|
|
128
|
+
b.ge .Lsb_ai_pos
|
|
129
|
+
neg x10, x10 // magnitude (wraps correctly for INT64_MIN)
|
|
130
|
+
.Lsb_ai_pos:
|
|
131
|
+
add x11, sp, #64 // pos = end of scratch
|
|
132
|
+
mov x12, x11
|
|
133
|
+
.Lsb_ai_digit:
|
|
134
|
+
mov x13, #10
|
|
135
|
+
udiv x14, x10, x13
|
|
136
|
+
msub x15, x14, x13, x10 // rem = v - q*10
|
|
137
|
+
add x15, x15, #48
|
|
138
|
+
sub x12, x12, #1
|
|
139
|
+
strb w15, [x12]
|
|
140
|
+
mov x10, x14
|
|
141
|
+
cbnz x10, .Lsb_ai_digit
|
|
142
|
+
cmp x9, #0
|
|
143
|
+
b.ge .Lsb_ai_store
|
|
144
|
+
sub x12, x12, #1
|
|
145
|
+
mov w15, #45 // '-'
|
|
146
|
+
strb w15, [x12]
|
|
147
|
+
.Lsb_ai_store:
|
|
148
|
+
sub x1, x11, x12 // sl = end - pos
|
|
149
|
+
ldr x2, [x19, #16] // len
|
|
150
|
+
add x3, x2, x1
|
|
151
|
+
add x3, x3, #1 // needed
|
|
152
|
+
ldr x4, [x19, #24] // cap
|
|
153
|
+
cmp x4, x3
|
|
154
|
+
b.ge .Lsb_ai_copy
|
|
155
|
+
mov x5, #16
|
|
156
|
+
cmp x4, #0
|
|
157
|
+
csel x5, x5, x4, eq
|
|
158
|
+
.Lsb_ai_grow:
|
|
159
|
+
cmp x5, x3
|
|
160
|
+
b.ge .Lsb_ai_realloc
|
|
161
|
+
lsl x5, x5, #1
|
|
162
|
+
b .Lsb_ai_grow
|
|
163
|
+
.Lsb_ai_realloc:
|
|
164
|
+
str x12, [sp, #0] // pos
|
|
165
|
+
str x1, [sp, #8] // sl
|
|
166
|
+
str x2, [sp, #16] // idx
|
|
167
|
+
str x5, [sp, #24] // new_cap
|
|
168
|
+
ldr x0, [x19, #8]
|
|
169
|
+
mov x1, x5
|
|
170
|
+
bl _realloc
|
|
171
|
+
str x0, [x19, #8]
|
|
172
|
+
ldr x5, [sp, #24]
|
|
173
|
+
str x5, [x19, #24]
|
|
174
|
+
ldr x12, [sp, #0]
|
|
175
|
+
ldr x1, [sp, #8]
|
|
176
|
+
ldr x2, [sp, #16]
|
|
177
|
+
.Lsb_ai_copy:
|
|
178
|
+
ldr x0, [x19, #8] // data
|
|
179
|
+
add x0, x0, x2 // dst = data + idx
|
|
180
|
+
mov x3, x1
|
|
181
|
+
.Lsb_ai_cl:
|
|
182
|
+
cbz x3, .Lsb_ai_done
|
|
183
|
+
ldrb w4, [x12]
|
|
184
|
+
strb w4, [x0]
|
|
185
|
+
add x12, x12, #1
|
|
186
|
+
add x0, x0, #1
|
|
187
|
+
sub x3, x3, #1
|
|
188
|
+
b .Lsb_ai_cl
|
|
189
|
+
.Lsb_ai_done:
|
|
190
|
+
add x2, x2, x1 // len += sl
|
|
191
|
+
str x2, [x19, #16]
|
|
192
|
+
add sp, sp, #64
|
|
193
|
+
```
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Append a float with the SAME text `float.to_string` produces ("%f"):
|
|
197
|
+
// one snprintf into a stack scratch, then a bulk copy into the buffer —
|
|
198
|
+
// no sizing pass and no intermediate string allocation.
|
|
199
|
+
pub inline func append_float = (ref self {}, float f) {
|
|
200
|
+
```
|
|
201
|
+
#arch: c
|
|
202
|
+
char tmp[360];
|
|
203
|
+
int sl = snprintf(tmp, sizeof(tmp), "%f", f);
|
|
204
|
+
long idx = self->len;
|
|
205
|
+
if (idx + sl + 1 > self->cap) {
|
|
206
|
+
long nc = self->cap;
|
|
207
|
+
if (nc == 0) nc = 16;
|
|
208
|
+
while (nc < idx + sl + 1) nc *= 2;
|
|
209
|
+
self->data = (unsigned long long)realloc((void*)(unsigned long long)self->data, nc);
|
|
210
|
+
self->cap = nc;
|
|
211
|
+
}
|
|
212
|
+
memcpy((void*)((unsigned long long)self->data + (unsigned long long)idx), tmp, (size_t)sl);
|
|
213
|
+
self->len = idx + sl;
|
|
214
|
+
```
|
|
215
|
+
```
|
|
216
|
+
#arch: aarch64
|
|
217
|
+
// x19 = self, x1 = f (raw bits — float params ride integer
|
|
218
|
+
// registers). Scratch [sp+16..sp+376); [sp+0] is snprintf's
|
|
219
|
+
// variadic slot, reused after the call for `sl`; [sp+8] = idx across
|
|
220
|
+
// the grow call; [sp+376] = new_cap.
|
|
221
|
+
sub sp, sp, #384
|
|
222
|
+
fmov d0, x1 // f bits (capture before x1 is reused)
|
|
223
|
+
str d0, [sp, #0] // variadic double slot
|
|
224
|
+
add x0, sp, #16
|
|
225
|
+
mov x1, #360
|
|
226
|
+
adr x2, .Lsb_af_fmt
|
|
227
|
+
bl _snprintf
|
|
228
|
+
str x0, [sp, #0] // sl
|
|
229
|
+
ldr x2, [x19, #16] // idx = len
|
|
230
|
+
add x3, x2, x0
|
|
231
|
+
add x3, x3, #1 // needed
|
|
232
|
+
ldr x4, [x19, #24] // cap
|
|
233
|
+
cmp x4, x3
|
|
234
|
+
b.ge .Lsb_af_copy
|
|
235
|
+
mov x5, #16
|
|
236
|
+
cmp x4, #0
|
|
237
|
+
csel x5, x5, x4, eq
|
|
238
|
+
.Lsb_af_grow:
|
|
239
|
+
cmp x5, x3
|
|
240
|
+
b.ge .Lsb_af_realloc
|
|
241
|
+
lsl x5, x5, #1
|
|
242
|
+
b .Lsb_af_grow
|
|
243
|
+
.Lsb_af_realloc:
|
|
244
|
+
str x2, [sp, #8] // idx
|
|
245
|
+
str x5, [sp, #376] // new_cap (above the scratch)
|
|
246
|
+
ldr x0, [x19, #8]
|
|
247
|
+
mov x1, x5
|
|
248
|
+
bl _realloc
|
|
249
|
+
str x0, [x19, #8]
|
|
250
|
+
ldr x5, [sp, #376]
|
|
251
|
+
str x5, [x19, #24]
|
|
252
|
+
ldr x2, [sp, #8]
|
|
253
|
+
.Lsb_af_copy:
|
|
254
|
+
ldr x0, [x19, #8] // data
|
|
255
|
+
add x0, x0, x2 // dst = data + idx
|
|
256
|
+
add x4, sp, #16 // src = scratch
|
|
257
|
+
ldr x1, [sp, #0] // sl
|
|
258
|
+
mov x3, x1
|
|
259
|
+
.Lsb_af_cl:
|
|
260
|
+
cbz x3, .Lsb_af_done
|
|
261
|
+
ldrb w5, [x4]
|
|
262
|
+
strb w5, [x0]
|
|
263
|
+
add x4, x4, #1
|
|
264
|
+
add x0, x0, #1
|
|
265
|
+
sub x3, x3, #1
|
|
266
|
+
b .Lsb_af_cl
|
|
267
|
+
.Lsb_af_done:
|
|
268
|
+
add x2, x2, x1 // len += sl
|
|
269
|
+
str x2, [x19, #16]
|
|
270
|
+
add sp, sp, #384
|
|
271
|
+
b .Lsb_af_after
|
|
272
|
+
.Lsb_af_fmt: .asciz "%f"
|
|
273
|
+
.p2align 2
|
|
274
|
+
.Lsb_af_after:
|
|
275
|
+
```
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Append a borrowed view without materializing it.
|
|
279
|
+
pub func append = (ref self {}, view string s) {
|
|
280
|
+
self.append_string_view(s)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Append an int without materializing a string (see `append_int`).
|
|
284
|
+
pub func append = (ref self {}, int n) {
|
|
285
|
+
self.append_int(n)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Append a float without materializing a string (see `append_float`).
|
|
289
|
+
pub func append = (ref self {}, float f) {
|
|
290
|
+
self.append_float(f)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Append a single byte. (Overload, so `sb.append(c)` works for chars.)
|
|
294
|
+
pub func append = (ref self {}, char c) {
|
|
295
|
+
self.append_char(c)
|
|
296
|
+
}
|
|
297
|
+
|
|
87
298
|
// both backends: the fat pair's pointer half feeds memcpy directly, and
|
|
88
299
|
// the tracked length replaces the strlen the old C body paid.
|
|
89
300
|
// `internal`: a library-implementation append — user code appends with
|
|
90
301
|
// `append_char` / `append_string_view`; the library's own structs (Json,
|
|
91
302
|
// Regex) are on the trusted side of the boundary.
|
|
92
|
-
internal func append_string = (ref self, string s) {
|
|
303
|
+
internal func append_string = (ref self {}, string s) {
|
|
93
304
|
unsafe {
|
|
94
305
|
var int sl = s.length
|
|
95
306
|
self.ensure(self.len + sl + 1)
|
|
@@ -103,7 +314,7 @@ pub struct StringBuilder {
|
|
|
103
314
|
// call. Views lower to the same (ptr, len) fat pair, so the bytes are
|
|
104
315
|
// memcpy'd straight out of the borrowed buffer (used by
|
|
105
316
|
// `string.replace_first`/`replace_all`).
|
|
106
|
-
pub func append_string_view = (ref self, view string s) {
|
|
317
|
+
pub func append_string_view = (ref self {}, view string s) {
|
|
107
318
|
unsafe {
|
|
108
319
|
var int sl = s.length
|
|
109
320
|
self.ensure(self.len + sl + 1)
|
|
@@ -116,7 +327,7 @@ pub struct StringBuilder {
|
|
|
116
327
|
// way to start a StringBuilder from a slice without a `to_string()`
|
|
117
328
|
// copy: the view's bytes are copied once into fresh storage, so the
|
|
118
329
|
// result is owned and independent of the source.
|
|
119
|
-
pub func seed = (ref self, view string s) {
|
|
330
|
+
pub func seed = (ref self {}, view string s) {
|
|
120
331
|
unsafe {
|
|
121
332
|
var int sl = s.length
|
|
122
333
|
self.ensure(sl + 1)
|
|
@@ -135,14 +346,14 @@ pub struct StringBuilder {
|
|
|
135
346
|
// Whether the buffer's current bytes end with `suffix` (an empty suffix
|
|
136
347
|
// is always true). Reads the buffer tail in place — no copy of either
|
|
137
348
|
// side (`view string` avoids materializing the checked suffix).
|
|
138
|
-
pub func ends_with = (ref self, view string suffix, out bool) {
|
|
349
|
+
pub func ends_with = (ref self {}, view string suffix, out bool) {
|
|
139
350
|
unsafe {
|
|
140
351
|
var int sl = suffix.length
|
|
141
352
|
if sl > self.len {
|
|
142
353
|
return false
|
|
143
354
|
}
|
|
144
355
|
var int start = self.len - sl
|
|
145
|
-
var
|
|
356
|
+
var i = 0
|
|
146
357
|
while i < sl; i += 1 {
|
|
147
358
|
if (self.data as ptr char)[start + i] != (suffix as ptr char)[i] {
|
|
148
359
|
return false
|
|
@@ -154,7 +365,7 @@ pub struct StringBuilder {
|
|
|
154
365
|
|
|
155
366
|
// Truncate the buffer to `new_len` bytes (clamped to [0, len]). Capacity
|
|
156
367
|
// is kept, so a subsequent append reuses the storage without a realloc.
|
|
157
|
-
pub func truncate = (ref self, int new_len) {
|
|
368
|
+
pub func truncate = (ref self {}, int new_len) {
|
|
158
369
|
var int n = new_len
|
|
159
370
|
if n < 0 {
|
|
160
371
|
n = 0
|
|
@@ -167,7 +378,7 @@ pub struct StringBuilder {
|
|
|
167
378
|
|
|
168
379
|
// Drop the last byte (a no-op when the buffer is empty). The common
|
|
169
380
|
// chomp-the-trailing-separator shape.
|
|
170
|
-
pub func chomp = (ref self) {
|
|
381
|
+
pub func chomp = (ref self {}) {
|
|
171
382
|
if self.len > 0 {
|
|
172
383
|
self.len = self.len - 1
|
|
173
384
|
}
|
|
@@ -180,7 +391,7 @@ pub struct StringBuilder {
|
|
|
180
391
|
// to [0, len]; the returned string is always an independent allocation.
|
|
181
392
|
// (`mv out string` — the raw body mallocs the result, so the caller
|
|
182
393
|
// owns it by signature, like `Console.read_line`.)
|
|
183
|
-
pub func take_since = (ref self, int mark, mv out string) {
|
|
394
|
+
pub func take_since = (ref self {}, int mark, mv out string) {
|
|
184
395
|
```
|
|
185
396
|
#arch: c
|
|
186
397
|
int start = mark;
|
|
@@ -248,7 +459,7 @@ pub struct StringBuilder {
|
|
|
248
459
|
// Explicitly `pub`: struct members default to pub, but this is the
|
|
249
460
|
// builder's primary read-back — the contract should not depend on the
|
|
250
461
|
// default.
|
|
251
|
-
pub func to_string = (ref self, out string) {
|
|
462
|
+
pub func to_string = (ref self {}, out string) {
|
|
252
463
|
```
|
|
253
464
|
#arch: c
|
|
254
465
|
int idx = self->len;
|