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.
Files changed (90) hide show
  1. package/audit_runtime.c +12 -2
  2. package/core/System/Arena.nm +14 -5
  3. package/core/System/Array.nm +1 -1
  4. package/core/System/Atomic.nm +3 -3
  5. package/core/System/BigInt.nm +182 -23
  6. package/core/System/Buffer.nm +392 -33
  7. package/core/System/ClassBuffer.nm +145 -13
  8. package/core/System/Controls/Alert.nm +3 -3
  9. package/core/System/Controls/App.nm +17 -17
  10. package/core/System/Controls/Button.nm +2 -2
  11. package/core/System/Controls/CheckBox.nm +3 -3
  12. package/core/System/Controls/ColorPicker.nm +2 -2
  13. package/core/System/Controls/ComboBox.nm +2 -2
  14. package/core/System/Controls/Container.nm +39 -33
  15. package/core/System/Controls/DatePicker.nm +1 -1
  16. package/core/System/Controls/Form.nm +2 -2
  17. package/core/System/Controls/GroupBox.nm +2 -2
  18. package/core/System/Controls/ImageView.nm +2 -2
  19. package/core/System/Controls/Layout.nm +5 -5
  20. package/core/System/Controls/LevelIndicator.nm +2 -2
  21. package/core/System/Controls/ListView.nm +2 -2
  22. package/core/System/Controls/Menu.nm +2 -2
  23. package/core/System/Controls/NumberInput.nm +3 -3
  24. package/core/System/Controls/OtpInput.nm +2 -2
  25. package/core/System/Controls/OutlineView.nm +2 -2
  26. package/core/System/Controls/Pagination.nm +14 -14
  27. package/core/System/Controls/Popover.nm +2 -2
  28. package/core/System/Controls/Progress.nm +2 -2
  29. package/core/System/Controls/Radio.nm +3 -3
  30. package/core/System/Controls/Scrollable.nm +1 -1
  31. package/core/System/Controls/SearchField.nm +2 -2
  32. package/core/System/Controls/SecureField.nm +2 -2
  33. package/core/System/Controls/Segmented.nm +2 -2
  34. package/core/System/Controls/Select.nm +2 -2
  35. package/core/System/Controls/Separator.nm +2 -2
  36. package/core/System/Controls/Sheet.nm +2 -2
  37. package/core/System/Controls/Slider.nm +2 -2
  38. package/core/System/Controls/Spinner.nm +5 -5
  39. package/core/System/Controls/SplitView.nm +3 -3
  40. package/core/System/Controls/Stepper.nm +2 -2
  41. package/core/System/Controls/Switch.nm +2 -2
  42. package/core/System/Controls/Table.nm +2 -2
  43. package/core/System/Controls/Tabs.nm +2 -2
  44. package/core/System/Controls/Text.nm +2 -2
  45. package/core/System/Controls/TextBox.nm +3 -3
  46. package/core/System/Controls/TextView.nm +2 -2
  47. package/core/System/Controls/Toggle.nm +3 -3
  48. package/core/System/Controls/Toolbar.nm +2 -2
  49. package/core/System/Controls/Window.nm +12 -5
  50. package/core/System/Fiber.nm +16 -3
  51. package/core/System/Graph.nm +2 -2
  52. package/core/System/LinkedList.nm +13 -4
  53. package/core/System/List.nm +76 -17
  54. package/core/System/Map.nm +179 -21
  55. package/core/System/Mutex.nm +4 -4
  56. package/core/System/Random.nm +6 -7
  57. package/core/System/Set.nm +99 -23
  58. package/core/System/StableList.nm +371 -0
  59. package/core/System/Stream/Directory.nm +2 -2
  60. package/core/System/Stream/File.nm +18 -18
  61. package/core/System/Stream/Http.nm +5 -5
  62. package/core/System/Stream/Tcp.nm +5 -5
  63. package/core/System/String.nm +10 -5
  64. package/core/System/StringBuilder.nm +223 -12
  65. package/core/System/Task.nm +56 -64
  66. package/core/System/Test.nm +18 -18
  67. package/core/System/Text/CharIndex.nm +9 -9
  68. package/core/System/Text/Chars.nm +1 -1
  69. package/core/System/Text/Json.nm +72 -58
  70. package/core/System/Text/JsonTree.nm +126 -98
  71. package/core/System/Text/Regex.nm +43 -38
  72. package/core/System/Text/Utf8.nm +5 -5
  73. package/core/System/Thread.nm +26 -3
  74. package/core/System/Tree.nm +19 -3
  75. package/core/System/float.nm +36 -22
  76. package/core/System/int.nm +80 -28
  77. package/core/System/int16.nm +11 -0
  78. package/core/System/int32.nm +11 -0
  79. package/core/System/int64.nm +11 -0
  80. package/core/System/int8.nm +11 -0
  81. package/core/System/uint.nm +11 -0
  82. package/core/System/uint16.nm +11 -0
  83. package/core/System/uint32.nm +11 -0
  84. package/core/System/uint64.nm +11 -0
  85. package/core/System/uint8.nm +11 -0
  86. package/core/docs/System/StringBuilder.md +6 -0
  87. package/core/docs/System/Text/JsonTree.md +3 -2
  88. package/dist/index.mjs +37622 -30603
  89. package/package.json +1 -1
  90. 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
- return FileError.other
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
- return HttpError.other
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
 
@@ -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
- while i < n {
286
- if nlen > 0 && i + nlen <= n && match_at(self, needle, i) {
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
- sb.append_char(self.at(i))
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 null-terminated string. `unsafe` Nomen single-sourced for
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 int i = 0
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;