nomen-lang 0.9.0 → 0.11.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 (72) 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/Format.nm +751 -0
  51. package/core/System/Graph.nm +2 -2
  52. package/core/System/LinkedList.nm +8 -6
  53. package/core/System/List.nm +16 -13
  54. package/core/System/Map.nm +11 -9
  55. package/core/System/Random.nm +3 -3
  56. package/core/System/Set.nm +9 -7
  57. package/core/System/StableList.nm +7 -7
  58. package/core/System/Stream/File.nm +16 -16
  59. package/core/System/Stream/Http.nm +3 -3
  60. package/core/System/Stream/Tcp.nm +5 -5
  61. package/core/System/StringBuilder.nm +16 -16
  62. package/core/System/Task.nm +56 -64
  63. package/core/System/Test.nm +18 -18
  64. package/core/System/Text/Chars.nm +1 -1
  65. package/core/System/Text/Json.nm +12 -12
  66. package/core/System/Text/JsonTree.nm +8 -8
  67. package/core/System/Text/Regex.nm +20 -20
  68. package/core/System/Thread.nm +26 -3
  69. package/core/System/Tree.nm +19 -3
  70. package/dist/index.mjs +3423 -1849
  71. package/package.json +1 -1
  72. package/src/docs.ts +10 -1
@@ -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
  }
@@ -96,7 +96,7 @@ pub mv struct Tester {
96
96
 
97
97
  // (harness) Start timing `name` and clear the per-test state. Called by
98
98
  // the `main` that `nomen test` generates — not by test code.
99
- pub func begin_test = (ref self, string name) {
99
+ pub func begin_test = (ref self { current }, string name) {
100
100
  self.has_failed = false
101
101
  self.passed = 0
102
102
  self.failed = 0
@@ -106,7 +106,7 @@ pub mv struct Tester {
106
106
  }
107
107
 
108
108
  // (harness) Close the current test and emit its `done` record.
109
- pub func end_test = (ref self) {
109
+ pub func end_test = (ref self {}) {
110
110
  const uint64 elapsed = Time.now_ns() - self.started
111
111
  Console.write_line(
112
112
  "\\nomen|done|" + self.current + "|\{self.passed}|\{self.failed}|\{elapsed}",
@@ -124,7 +124,7 @@ pub mv struct Tester {
124
124
  *
125
125
  * t.expect(result == 2, "add(1, 1) should be 2")
126
126
  **/
127
- pub func expect = (ref self, bool condition, string message) {
127
+ pub func expect = (ref self {}, bool condition, string message) {
128
128
  if self.has_failed {
129
129
  return
130
130
  }
@@ -143,7 +143,7 @@ pub mv struct Tester {
143
143
  * t.fail("expected to find the key")
144
144
  * }
145
145
  **/
146
- pub func fail = (ref self, string message) {
146
+ pub func fail = (ref self {}, string message) {
147
147
  if self.has_failed {
148
148
  return
149
149
  }
@@ -154,43 +154,43 @@ pub mv struct Tester {
154
154
  //
155
155
  // Nomen has no generic methods, so there is one overload per nullable
156
156
  // type the compiler can compare against `null`.
157
- pub func assert = (ref self, int? value, string message) {
157
+ pub func assert = (ref self {}, int? value, string message) {
158
158
  self.expect(value != null, message)
159
159
  }
160
160
 
161
- pub func assert = (ref self, uint? value, string message) {
161
+ pub func assert = (ref self {}, uint? value, string message) {
162
162
  self.expect(value != null, message)
163
163
  }
164
164
 
165
- pub func assert = (ref self, int64? value, string message) {
165
+ pub func assert = (ref self {}, int64? value, string message) {
166
166
  self.expect(value != null, message)
167
167
  }
168
168
 
169
- pub func assert = (ref self, uint64? value, string message) {
169
+ pub func assert = (ref self {}, uint64? value, string message) {
170
170
  self.expect(value != null, message)
171
171
  }
172
172
 
173
- pub func assert = (ref self, int8? value, string message) {
173
+ pub func assert = (ref self {}, int8? value, string message) {
174
174
  self.expect(value != null, message)
175
175
  }
176
176
 
177
- pub func assert = (ref self, uint8? value, string message) {
177
+ pub func assert = (ref self {}, uint8? value, string message) {
178
178
  self.expect(value != null, message)
179
179
  }
180
180
 
181
- pub func assert = (ref self, float? value, string message) {
181
+ pub func assert = (ref self {}, float? value, string message) {
182
182
  self.expect(value != null, message)
183
183
  }
184
184
 
185
- pub func assert = (ref self, bool? value, string message) {
185
+ pub func assert = (ref self {}, bool? value, string message) {
186
186
  self.expect(value != null, message)
187
187
  }
188
188
 
189
- pub func assert = (ref self, char? value, string message) {
189
+ pub func assert = (ref self {}, char? value, string message) {
190
190
  self.expect(value != null, message)
191
191
  }
192
192
 
193
- pub func assert = (ref self, string? value, string message) {
193
+ pub func assert = (ref self {}, string? value, string message) {
194
194
  self.expect(value != null, message)
195
195
  }
196
196
 
@@ -212,7 +212,7 @@ pub mv struct Tester {
212
212
  * (default 1000, override with `bench_n`) and computes min / median /
213
213
  * mean / max / stddev over the per-iteration durations.
214
214
  **/
215
- pub func bench = (ref self, string label, func() body) {
215
+ pub func bench = (ref self { bench_label }, string label, func() body) {
216
216
  if self.has_failed {
217
217
  return
218
218
  }
@@ -226,7 +226,7 @@ pub mv struct Tester {
226
226
  * for slow functions (where the default 1000 would dominate the suite) or
227
227
  * for reproducible sample counts.
228
228
  **/
229
- pub func bench_n = (ref self, string label, func() body, int samples) {
229
+ pub func bench_n = (ref self { bench_label }, string label, func() body, int samples) {
230
230
  if self.has_failed {
231
231
  return
232
232
  }
@@ -244,7 +244,7 @@ pub mv struct Tester {
244
244
  * this is a no-op.
245
245
  **/
246
246
  pub func record_bench = (
247
- ref self,
247
+ ref self {},
248
248
  string label,
249
249
  int n,
250
250
  int min,
@@ -263,7 +263,7 @@ pub mv struct Tester {
263
263
  )
264
264
  }
265
265
 
266
- func record_failure = (ref self, string message) {
266
+ func record_failure = (ref self {}, string message) {
267
267
  self.failed += 1
268
268
  self.total_failed += 1
269
269
  self.has_failed = true
@@ -21,7 +21,7 @@ pub struct Chars {
21
21
 
22
22
  // The code point at the cursor, advancing past it. Malformed sequences
23
23
  // yield U+FFFD. Panics when exhausted — check has_next first.
24
- pub func next = (ref self, out int) {
24
+ pub func next = (ref self {}, out int) {
25
25
  if self.byte_pos >= self.source.length {
26
26
  panic("Chars exhausted; check has_next first")
27
27
  }
@@ -102,7 +102,7 @@ pub struct Json {
102
102
 
103
103
  // Parse a JSON document into tree. The caller provides a JsonTree pool
104
104
  // which is reset and filled. Returns the index of the root node.
105
- pub func parse = (string s, ref JsonTree tree, out int) {
105
+ pub func parse = (string s, ref JsonTree tree { nodes }, out int) {
106
106
  tree.reset()
107
107
  var pos = Buffer<int>()
108
108
  pos.alloc_int(1)
@@ -112,14 +112,14 @@ pub struct Json {
112
112
  }
113
113
 
114
114
  // Serialize a node in the tree back to a JSON string.
115
- pub func stringify = (ref JsonTree tree, int root, out string) {
115
+ pub func stringify = (ref JsonTree tree { nodes }, int root, out string) {
116
116
  var sb = StringBuilder()
117
117
  json_ser_value(ref tree, root, ref sb)
118
118
  return sb.to_string()
119
119
  }
120
120
  }
121
121
 
122
- func json_skip_ws = (string s, ref Buffer<int> pos, int len) {
122
+ func json_skip_ws = (string s, ref Buffer<int> pos {}, int len) {
123
123
  while pos.load_int(0) < len {
124
124
  var int i = pos.load_int(0)
125
125
  var int code = s.at(i) as int
@@ -131,7 +131,7 @@ func json_skip_ws = (string s, ref Buffer<int> pos, int len) {
131
131
  }
132
132
  }
133
133
 
134
- func json_parse_string = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
134
+ func json_parse_string = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
135
135
  var int i = pos.load_int(0)
136
136
  i += 1
137
137
  var sb = StringBuilder()
@@ -193,7 +193,7 @@ func json_parse_string = (string s, ref Buffer<int> pos, int len, ref JsonTree t
193
193
  return n
194
194
  }
195
195
 
196
- func json_parse_number = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
196
+ func json_parse_number = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
197
197
  var int i = pos.load_int(0)
198
198
  var int start = i
199
199
  while i < len {
@@ -215,7 +215,7 @@ func json_parse_number = (string s, ref Buffer<int> pos, int len, ref JsonTree t
215
215
  return n
216
216
  }
217
217
 
218
- func json_parse_literal = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
218
+ func json_parse_literal = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
219
219
  var int i = pos.load_int(0)
220
220
  var int code = s.at(i) as int
221
221
  var int n = tree.alloc_node()
@@ -237,7 +237,7 @@ func json_parse_literal = (string s, ref Buffer<int> pos, int len, ref JsonTree
237
237
  return n
238
238
  }
239
239
 
240
- func json_parse_value = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
240
+ func json_parse_value = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
241
241
  json_skip_ws(s, ref pos, len)
242
242
  var int i = pos.load_int(0)
243
243
  if i >= len {
@@ -267,7 +267,7 @@ func json_parse_value = (string s, ref Buffer<int> pos, int len, ref JsonTree tr
267
267
  return json_parse_number(s, ref pos, len, ref tree)
268
268
  }
269
269
 
270
- func json_parse_elements = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
270
+ func json_parse_elements = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
271
271
  json_skip_ws(s, ref pos, len)
272
272
  var int i = pos.load_int(0)
273
273
  if i >= len {
@@ -289,7 +289,7 @@ func json_parse_elements = (string s, ref Buffer<int> pos, int len, ref JsonTree
289
289
  return elem
290
290
  }
291
291
 
292
- func json_parse_pairs = (string s, ref Buffer<int> pos, int len, ref JsonTree tree, out int) {
292
+ func json_parse_pairs = (string s, ref Buffer<int> pos {}, int len, ref JsonTree tree { nodes }, out int) {
293
293
  json_skip_ws(s, ref pos, len)
294
294
  var int i = pos.load_int(0)
295
295
  if i >= len {
@@ -321,7 +321,7 @@ func json_parse_pairs = (string s, ref Buffer<int> pos, int len, ref JsonTree tr
321
321
  return key
322
322
  }
323
323
 
324
- func json_ser_list = (ref JsonTree tree, int first, ref StringBuilder sb) {
324
+ func json_ser_list = (ref JsonTree tree { nodes }, int first, ref StringBuilder sb {}) {
325
325
  json_ser_value(ref tree, first, ref sb)
326
326
  var int next = tree.get_next(first)
327
327
  if next >= 0 {
@@ -330,7 +330,7 @@ func json_ser_list = (ref JsonTree tree, int first, ref StringBuilder sb) {
330
330
  }
331
331
  }
332
332
 
333
- func json_ser_pairs = (ref JsonTree tree, int first, ref StringBuilder sb) {
333
+ func json_ser_pairs = (ref JsonTree tree { nodes }, int first, ref StringBuilder sb {}) {
334
334
  sb.append_char('"')
335
335
  sb.append_string_view(tree.get_text_view(first))
336
336
  sb.append_string("\":")
@@ -347,7 +347,7 @@ func json_ser_pairs = (ref JsonTree tree, int first, ref StringBuilder sb) {
347
347
  }
348
348
  }
349
349
 
350
- func json_ser_value = (ref JsonTree tree, int n, ref StringBuilder sb) {
350
+ func json_ser_value = (ref JsonTree tree { nodes }, int n, ref StringBuilder sb {}) {
351
351
  var int k = tree.get_kind(n)
352
352
  if k == 0 {
353
353
  sb.append_string("null")
@@ -37,7 +37,7 @@ pub mv struct JsonTree {
37
37
  var nodes = StableList<JsonNode>()
38
38
 
39
39
  // Append a fresh node and return its index.
40
- func alloc_node = (ref self, out int) {
40
+ func alloc_node = (ref self { nodes }, out int) {
41
41
  self.nodes.push(JsonNode())
42
42
  return self.nodes.length - 1
43
43
  }
@@ -45,7 +45,7 @@ pub mv struct JsonTree {
45
45
  // Drop the current document: the fresh StableList displaces the old one,
46
46
  // whose destroy frees every node (texts included) and its slabs. The
47
47
  // next parse starts from a clean pool.
48
- func reset = (ref self) {
48
+ func reset = (ref self { nodes }) {
49
49
  self.nodes = StableList<JsonNode>()
50
50
  }
51
51
 
@@ -58,7 +58,7 @@ pub mv struct JsonTree {
58
58
  // once, by the list's destroy or the next text store. For strings
59
59
  // produced by a StringBuilder, `take_text` installs the builder's
60
60
  // buffer with no copy at all.
61
- func set_text = (ref self, int idx, mv string text) {
61
+ func set_text = (ref self {}, int idx, mv string text) {
62
62
  if idx < 0 || idx >= self.nodes.length {
63
63
  panic("index out of range")
64
64
  }
@@ -75,7 +75,7 @@ pub mv struct JsonTree {
75
75
  // temp free. (A `mv string` parameter cannot do this: the string-arg
76
76
  // ownership convention makes mv string arguments caller-owned
77
77
  // borrows, forcing the callee-side copy this method exists to skip.)
78
- func take_text = (ref self, int idx, ref StringBuilder sb) {
78
+ func take_text = (ref self {}, int idx, ref StringBuilder sb {}) {
79
79
  if idx < 0 || idx >= self.nodes.length {
80
80
  panic("index out of range")
81
81
  }
@@ -83,7 +83,7 @@ pub mv struct JsonTree {
83
83
  n.text = sb.to_string()
84
84
  }
85
85
 
86
- func set_kind = (ref self, int idx, int val) {
86
+ func set_kind = (ref self {}, int idx, int val) {
87
87
  if idx < 0 || idx >= self.nodes.length {
88
88
  panic("index out of range")
89
89
  }
@@ -91,7 +91,7 @@ pub mv struct JsonTree {
91
91
  n.kind = val
92
92
  }
93
93
 
94
- func set_child = (ref self, int idx, int val) {
94
+ func set_child = (ref self {}, int idx, int val) {
95
95
  if idx < 0 || idx >= self.nodes.length {
96
96
  panic("index out of range")
97
97
  }
@@ -99,7 +99,7 @@ pub mv struct JsonTree {
99
99
  n.child = val
100
100
  }
101
101
 
102
- func set_next = (ref self, int idx, int val) {
102
+ func set_next = (ref self {}, int idx, int val) {
103
103
  if idx < 0 || idx >= self.nodes.length {
104
104
  panic("index out of range")
105
105
  }
@@ -107,7 +107,7 @@ pub mv struct JsonTree {
107
107
  n.next = val
108
108
  }
109
109
 
110
- func set_val = (ref self, int idx, int val) {
110
+ func set_val = (ref self {}, int idx, int val) {
111
111
  if idx < 0 || idx >= self.nodes.length {
112
112
  panic("index out of range")
113
113
  }