nomen-lang 0.6.12 → 0.7.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 (71) hide show
  1. package/NOMEN_AGENTS.md +27 -13
  2. package/audit_runtime.c +2 -0
  3. package/core/System/Arena.nm +4 -4
  4. package/core/System/Array.nm +108 -78
  5. package/core/System/Atomic.nm +81 -0
  6. package/core/System/Awaitable.nm +12 -5
  7. package/core/System/BigInt.nm +1 -1
  8. package/core/System/Box.nm +32 -0
  9. package/core/System/Buffer.nm +47 -18
  10. package/core/System/Channel.nm +27 -11
  11. package/core/System/ClassBuffer.nm +24 -28
  12. package/core/System/Console.nm +4 -4
  13. package/core/System/Controls/Button.nm +8 -3
  14. package/core/System/Controls/CheckBox.nm +8 -3
  15. package/core/System/Controls/Container.nm +18 -11
  16. package/core/System/Controls/Layout.nm +1 -1
  17. package/core/System/Controls/Text.nm +9 -4
  18. package/core/System/Controls/TextBox.nm +8 -3
  19. package/core/System/Controls/Window.nm +10 -3
  20. package/core/System/Fiber.nm +6 -2
  21. package/core/System/Graph.nm +2 -2
  22. package/core/System/Init.nm +2 -2
  23. package/core/System/LinkedList.nm +2 -2
  24. package/core/System/List.nm +7 -7
  25. package/core/System/Map.nm +10 -7
  26. package/core/System/Math.nm +1 -1
  27. package/core/System/Mutex.nm +14 -2
  28. package/core/System/Random.nm +7 -1
  29. package/core/System/Result.nm +1 -1
  30. package/core/System/Sendable.nm +2 -2
  31. package/core/System/Set.nm +6 -6
  32. package/core/System/Spawnable.nm +9 -9
  33. package/core/System/Stream/Directory.nm +1 -2
  34. package/core/System/Stream/File.nm +8 -9
  35. package/core/System/Stream/Http.nm +2 -3
  36. package/core/System/Stream/Tcp.nm +13 -8
  37. package/core/System/String.nm +22 -12
  38. package/core/System/StringBuilder.nm +2 -2
  39. package/core/System/Task.nm +21 -29
  40. package/core/System/Test.nm +10 -4
  41. package/core/System/Text/CharIndex.nm +2 -3
  42. package/core/System/Text/Json.nm +8 -12
  43. package/core/System/Text/JsonTree.nm +4 -4
  44. package/core/System/Text/Regex.nm +7 -7
  45. package/core/System/Text/Utf8.nm +2 -3
  46. package/core/System/Thread.nm +9 -4
  47. package/core/System/Tree.nm +2 -2
  48. package/core/System/Viewable.nm +2 -2
  49. package/core/System/WeakHandle.nm +56 -0
  50. package/core/System/bool.nm +1 -1
  51. package/core/System/char.nm +1 -1
  52. package/core/System/float.nm +1 -1
  53. package/core/System/float32.nm +1 -1
  54. package/core/System/float64.nm +1 -1
  55. package/core/System/int.nm +1 -1
  56. package/core/System/int16.nm +1 -1
  57. package/core/System/int32.nm +1 -1
  58. package/core/System/int64.nm +1 -1
  59. package/core/System/int8.nm +1 -1
  60. package/core/System/ufloat.nm +1 -1
  61. package/core/System/ufloat32.nm +1 -1
  62. package/core/System/ufloat64.nm +1 -1
  63. package/core/System/uint.nm +1 -1
  64. package/core/System/uint16.nm +1 -1
  65. package/core/System/uint32.nm +1 -1
  66. package/core/System/uint64.nm +1 -1
  67. package/core/System/uint8.nm +1 -1
  68. package/core/docs/System/Result.md +2 -2
  69. package/dist/index.mjs +28088 -24186
  70. package/package.json +1 -1
  71. package/src/test.ts +26 -11
@@ -11,13 +11,18 @@
11
11
  // on the first spawn — not in Task's own methods — so that Task can be
12
12
  // generic without duplicating the pool per instantiation.
13
13
  //
14
+ // Task is an OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 2 — the shape
15
+ // menu): every field is an opaque handle (uint64/bool), so the handle value
16
+ // is movable and its `#destroy` releases the future reference it holds.
17
+ // Moving a Task transfers that reference; there is no aliasing copy.
18
+ //
14
19
  // See ASYNC.md for the design.
15
20
 
16
21
  /**
17
22
  * A handle to an asynchronously-running computation, backed by a shared thread pool.
18
23
  * Conforms to `Awaitable`: `.wait()` may park the current execution context.
19
24
  **/
20
- pub class Task<T> : Sendable, Awaitable {
25
+ pub mv struct Task<T> : Awaitable {
21
26
  pub var uint64 handle = 0
22
27
  pub var done = false
23
28
  pub var uint64 result_slot = 0
@@ -35,40 +40,27 @@ pub class Task<T> : Sendable, Awaitable {
35
40
  // Block until the task finishes. Idempotent — calling twice is safe, and
36
41
  // a Task captured from a nursery spawn can be waited on here AND joined
37
42
  // by the nursery at block exit (both wait on the same shared future).
38
- pub func wait = (ref self) {
43
+ //
44
+ // The receiver is a bare VALUE self (matching the Awaitable trait):
45
+ // waiting never mutates the handle — it parks on the future the handle
46
+ // names. Struct receivers travel by address regardless (the raw body
47
+ // reads `self->future`), so the ABI is unchanged; the bare spelling is
48
+ // 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
+ pub func wait = (self) {
39
52
  ```
40
53
  #arch: c
41
54
  if (self->future) {
42
55
  __nomen_future_wait((struct nomen_future *)self->future);
43
- } else if (self->handle && !self->done) {
44
- void *ret;
45
- pthread_join((pthread_t)self->handle, &ret);
46
- self->handle = 0;
47
- self->done = 1;
48
56
  }
49
57
  ```
50
58
  ```
51
59
  #arch: aarch64
52
- // if (self->future) goto wait_future
60
+ // if (self->future) __nomen_future_wait(self->future)
53
61
  ldr x0, [x19, #40]
54
- cbz x0, .Lwait_handle
55
- bl ___nomen_future_wait
56
- b .Lwait_done
57
- .Lwait_handle:
58
- // else if (self->handle && !self->done)
59
- ldr x0, [x19, #8]
60
62
  cbz x0, .Lwait_done
61
- ldrb w1, [x19, #16]
62
- cbnz w1, .Lwait_done
63
- // pthread_join((pthread_t)self->handle, &ret)
64
- sub sp, sp, #16
65
- mov x1, sp
66
- bl _pthread_join
67
- add sp, sp, #16
68
- // self->handle = 0; self->done = 1
69
- str xzr, [x19, #8]
70
- mov w0, #1
71
- strb w0, [x19, #16]
63
+ bl ___nomen_future_wait
72
64
  .Lwait_done:
73
65
  ```
74
66
  }
@@ -78,10 +70,10 @@ pub class Task<T> : Sendable, Awaitable {
78
70
  // the full return value — including the 16-byte fat-string pair — and the
79
71
  // trampoline writes the function's return value there before exiting.
80
72
  // The result is MOVED OUT: the slot is zeroed as the value leaves, and
81
- // `move out T` marks the caller as the owner. Call it once; a second call
73
+ // `mv out T` marks the caller as the owner. Call it once; a second call
82
74
  // returns the zero value. For tasks with no return value (void
83
75
  // functions), returns the zero value.
84
- pub func result = (ref self, move out T) {
76
+ pub func result = (ref self, mv out T) {
85
77
  ```
86
78
  #arch: c
87
79
  if (self->future) {
@@ -284,7 +276,7 @@ pub class Task<T> : Sendable, Awaitable {
284
276
  // ---- User-defined async primitive seam (ASYNC.md, "User-defined async
285
277
  // primitives") ----
286
278
  // The construction sugar stores the packed-task machinery in a user
287
- // class's plain uint64 fields (task / result_slot / cancel_flag /
279
+ // spawnable's plain uint64 fields (task / result_slot / cancel_flag /
288
280
  // future); these statics are the library boundary its own launch
289
281
  // methods drive the runtime through — the same calls the generated
290
282
  // Thread/Fiber launch code makes, so a user primitive parks fibers,
@@ -294,7 +286,7 @@ pub class Task<T> : Sendable, Awaitable {
294
286
 
295
287
  // Submit a packed task closure (the `task` field's value) to the shared
296
288
  // worker pool. The closure must come from a construction of an
297
- // Awaitable-conforming class — it is not callable.
289
+ // Awaitable-conforming spawnable — it is not callable.
298
290
  pub func pool_submit = (uint64 closure) {
299
291
  ```
300
292
  #arch: c
@@ -32,6 +32,12 @@
32
32
  //
33
33
  // See TESTING.md for the full design.
34
34
 
35
+ // Tester is an OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 3 — the shape
36
+ // menu): the harness builds exactly one per run, so the single-owner rule
37
+ // costs nothing and the record state moves with the value. The string
38
+ // fields (current/bench_label) are normalized heap-owned by the compiler's
39
+ // struct string machinery, so `#destroy` reclaims them cleanly.
40
+
35
41
  /**
36
42
  * Records assertions and benchmarks for one test file.
37
43
  *
@@ -47,7 +53,7 @@
47
53
  * skipped, so a single root cause reports as a single failure. Check
48
54
  * `t.has_failed` to bail out of expensive follow-up work yourself.
49
55
  **/
50
- pub class Tester {
56
+ pub mv struct Tester {
51
57
  // Has the *current* test recorded a failure? Reset by `begin_test`.
52
58
  pub var has_failed = false
53
59
 
@@ -94,7 +100,7 @@ pub class Tester {
94
100
  self.has_failed = false
95
101
  self.passed = 0
96
102
  self.failed = 0
97
- self.current = name
103
+ self.current = name.copy()
98
104
  Console.write_line("\\nomen|start|" + name)
99
105
  self.started = Time.now_ns()
100
106
  }
@@ -211,7 +217,7 @@ pub class Tester {
211
217
  return
212
218
  }
213
219
  self.bench_pending = true
214
- self.bench_label = label
220
+ self.bench_label = label.copy()
215
221
  self.bench_samples = 1000
216
222
  }
217
223
 
@@ -225,7 +231,7 @@ pub class Tester {
225
231
  return
226
232
  }
227
233
  self.bench_pending = true
228
- self.bench_label = label
234
+ self.bench_label = label.copy()
229
235
  self.bench_samples = samples
230
236
  }
231
237
 
@@ -20,7 +20,7 @@ pub struct CharRun {
20
20
  * A run-length character-width index (construct with `CharIndex(text)`,
21
21
  * then `byte_offset_of` / `char_index_of` / `char_at` in O(log runs))
22
22
  **/
23
- pub struct CharIndex {
23
+ pub mv struct CharIndex {
24
24
  var view string source
25
25
  var runs = List<CharRun>()
26
26
  var char_count = 0
@@ -50,7 +50,7 @@ pub struct CharIndex {
50
50
  pos = pos + w
51
51
  chars = chars + 1
52
52
  }
53
- else {
53
+ } else {
54
54
  if open_at >= 0 {
55
55
  self.runs.push(CharRun(open_at, open_start, open_width, open_count))
56
56
  }
@@ -61,7 +61,6 @@ pub struct CharIndex {
61
61
  pos = pos + w
62
62
  chars = chars + 1
63
63
  }
64
- }
65
64
  }
66
65
  if open_at >= 0 {
67
66
  self.runs.push(CharRun(open_at, open_start, open_width, open_count))
@@ -14,9 +14,9 @@
14
14
  **/
15
15
  pub struct Json {
16
16
  // Serialize a string to a JSON string literal, escaping the special
17
- // characters ", \, newline, tab and carriage return. `move out string`:
17
+ // characters ", \, newline, tab and carriage return. `mv out string`:
18
18
  // returns the StringBuilder's owned heap copy.
19
- pub func serialize = (string value, move out string) {
19
+ pub func serialize = (string value, mv out string) {
20
20
  var sb = StringBuilder()
21
21
  sb.append_char('"')
22
22
  var i = 0
@@ -40,18 +40,17 @@ pub struct Json {
40
40
  case code == 13 {
41
41
  sb.append_string("\x5cr")
42
42
  }
43
- else {
43
+ } else {
44
44
  sb.append_char(c)
45
45
  }
46
- }
47
46
  }
48
47
  sb.append_char('"')
49
48
  return sb.to_string()
50
49
  }
51
50
 
52
51
  // Deserialize a JSON string literal to the raw, unescaped value.
53
- // `move out string`: returns the StringBuilder's owned heap copy.
54
- pub func deserialize = (string json, move out string) {
52
+ // `mv out string`: returns the StringBuilder's owned heap copy.
53
+ pub func deserialize = (string json, mv out string) {
55
54
  var sb = StringBuilder()
56
55
  var int len = json.length
57
56
  var i = 0
@@ -90,10 +89,9 @@ pub struct Json {
90
89
  case ec == 92 {
91
90
  sb.append_string("\x5c")
92
91
  }
93
- else {
92
+ } else {
94
93
  sb.append_char(e)
95
94
  }
96
- }
97
95
  }
98
96
  } else {
99
97
  sb.append_char(c)
@@ -165,10 +163,9 @@ func json_parse_string = (string s, ref Buffer<int> pos, int len, ref JsonTree t
165
163
  case ec == 92 {
166
164
  sb.append_string("\x5c")
167
165
  }
168
- else {
166
+ } else {
169
167
  sb.append_char(e)
170
168
  }
171
- }
172
169
  }
173
170
  } else {
174
171
  sb.append_char(c)
@@ -218,11 +215,10 @@ func json_parse_literal = (string s, ref Buffer<int> pos, int len, ref JsonTree
218
215
  tree.set_kind(n, 6)
219
216
  adv = 5
220
217
  }
221
- else {
218
+ } else {
222
219
  tree.set_kind(n, 0)
223
220
  adv = 4
224
221
  }
225
- }
226
222
  pos.store_int(0, i + adv)
227
223
  return n
228
224
  }
@@ -11,7 +11,7 @@
11
11
  // A node in a parsed JSON tree, stored by value in the pool.
12
12
  // kind: 0=null, 1=true, 2=number, 3=string, 4=array, 5=object, 6=false
13
13
  // child/next/val are node indices, -1 = none.
14
- struct JsonNode {
14
+ mv struct JsonNode {
15
15
  var kind = 0
16
16
  var text = ""
17
17
  var int child = -1
@@ -22,7 +22,7 @@ struct JsonNode {
22
22
  /**
23
23
  * A flat, buffer-backed pool of JSON tree nodes — the parsed representation `Json.parse` produces
24
24
  **/
25
- pub struct JsonTree {
25
+ pub mv struct JsonTree {
26
26
  var nodes = Buffer<JsonNode>()
27
27
  var count = 0
28
28
 
@@ -32,7 +32,7 @@ pub struct JsonTree {
32
32
  self.count = idx + 1
33
33
  var default = JsonNode()
34
34
  self.nodes.store(idx, default)
35
- // store_T deep-copies the owning `text` field (strdup of the shared
35
+ // store_T deep-copies the mv `text` field (strdup of the shared
36
36
  // empty-string literal) into the slot. JsonTree manages node texts
37
37
  // manually (set_text strdup's into the slab; free_text/release frees
38
38
  // them; NULL means "no text"), so the slot must start NULL — free the
@@ -136,7 +136,7 @@ pub struct JsonTree {
136
136
 
137
137
  func get_text = (self, int idx, out string) {
138
138
  var JsonNode n = self.nodes.load(idx)
139
- return n.text
139
+ return n.text.copy()
140
140
  }
141
141
 
142
142
  func get_child = (self, int idx, out int) {
@@ -33,9 +33,9 @@ pub struct Regex {
33
33
  }
34
34
 
35
35
  // Return the first substring of input matching pattern, or "" if none.
36
- // `move out string`: the built match (or the copied empty literal) is
36
+ // `mv out string`: the built match (or the copied empty literal) is
37
37
  // handed to the caller as an owned value.
38
- pub func match = (string pattern, string input, move out string) {
38
+ pub func match = (string pattern, string input, mv out string) {
39
39
  var match_result = ""
40
40
  var int pat_len = pattern.length
41
41
  var int len = input.length
@@ -89,7 +89,7 @@ pub struct Regex {
89
89
  var int end = match_here(pattern, 0, pat_len, input, i, len, ref caps)
90
90
  if end >= 0 {
91
91
  var string whole = input.substring(i, end)
92
- dst.push(whole)
92
+ dst.push(mv whole)
93
93
  var g = 1
94
94
  while g <= groups; g += 1 {
95
95
  var int at = last_capture_index(caps, g)
@@ -97,7 +97,7 @@ pub struct Regex {
97
97
  var int s = caps.at(at + 1)
98
98
  if s >= 0 {
99
99
  var string cap = input.substring(s, caps.at(at + 2))
100
- dst.push(cap)
100
+ dst.push(mv cap)
101
101
  } else {
102
102
  dst.push("")
103
103
  }
@@ -221,7 +221,7 @@ pub struct Regex {
221
221
  }
222
222
 
223
223
  // First match of pattern in input, ignoring ASCII case ("" if none).
224
- pub func match_ci = (string pattern, string input, move out string) {
224
+ pub func match_ci = (string pattern, string input, mv out string) {
225
225
  var string folded = fold_pattern(pattern)
226
226
  return Regex.match(folded, input)
227
227
  }
@@ -250,7 +250,7 @@ pub struct Regex {
250
250
  // their case counterparts ([a-z] -> [a-zA-Z]). Structural syntax — groups,
251
251
  // alternation, quantifiers, anchors, escaped punctuation — is copied
252
252
  // through unchanged.
253
- func fold_pattern = (string pattern, move out string) {
253
+ func fold_pattern = (string pattern, mv out string) {
254
254
  var int n = pattern.length
255
255
  var sb = StringBuilder()
256
256
  var i = 0
@@ -1925,7 +1925,7 @@ func last_capture_index = (List<int> caps, int group, out int) {
1925
1925
  /**
1926
1926
  * A Regex.find result: whether the pattern matched, where, and what
1927
1927
  **/
1928
- pub struct RegexMatch {
1928
+ pub mv struct RegexMatch {
1929
1929
  var found = false
1930
1930
  var start = 0
1931
1931
  var end = 0
@@ -103,7 +103,7 @@ pub struct Utf8 {
103
103
 
104
104
  // Encode a code point as UTF-8. Out-of-range values and surrogate halves
105
105
  // encode as U+FFFD.
106
- pub func encode = (int code_point, move out string) {
106
+ pub func encode = (int code_point, mv out string) {
107
107
  var int code = code_point
108
108
  if code < 0 || code > 0x10FFFF {
109
109
  code = 0xFFFD
@@ -125,13 +125,12 @@ pub struct Utf8 {
125
125
  sb.append_char(((0x80 | ((code >> 6) & 0x3F)) as char))
126
126
  sb.append_char(((0x80 | (code & 0x3F)) as char))
127
127
  }
128
- else {
128
+ } else {
129
129
  sb.append_char(((0xF0 | (code >> 18)) as char))
130
130
  sb.append_char(((0x80 | ((code >> 12) & 0x3F)) as char))
131
131
  sb.append_char(((0x80 | ((code >> 6) & 0x3F)) as char))
132
132
  sb.append_char(((0x80 | (code & 0x3F)) as char))
133
133
  }
134
- }
135
134
  return sb.to_string()
136
135
  }
137
136
 
@@ -30,6 +30,11 @@
30
30
  // (and nursery.start) transfer ownership of the packed task out of the
31
31
  // value, so a started Thread destroys as a no-op.
32
32
  //
33
+ // Thread is an OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 2 — the shape
34
+ // menu): every field is an opaque handle (uint64/bool), so the value is
35
+ // movable and its `#destroy` closes what the handles name. Moving a Thread
36
+ // transfers the handles; there is no aliasing copy to misuse.
37
+ //
33
38
  // See ASYNC.md for the design.
34
39
 
35
40
  // The launch surface's return type (ASYNC.md: the dependency is
@@ -39,11 +44,11 @@ import Task
39
44
  /**
40
45
  * A deferred function call, startable on the shared worker pool
41
46
  **/
42
- pub class Thread<T> : Sendable, Spawnable<T> {
43
- // The construction hook (ASYNC.md): declares this class's
47
+ pub mv struct Thread<T> : Spawnable<T> {
48
+ // The construction hook (ASYNC.md): declares this type's
44
49
  // construction as the deferred-call special form — the single argument
45
50
  // is a call (args packed eagerly, call deferred) or a zero-arg function
46
- // value. The compiler matches this member, never the class name; the
51
+ // value. The compiler matches this member, never the type name; the
47
52
  // construction itself is compiler-generated (pack the args, allocate the
48
53
  // future machinery, build the instance), so the body is a declaration.
49
54
  #spawn = () {
@@ -77,7 +82,7 @@ pub class Thread<T> : Sendable, Spawnable<T> {
77
82
  // fields, so #destroy becomes a no-op afterwards. The future's refs
78
83
  // account for the trampoline, the returned handle, and the nursery (when
79
84
  // captured).
80
- pub func start = (ref self, move out Task<T>) {
85
+ pub func start = (ref self, mv out Task<T>) {
81
86
  ```
82
87
  #arch: c
83
88
  struct nomen_future *_f = (struct nomen_future *)self->future;
@@ -6,14 +6,14 @@
6
6
  /**
7
7
  * A tree of values connected by parent/child links
8
8
  **/
9
- pub struct Tree<T>: Enumerable {
9
+ pub mv struct Tree<T>: Enumerable {
10
10
  var values = Buffer<T>()
11
11
  var lefts = Buffer<int>()
12
12
  var rights = Buffer<int>()
13
13
  var parents = Buffer<int>()
14
14
  var count = 0
15
15
 
16
- pub func add = (ref self, move T value) {
16
+ pub func add = (ref self, mv T value) {
17
17
  const int idx = self.count
18
18
  self.values.grow_int(idx + 1)
19
19
  const int v = value
@@ -1,4 +1,4 @@
1
- // Marker trait for containers that can be borrowed as a non-owning `view T`
1
+ // Marker trait for containers that can be borrowed as a non-mv `view T`
2
2
  // slice via a `slice(start, end, out view T)` method. Conforming types
3
3
  // implement slice — almost always by delegating to an internal Buffer's slice
4
4
  // (`return self.items.slice(start, end)`), so no #arch code is needed in user
@@ -21,7 +21,7 @@
21
21
  // }
22
22
 
23
23
  /**
24
- * A trait for containers that can be borrowed as a non-owning `view T` slice
24
+ * A trait for containers that can be borrowed as a non-mv `view T` slice
25
25
  **/
26
26
  pub trait Viewable {
27
27
  }
@@ -0,0 +1,56 @@
1
+ // WeakHandle<T> (STRUCT_PLAN_3 N3) — a checked back-pointer / OS-retained
2
+ // handle. The residue of OS/AppKit retention and child→parent edges: a
3
+ // handle to a registry slot, not a reference — no refcounts, no cycles.
4
+ //
5
+ // var WeakHandle<Window> w = WeakHandle<Window>(window)
6
+ // ...
7
+ // var Window? live = w.get() // nil check at the use site
8
+ //
9
+ // The CREATION is the marker (nothing aliases without one). The race is
10
+ // inherently dynamic — the OS may have torn the object down — so the
11
+ // runtime check in `get` is the only truthful one. The registry is ONE
12
+ // process-wide (pointer, generation) slot table with a free list,
13
+ // internally synchronized (handles are consulted from workers); the
14
+ // tracked type's `#destroy` invalidates every slot holding the pointer
15
+ // (generation bump), and a recycled slot never resets its generation, so a
16
+ // stale handle can never alias a new object. Move-safe by construction: a
17
+ // handle owns nothing.
18
+ //
19
+ // `T` must be a class (enforced at the construction site) — a weak handle
20
+ // to a value-struct local would outlive the stack storage it names.
21
+ //
22
+ // `get` returns the instance pointer, NULL once the instance is gone —
23
+ // bind it to a `T?` and nil-check at the use site.
24
+
25
+ /**
26
+ * A checked, generation-validated handle to a possibly-gone object
27
+ **/
28
+ pub struct WeakHandle<T> {
29
+ // The construction hook (the library-tier marker, beside #init and
30
+ // #destroy): `WeakHandle<T>(obj)` registers `obj` in the process-wide
31
+ // registry. The construction itself is compiler-generated (register the
32
+ // object, capture the slot's generation), so the body is a declaration.
33
+ #weak = () {
34
+ }
35
+
36
+ // The registry slot id and the generation captured at creation.
37
+ var uint64 id = 0
38
+ var uint64 gen = 0
39
+
40
+ // The checked read: the slot's live pointer, NULL when the instance was
41
+ // destroyed (or the slot was recycled). Bind to `T?` and nil-check.
42
+ // Offsets skip the leading `_vt` slot the auto-derived `to_string`
43
+ // (Stringable conformance) puts on every struct: id at +8, gen at +16.
44
+ pub func get = (self, out T) {
45
+ ```
46
+ #arch: c
47
+ return __nomen_weak_get(self->id, self->gen);
48
+ ```
49
+ ```
50
+ #arch: aarch64
51
+ ldr x1, [x0, #16]
52
+ ldr x0, [x0, #8]
53
+ bl ___nomen_weak_get
54
+ ```
55
+ }
56
+ }
@@ -12,7 +12,7 @@ pub struct bool: Stringable, Hashable, Equatable {
12
12
  * @param self: the boolean
13
13
  * @out string: the boolean as a string value (`"true"` or `"false"`)
14
14
  **/
15
- pub func to_string = (self, move out string) {
15
+ pub func to_string = (self, mv out string) {
16
16
  ```
17
17
  #arch: c
18
18
  int length = snprintf(NULL, 0, "%s", self ? "true" : "false");
@@ -6,7 +6,7 @@ pub struct char: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%c", self);
@@ -2,7 +2,7 @@
2
2
  * A double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct float: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -2,7 +2,7 @@
2
2
  * A signed double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct float32: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -2,7 +2,7 @@
2
2
  * A signed double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct float64: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -6,7 +6,7 @@ pub struct int: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%ld", self);
@@ -6,7 +6,7 @@ pub struct int16: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%d", self);
@@ -6,7 +6,7 @@ pub struct int32: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%d", self);
@@ -6,7 +6,7 @@ pub struct int64: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%lld", self);
@@ -6,7 +6,7 @@ pub struct int8: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%d", self);
@@ -2,7 +2,7 @@
2
2
  * An unsigned double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct ufloat: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -2,7 +2,7 @@
2
2
  * An unsigned double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct ufloat32: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -2,7 +2,7 @@
2
2
  * An unsigned double-precision (64-bit) floating-point number
3
3
  **/
4
4
  pub struct ufloat64: Stringable {
5
- pub func to_string = (self, move out string) {
5
+ pub func to_string = (self, mv out string) {
6
6
  ```
7
7
  #arch: c
8
8
  int length = snprintf(NULL, 0, "%f", self);
@@ -6,7 +6,7 @@ pub struct uint: Stringable, Hashable, Equatable {
6
6
  return self
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%ld", self);
@@ -6,7 +6,7 @@ pub struct uint16: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%u", self);
@@ -6,7 +6,7 @@ pub struct uint32: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%u", self);
@@ -6,7 +6,7 @@ pub struct uint64: Stringable, Hashable, Equatable {
6
6
  return self as uint
7
7
  }
8
8
 
9
- pub func to_string = (self, move out string) {
9
+ pub func to_string = (self, mv out string) {
10
10
  ```
11
11
  #arch: c
12
12
  int length = snprintf(NULL, 0, "%llu", self);