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
@@ -3,7 +3,7 @@
3
3
  // class, the monomorphizer rewrites a Buffer<T> field to ClassBuffer<T>.
4
4
  //
5
5
  // Public API is the size-aware family (`alloc`/`grow`/`load`/`replace`/
6
- // `move`/`modify`/`shift`/`slice` plus the readonly `cap`). `replace` is the
6
+ // `mv`/`modify`/`shift`/`slice` plus the readonly `cap`). `replace` is the
7
7
  // public write — it reclaims the displaced element, so it is correct on both
8
8
  // fresh and occupied slots. `store` (which assumes a fresh slot and leaks on
9
9
  // overwrite), `zero`, the fixed-width `*_u32`/`*_int`/`*_float` primitives,
@@ -93,6 +93,35 @@ pub struct Buffer<T> {
93
93
  ```
94
94
  }
95
95
 
96
+ // Byte-width primitives (uint8 elements): the width-matched family the
97
+ // NEON planner's `.16b` descriptor keys on — one 16-byte group carries
98
+ // 16 lanes. `ldrb`/`strb` zero-extend/clobber exactly one byte.
99
+ internal inline func load_u8 = (self, int i: i >= 0 && i < self.cap, out uint8) {
100
+ ```
101
+ #arch: c
102
+ return ((unsigned char*)(unsigned long long)self->data)[i];
103
+ ```
104
+ ```
105
+ #arch: aarch64
106
+ ldr x0, [x19, #8]
107
+ add x0, x0, x1
108
+ ldrb w0, [x0]
109
+ ```
110
+ }
111
+
112
+ internal inline func store_u8 = (ref self, int i: i >= 0 && i < self.cap, uint8 val) {
113
+ ```
114
+ #arch: c
115
+ ((unsigned char*)(unsigned long long)self->data)[i] = val;
116
+ ```
117
+ ```
118
+ #arch: aarch64
119
+ ldr x0, [x19, #8]
120
+ add x0, x0, x1
121
+ strb w2, [x0]
122
+ ```
123
+ }
124
+
96
125
  internal func alloc_int = (ref self, int size, out int: out >= size) {
97
126
  self.cap = size
98
127
  self.data = calloc(size, 8)
@@ -259,7 +288,7 @@ pub struct Buffer<T> {
259
288
  }
260
289
 
261
290
  // Store `val` into slot `i`, which MUST be fresh (calloc'd, or zeroed by
262
- // move). For an owning T (string, or a struct with string fields) the
291
+ // mv). For a mv T (string, or a struct with string fields) the
263
292
  // specialised body deep-copies the incoming value but does NOT free the
264
293
  // slot's previous occupant — a second `store` at an occupied index
265
294
  // leaks it. To overwrite a live slot use replace (frees the displaced
@@ -308,11 +337,11 @@ pub struct Buffer<T> {
308
337
  }
309
338
 
310
339
  // Move a value out of a T_SIZE-sized slot: return it and zero the slot so the
311
- // buffer no longer holds a (possibly owning) copy. Declared `move out T` so
340
+ // buffer no longer holds a (possibly mv) copy. Declared `mv out T` so
312
341
  // the result is treated as OWNED by the borrow checker — the slot is
313
342
  // relinquished, so the caller is the sole remaining owner. The value
314
343
  // counterpart of ClassBuffer.move_int — used by List.pop for any value T.
315
- inline func move = (ref self, int i: i >= 0 && i < self.cap, move out T) {
344
+ inline func move = (ref self, int i: i >= 0 && i < self.cap, mv out T) {
316
345
  ```
317
346
  #arch: c
318
347
  T* _slots = (T*)(unsigned long long)self->data;
@@ -375,8 +404,8 @@ pub struct Buffer<T> {
375
404
  // aliases the slot's own copy (the round-trip case) is kept, not freed or
376
405
  // re-copied. Unlike store this never leaks on overwrite, and unlike
377
406
  // replace it is safe to derive the new value from the old one. The
378
- // returned struct's owning fields must be fresh, null, or identical to
379
- // the corresponding input fields (no cross-field aliasing). For owning
407
+ // returned struct's mv fields must be fresh, null, or identical to
408
+ // the corresponding input fields (no cross-field aliasing). For mv
380
409
  // elements (string / structs with string fields) the build phase replaces
381
410
  // this body with a specialized one (see owning_buffer_specialize.ts);
382
411
  // this raw form is correct for trivially-copyable elements only. NOT
@@ -464,7 +493,7 @@ pub struct Buffer<T> {
464
493
 
465
494
  // Store into a T_SIZE-sized slot, overwriting the previous value. For
466
495
  // trivially-destructible value structs this is a plain overwrite. For
467
- // owning value structs (with string fields), the build phase replaces this
496
+ // mv value structs (with string fields), the build phase replaces this
468
497
  // body with a specialised version that calls T_destroy on the old slot
469
498
  // value, then deep-copies (strdup per string field). See
470
499
  // owning_buffer_specialize.ts (both backends). ClassBuffer.replace
@@ -512,12 +541,12 @@ pub struct Buffer<T> {
512
541
 
513
542
  // Move-taking write, mirroring `List.set`: the caller's value is
514
543
  // consumed and an independent copy is installed in the slot (replace
515
- // deep-copies owning elements). The owning entry point a caller uses
544
+ // deep-copies mv elements). The mv entry point a caller uses
516
545
  // when it wants to hand over a value — `replace`'s by-value parameter
517
- // cannot accept the `move` keyword, so a borrow being transferred
546
+ // cannot accept the `mv` keyword, so a borrow being transferred
518
547
  // (e.g. a loaded element) must go through here rather than be bound to
519
548
  // a freed local.
520
- pub func set = (ref self, int i: i >= 0 && i < self.cap, move T value) {
549
+ pub func set = (ref self, int i: i >= 0 && i < self.cap, mv T value) {
521
550
  self.replace(i, value)
522
551
  }
523
552
 
@@ -526,7 +555,7 @@ pub struct Buffer<T> {
526
555
  // ownership-transferring primitive behind backward-shift deletion
527
556
  // (Map/Set.remove) — unlike store, which gives the slot its own deep
528
557
  // copy and leaves the source slot intact, a shift transfers the source's
529
- // heap pointers wholesale. For owning elements (string / value structs
558
+ // heap pointers wholesale. For mv elements (string / value structs
530
559
  // with string fields) the build replaces this body with a specialized
531
560
  // version that also reclaims dst's previous value first (see
532
561
  // owning_buffer_specialize.ts); this raw form is correct for
@@ -555,7 +584,7 @@ pub struct Buffer<T> {
555
584
  b.eq .Lbuffer_shift_T_end
556
585
  cmp x3, #8
557
586
  b.gt .Lbuffer_shift_T_copy
558
- // Width-matched move: an 8-byte access on a sub-8 element would
587
+ // Width-matched mv: an 8-byte access on a sub-8 element would
559
588
  // clobber the following slot (and run past the slab's end).
560
589
  cmp x3, #1
561
590
  b.eq .Lbuffer_shift_T_1
@@ -597,7 +626,7 @@ pub struct Buffer<T> {
597
626
  ```
598
627
  }
599
628
 
600
- // A non-owning (ptr, len) slice [start, end) over this buffer's element
629
+ // A non-mv (ptr, len) slice [start, end) over this buffer's element
601
630
  // storage, returned as a `view T`. It borrows from self: it may not outlive
602
631
  // self's scope and is invalidated if self is reassigned. This is the single
603
632
  // primitive every other slice (Array<T>, List<T>, user containers) builds
@@ -626,13 +655,13 @@ pub struct Buffer<T> {
626
655
  ```
627
656
  }
628
657
 
629
- // Internal: zeroes slots without reclaiming owning elements.
658
+ // Internal: zeroes slots without reclaiming mv elements.
630
659
  internal inline func zero = (ref self, int len) {
631
660
  memset(self.data, 0, len * T_SIZE)
632
661
  }
633
662
 
634
663
  // An independent copy: fresh slab, per-element deep copies. Each slot
635
- // round-trips load→replace through a local, so owning element types get
664
+ // round-trips load→replace through a local, so mv element types get
636
665
  // the same treatment a List<T>.copy slot does (the load materializes an
637
666
  // owned copy, replace gives the destination its own). Class elements
638
667
  // never reach this body (a `Buffer<T>` with T a class monomorphizes to
@@ -643,10 +672,10 @@ pub struct Buffer<T> {
643
672
  dst.alloc(self.cap)
644
673
  var i = 0
645
674
  while i < self.cap {
646
- // Bind the loaded element and hand it to `set` (move): for a
675
+ // Bind the loaded element and hand it to `set` (mv): for a
647
676
  // string element load returns a BORROW of the source slot, and
648
- // the move transfers it into the write without a scope-exit
649
- // reclaim (which would free the source's buffer); for an owning
677
+ // the mv transfers it into the write without a scope-exit
678
+ // reclaim (which would free the source's buffer); for a mv
650
679
  // struct element load returns an owned copy that transfers the
651
680
  // same way. Mirrors List.copy's `var T v = self.at(i)` +
652
681
  // `dst.push(v)`.
@@ -2,8 +2,8 @@
2
2
  // tasks. Unbounded, FIFO, blocking receive.
3
3
  //
4
4
  // The queue node's payload is three words wide: every message carries a
5
- // (value, len, kind) triple. `send`/`receive` move uint64 values (len and
6
- // kind stay 0); `send_string`/`receive_string` move fat strings (kind = 1)
5
+ // (value, len, kind) triple. `send`/`receive` mv uint64 values (len and
6
+ // kind stay 0); `send_string`/`receive_string` mv fat strings (kind = 1)
7
7
  // without truncating the len half. `#destroy` frees only string payloads —
8
8
  // a raw uint64 payload is a value, not a pointer. A typed Channel<T>
9
9
  // wrapper can come later — the storage story is identical, only the
@@ -19,10 +19,22 @@
19
19
  // Default stance in Nomen is "no shared mutable state" — channels are the
20
20
  // preferred way for tasks to communicate. See ASYNC.md.
21
21
 
22
+ // Channel is an OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 3 — the shape
23
+ // menu): every field is an opaque handle/counter word, so the value is
24
+ // movable and its `#destroy` closes what the handles name. Sharing one
25
+ // across tasks rides the checked region borrows (`async { }` — the join
26
+ // bounds the borrow) or a transfer (`mv ch` — the receiver owns the
27
+ // queue). The send/receive methods take the receiver bare (struct receivers
28
+ // travel by address), so queue mutations land in the one shared instance,
29
+ // never in a copy.
30
+ //
31
+ // Default stance in Nomen is "no shared mutable state" — channels are the
32
+ // preferred way for tasks to communicate. See ASYNC.md.
33
+
22
34
  /**
23
35
  * A thread-safe, blocking FIFO queue for passing values between tasks
24
36
  **/
25
- pub class Channel: Sendable {
37
+ pub mv struct Channel {
26
38
  pub var uint64 mu = 0
27
39
  pub var uint64 not_empty_cv = 0
28
40
  pub var uint64 head = 0
@@ -44,13 +56,17 @@ pub class Channel: Sendable {
44
56
  ```
45
57
  ```
46
58
  #arch: c
47
- self->mu = (unsigned long long)malloc(sizeof(pthread_mutex_t));
48
- self->not_empty_cv = (unsigned long long)malloc(sizeof(pthread_cond_t));
49
- pthread_mutex_init((pthread_mutex_t *)self->mu, NULL);
50
- pthread_cond_init((pthread_cond_t *)self->not_empty_cv, NULL);
51
- self->head = 0;
52
- self->tail = 0;
53
- self->waiters = 0;
59
+ // The constructor's `self` is the INLINE instance (a local value in
60
+ // the C lowering — methods take the pointer form, the ctor does not),
61
+ // so this body uses the `.` accessor; the aarch64 body writes through
62
+ // x19 = &instance as always.
63
+ self.mu = (unsigned long long)malloc(sizeof(pthread_mutex_t));
64
+ self.not_empty_cv = (unsigned long long)malloc(sizeof(pthread_cond_t));
65
+ pthread_mutex_init((pthread_mutex_t *)self.mu, NULL);
66
+ pthread_cond_init((pthread_cond_t *)self.not_empty_cv, NULL);
67
+ self.head = 0;
68
+ self.tail = 0;
69
+ self.waiters = 0;
54
70
  ```
55
71
  ```
56
72
  #arch: aarch64
@@ -251,7 +267,7 @@ pub class Channel: Sendable {
251
267
  // (the node's copy is moved out — the payload leaves the channel, and a
252
268
  // second receive of the same message is not possible). The fat (ptr, len)
253
269
  // pair survives intact. Pair with send_string.
254
- pub func receive_string = (self, move out string) {
270
+ pub func receive_string = (self, mv out string) {
255
271
  ```
256
272
  #arch: c
257
273
  pthread_mutex_lock((pthread_mutex_t *)self->mu);
@@ -95,15 +95,15 @@ pub struct ClassBuffer<T> {
95
95
  }
96
96
 
97
97
  // Store the owned class pointer `val` into slot `i`, which MUST be fresh
98
- // (calloc'd, or zeroed by move/move_int). Takes OWNERSHIP of `val`
99
- // (`move`): the slot's #destroy reclaims the instance, so the caller must
98
+ // (calloc'd, or zeroed by mv/move_int). Takes OWNERSHIP of `val`
99
+ // (`mv`): the slot's #destroy reclaims the instance, so the caller must
100
100
  // not free its copy — a fresh constructor result transfers here directly,
101
101
  // and a local must be moved (its own cleanup is suppressed at the call
102
102
  // site). This is a plain pointer store — it does NOT destroy/free the
103
103
  // slot's previous occupant, so a second `store` at an occupied index
104
104
  // leaks that instance. Use replace (or replace_int) to overwrite a live
105
105
  // slot.
106
- internal inline func store = (ref self, int i: i >= 0 && i < self.cap, move T val: val != 0) {
106
+ internal inline func store = (ref self, int i: i >= 0 && i < self.cap, mv T val: val != 0) {
107
107
  ```
108
108
  #arch: c
109
109
  ((long*)(unsigned long long)self->data)[i] = (long)val;
@@ -118,14 +118,14 @@ pub struct ClassBuffer<T> {
118
118
  }
119
119
 
120
120
  // Move a class pointer out of a slot: return it and zero the slot so the
121
- // buffer no longer references it. Declared `move out T` so the borrow
121
+ // buffer no longer references it. Declared `mv out T` so the borrow
122
122
  // checker treats the result as OWNED — the slot is relinquished, so the
123
- // caller is the sole remaining owner. This is the owning-extract primitive
123
+ // caller is the sole remaining owner. This is the mv-extract primitive
124
124
  // (parallel to List.pop); use it (not load) when transferring ownership
125
- // out of a ClassBuffer slot, or moving a value into a fresh owning
125
+ // out of a ClassBuffer slot, or moving a value into a fresh mv
126
126
  // container — load returns a BORROW (the slot is unchanged) and storing
127
127
  // it elsewhere would create shared ownership (double-free at destroy).
128
- inline func move = (ref self, int i: i >= 0 && i < self.cap, move out T) {
128
+ inline func move = (ref self, int i: i >= 0 && i < self.cap, mv out T) {
129
129
  ```
130
130
  #arch: c
131
131
  long *slots = (long*)(unsigned long long)self->data;
@@ -143,13 +143,19 @@ pub struct ClassBuffer<T> {
143
143
  ```
144
144
  }
145
145
 
146
- // Apply `f` to slot `i` in place — the owning-counterpart of Buffer's
146
+ // Apply `f` to slot `i` in place — the mv-counterpart of Buffer's
147
147
  // modify for class elements. `f` receives the current instance pointer
148
- // as a borrow and returns the replacement instance (fresh, or the same
149
- // pointer); the primitive frees the displaced instance (destroy + free)
150
- // unless `f` returned it. Storing the returned instance raw is sound:
151
- // the slot takes sole ownership and `f`'s return is not retained
152
- // elsewhere. NOT `inline`: the body calls through the fn pointer.
148
+ // as a MOVE argument — the only expressible parameter mode for a
149
+ // class-tier element (a bare `Box<T>` param is rejected — B2/T2 — and a
150
+ // `ref` param's &binding lowering mismatches this raw call) — so the
151
+ // displaced instance's reclamation is the CALLEE's mv-param contract:
152
+ // a function whose parameter is not returned frees it at its own exit
153
+ // (the C auto-free registration / the aarch64 return-compare arm). The
154
+ // body frees nothing — freeing here too was a double free (the
155
+ // aarch64 callee already reclaimed it; the audit caught the stale
156
+ // free). Storing the returned instance raw is sound: the slot takes
157
+ // sole ownership and `f`'s return is not retained elsewhere. NOT
158
+ // `inline`: the body calls through the fn pointer.
153
159
  func modify = (ref self, int i: i >= 0 && i < self.cap, func(T, out T) f) {
154
160
  ```
155
161
  #arch: c
@@ -157,15 +163,13 @@ pub struct ClassBuffer<T> {
157
163
  void *old = (void*)slots[i];
158
164
  void *new_value = (void*)((void *(*)(void *, void *))f->code)(f->env, old);
159
165
  slots[i] = (long)new_value;
160
- if (old != new_value) {
161
- T_destroy(old);
162
- free(old);
163
- }
164
166
  ```
165
167
  ```
166
168
  #arch: aarch64
167
169
  // x19 = self, x1 = i, x2 = f (a closure descriptor — env goes in x0,
168
170
  // the old slot value shifts to x1). Class slots are one pointer wide.
171
+ // `old` is MOVED into f — the callee's mv-param contract reclaims
172
+ // it; this body frees nothing.
169
173
  stp x20, x21, [sp, #-16]!
170
174
  stp x22, x23, [sp, #-16]!
171
175
  stp x24, x25, [sp, #-16]!
@@ -178,15 +182,7 @@ pub struct ClassBuffer<T> {
178
182
  ldr x1, [x20]
179
183
  blr x24
180
184
  mov x23, x0
181
- ldr x9, [x20]
182
185
  str x23, [x20]
183
- cmp x9, x23
184
- b.eq .Lcb_modify_T_done
185
- mov x0, x9
186
- bl T_destroy
187
- mov x0, x9
188
- bl _free
189
- .Lcb_modify_T_done:
190
186
  ldp x24, x25, [sp], #16
191
187
  ldp x22, x23, [sp], #16
192
188
  ldp x20, x21, [sp], #16
@@ -262,8 +258,8 @@ pub struct ClassBuffer<T> {
262
258
  // free) then store the new one. Used by List.set so the uniform API
263
259
  // preserves ownership for class elements.
264
260
  // Overwrite a live slot: destroy + free the displaced instance, then take
265
- // OWNERSHIP of `val` (`move`) — same transfer rule as store.
266
- func replace = (ref self, int i: i >= 0 && i < self.cap, move T val: val != 0) {
261
+ // OWNERSHIP of `val` (`mv`) — same transfer rule as store.
262
+ func replace = (ref self, int i: i >= 0 && i < self.cap, mv T val: val != 0) {
267
263
  ```
268
264
  #arch: c
269
265
  long *slots = (long*)(unsigned long long)self->data;
@@ -343,7 +339,7 @@ pub struct ClassBuffer<T> {
343
339
  ```
344
340
  }
345
341
 
346
- // A non-owning (ptr, len) slice [start, end) over this buffer's class
342
+ // A non-mv (ptr, len) slice [start, end) over this buffer's class
347
343
  // pointers, returned as a `view T` (T is a class, so each element is an
348
344
  // 8-byte pointer). Borrows from self — invalidated on reassignment. Mirrors
349
345
  // Buffer.slice; ClassBuffer stores 8-byte slots, so the element width is 8.
@@ -70,8 +70,8 @@ pub struct Console {
70
70
  }
71
71
 
72
72
  // Read one line from stdin (newline stripped). The raw body mallocs the
73
- // buffer — `move out string` transfers ownership to the caller.
74
- pub func read_line = (move out string) {
73
+ // buffer — `mv out string` transfers ownership to the caller.
74
+ pub func read_line = (mv out string) {
75
75
  ```
76
76
  #arch: c
77
77
  int cap = 16;
@@ -153,8 +153,8 @@ pub struct Console {
153
153
  }
154
154
 
155
155
  // The platform name ("macos" / "ios" / …). The raw body strdups a static
156
- // string — `move out string` transfers the owned copy to the caller.
157
- pub func platform = (move out string) {
156
+ // string — `mv out string` transfers the owned copy to the caller.
157
+ pub func platform = (mv out string) {
158
158
  ```
159
159
  #arch: c
160
160
  #platform: macos
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * A push-button control that triggers an action when clicked
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * single field is an AppKit handle, so the value is movable and its
6
+ * `#destroy` releases what the handle names. The constructor's `self` is
7
+ * the inline instance (the `.` accessor); methods keep the pointer form.
3
8
  **/
4
- pub class Button: Control {
9
+ pub mv struct Button : Control {
5
10
  var uint64 handle = 0
6
11
 
7
12
  pub func #init = (self, Window window, string title) {
@@ -22,7 +27,7 @@ pub class Button: Control {
22
27
  (id)window->handle, sel_registerName("contentView"));
23
28
  ((void(*)(id, SEL, id))objc_msgSend)(
24
29
  contentView, sel_registerName("addSubview:"), btn);
25
- self->handle = (uint64_t)btn;
30
+ self.handle = (uint64_t)btn;
26
31
  ```
27
32
  ```
28
33
  #arch: aarch64_use_c
@@ -61,7 +66,7 @@ pub class Button: Control {
61
66
  sel_registerName("view"));
62
67
  ((void(*)(id, SEL, id))objc_msgSend)(
63
68
  parentView, sel_registerName("addSubview:"), btn);
64
- self->handle = (uint64_t)btn;
69
+ self.handle = (uint64_t)btn;
65
70
  ```
66
71
  ```
67
72
  #arch: aarch64_use_c
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * A toggle control with a title and checked/hidden state
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * single field is an AppKit handle, so the value is movable and its
6
+ * `#destroy` releases what the handle names. The constructor's `self` is
7
+ * the inline instance (the `.` accessor); methods keep the pointer form.
3
8
  **/
4
- pub class CheckBox: Control {
9
+ pub mv struct CheckBox : Control {
5
10
  var uint64 handle = 0
6
11
 
7
12
  pub func #init = (self, Window window) {
@@ -20,7 +25,7 @@ pub class CheckBox: Control {
20
25
  (id)window->handle, sel_registerName("contentView"));
21
26
  ((void(*)(id, SEL, id))objc_msgSend)(
22
27
  contentView, sel_registerName("addSubview:"), cb);
23
- self->handle = (uint64_t)cb;
28
+ self.handle = (uint64_t)cb;
24
29
  ```
25
30
  ```
26
31
  #arch: aarch64_use_c
@@ -52,7 +57,7 @@ pub class CheckBox: Control {
52
57
  sel_registerName("view"));
53
58
  ((void(*)(id, SEL, id))objc_msgSend)(
54
59
  parentView, sel_registerName("addSubview:"), cb);
55
- self->handle = (uint64_t)cb;
60
+ self.handle = (uint64_t)cb;
56
61
  ```
57
62
  ```
58
63
  #arch: aarch64_use_c
@@ -241,6 +241,9 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
241
241
  /**
242
242
  * A flexbox-style container that measures and arranges its child controls.
243
243
  *
244
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
245
+ * SoA buffers mv with the value and a scope-exit destroy reclaims them.
246
+ * *
244
247
  * Conforms to `Control`: `measure(BoxConstraints)` measures the whole subtree,
245
248
  * `set_frame` arranges it into a rectangle, and `intrinsic_size` reports the
246
249
  * unbounded-content size. The handle-based `add` API and the SoA engine are
@@ -248,7 +251,7 @@ pub func native_intrinsic = (uint64 handle, out [int, int]) {
248
251
  * so a `Container` can also be driven polymorphically as a `Control` (passed to
249
252
  * a `Control`-taking function, stored in a `ClassBuffer<Control>`, etc.).
250
253
  **/
251
- pub class Container: Control {
254
+ pub mv struct Container : Control {
252
255
  var kinds = Buffer<int>()
253
256
  // Per-leaf requested size, stored as a (kind, value) pair per axis. The
254
257
  // kind is one of LEN_* (auto/fixed/percent/fill); the value is the pixel
@@ -1454,10 +1457,12 @@ pub class Container: Control {
1454
1457
  // nomen_layout_thunk is a free function (defined in Nomen below) that
1455
1458
  // forwards to Container.layout — exported for C linkage on both
1456
1459
  // backends, unlike the layout method itself. It takes the Container by
1457
- // `ref` (mutable reference): as a `class`, `ref Container` lowers to
1458
- // `struct Container **` (reference to the instance pointer), so the
1459
- // callback passes the address of the stored instance pointer.
1460
- extern void nomen_layout_thunk(struct Container**, struct Window*);
1460
+ // `ref` (mutable reference): as a mv struct, `ref Container` lowers
1461
+ // to `struct Container *` (the address of the value), so the callback
1462
+ // passes the stored instance address directly. The address must stay
1463
+ // valid for as long as the delegate is installed — an app-lifetime
1464
+ // Container binding (or a Box<Container>).
1465
+ extern void nomen_layout_thunk(struct Container*, struct Window*);
1461
1466
  static void *g_resize_grid = 0;
1462
1467
  static void *g_resize_win = 0;
1463
1468
  void nomen_set_resize_target(void *grid, void *win) {
@@ -1467,7 +1472,7 @@ pub class Container: Control {
1467
1472
  void nomen_window_did_resize(id self, SEL cmd, id notification) {
1468
1473
  (void)self; (void)cmd; (void)notification;
1469
1474
  if (g_resize_grid && g_resize_win) {
1470
- nomen_layout_thunk((struct Container**)&g_resize_grid, (struct Window*)g_resize_win);
1475
+ nomen_layout_thunk((struct Container*)g_resize_grid, (struct Window*)g_resize_win);
1471
1476
  }
1472
1477
  }
1473
1478
  ```
@@ -1480,10 +1485,12 @@ pub class Container: Control {
1480
1485
  // nomen_layout_thunk is a free function (defined in Nomen below) that
1481
1486
  // forwards to Container.layout — exported for C linkage on both
1482
1487
  // backends, unlike the layout method itself. It takes the Container by
1483
- // `ref` (mutable reference): as a `class`, `ref Container` lowers to
1484
- // `struct Container **` (reference to the instance pointer), so the
1485
- // callback passes the address of the stored instance pointer.
1486
- extern void nomen_layout_thunk(struct Container**, struct Window*);
1488
+ // `ref` (mutable reference): as a mv struct, `ref Container` lowers
1489
+ // to `struct Container *` (the address of the value), so the callback
1490
+ // passes the stored instance address directly. The address must stay
1491
+ // valid for as long as the delegate is installed — an app-lifetime
1492
+ // Container binding (or a Box<Container>).
1493
+ extern void nomen_layout_thunk(struct Container*, struct Window*);
1487
1494
  static void *g_resize_grid = 0;
1488
1495
  static void *g_resize_win = 0;
1489
1496
  void nomen_set_resize_target(void *grid, void *win) {
@@ -1493,7 +1500,7 @@ pub class Container: Control {
1493
1500
  void nomen_window_did_resize(id self, SEL cmd, id notification) {
1494
1501
  (void)self; (void)cmd; (void)notification;
1495
1502
  if (g_resize_grid && g_resize_win) {
1496
- nomen_layout_thunk((struct Container**)&g_resize_grid, (struct Window*)g_resize_win);
1503
+ nomen_layout_thunk((struct Container*)g_resize_grid, (struct Window*)g_resize_win);
1497
1504
  }
1498
1505
  }
1499
1506
  ```
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  * A flat, buffer-backed layout tree — nodes stored in parallel arrays for the layout engine
6
6
  **/
7
- pub struct Layout {
7
+ pub mv struct Layout {
8
8
  var kinds = Buffer<int>() // 0=leaf, 1=vstack, 2=hstack
9
9
  var ws = Buffer<int>() // intrinsic width (leaf) or 0
10
10
  var hs = Buffer<int>() // intrinsic height (leaf) or 0
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * A read-only text label control
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * AppKit handle plus the cached label text mv with the value, and the
6
+ * `#destroy` releases what the handle names. The constructor's `self` is
7
+ * the inline instance (the `.` accessor); methods keep the pointer form.
3
8
  **/
4
- pub class Text: Control {
9
+ pub mv struct Text : Control {
5
10
  var uint64 handle = 0
6
11
  var text = ""
7
12
 
@@ -25,7 +30,7 @@ pub class Text: Control {
25
30
  (id)window->handle, sel_registerName("contentView"));
26
31
  ((void(*)(id, SEL, id))objc_msgSend)(
27
32
  contentView, sel_registerName("addSubview:"), label);
28
- self->handle = (uint64_t)label;
33
+ self.handle = (uint64_t)label;
29
34
  ```
30
35
  ```
31
36
  #arch: aarch64_use_c
@@ -67,7 +72,7 @@ pub class Text: Control {
67
72
  sel_registerName("view"));
68
73
  ((void(*)(id, SEL, id))objc_msgSend)(
69
74
  parentView, sel_registerName("addSubview:"), label);
70
- self->handle = (uint64_t)label;
75
+ self.handle = (uint64_t)label;
71
76
  ```
72
77
  ```
73
78
  #arch: aarch64_use_c
@@ -93,7 +98,7 @@ pub class Text: Control {
93
98
  }
94
99
 
95
100
  pub func set_text = (ref self, string text) {
96
- self.text = text
101
+ self.text = text.copy()
97
102
  ```
98
103
  #arch: c
99
104
  #platform: macos
@@ -1,7 +1,12 @@
1
1
  /**
2
2
  * An editable single-line text input control
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * single field is an AppKit handle, so the value is movable and its
6
+ * `#destroy` releases what the handle names. The constructor's `self` is
7
+ * the inline instance (the `.` accessor); methods keep the pointer form.
3
8
  **/
4
- pub class TextBox: Control {
9
+ pub mv struct TextBox : Control {
5
10
  var uint64 handle = 0
6
11
 
7
12
  pub func #init = (self, Window window) {
@@ -30,7 +35,7 @@ pub class TextBox: Control {
30
35
  (id)window->handle, sel_registerName("contentView"));
31
36
  ((void(*)(id, SEL, id))objc_msgSend)(
32
37
  contentView, sel_registerName("addSubview:"), field);
33
- self->handle = (uint64_t)field;
38
+ self.handle = (uint64_t)field;
34
39
  ```
35
40
  ```
36
41
  #arch: aarch64_use_c
@@ -74,7 +79,7 @@ pub class TextBox: Control {
74
79
  sel_registerName("view"));
75
80
  ((void(*)(id, SEL, id))objc_msgSend)(
76
81
  parentView, sel_registerName("addSubview:"), field);
77
- self->handle = (uint64_t)field;
82
+ self.handle = (uint64_t)field;
78
83
  ```
79
84
  ```
80
85
  #arch: aarch64_use_c
@@ -1,7 +1,14 @@
1
1
  /**
2
2
  * A top-level native window that hosts controls and dispatches events
3
+ *
4
+ * An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
5
+ * single field is an AppKit handle, so the value is movable and its
6
+ * `#destroy` releases what the handle names. The methods take the receiver
7
+ * bare (struct receivers travel by address — the raw bodies keep the
8
+ * pointer form); the constructor's `self` is the inline instance (the `.`
9
+ * accessor).
3
10
  **/
4
- pub class Window: Control {
11
+ pub mv struct Window : Control {
5
12
  var uint64 handle = 0
6
13
 
7
14
  pub func #init = (self, string title, int width, int height) {
@@ -32,7 +39,7 @@ pub class Window: Control {
32
39
  id cv = ((id(*)(id, SEL))objc_msgSend)(win, sel_registerName("contentView"));
33
40
  ((void(*)(id, SEL, unsigned long))objc_msgSend)(cv, sel_registerName("setAutoresizingMask:"), 18UL);
34
41
  ((void(*)(id, SEL, BOOL))objc_msgSend)(cv, sel_registerName("setAutoresizesSubviews:"), 1);
35
- self->handle = (uint64_t)win;
42
+ self.handle = (uint64_t)win;
36
43
  ```
37
44
  ```
38
45
  #arch: aarch64_use_c
@@ -71,7 +78,7 @@ pub class Window: Control {
71
78
  sel_registerName("initWithFrame:"),
72
79
  ((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, (double)width, (double)height));
73
80
  ((void(*)(id, SEL))objc_msgSend)(win, sel_registerName("makeKeyAndVisible"));
74
- self->handle = (uint64_t)win;
81
+ self.handle = (uint64_t)win;
75
82
  ```
76
83
  ```
77
84
  #arch: aarch64_use_c
@@ -29,6 +29,10 @@
29
29
  // reads the packed handles from the instance's fields and drives the
30
30
  // scheduler. The runtime (scheduler, context switch) lives in the build's
31
31
  // emitted companion C — see build_fiber_spawn.
32
+ //
33
+ // Fiber is an OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 2 — the shape
34
+ // menu), exactly like Thread: handle fields only, movable, `#destroy`
35
+ // enforces must-start.
32
36
 
33
37
  // The launch surface's return type (ASYNC.md: the dependency is
34
38
  // declared by the library file, not inferred from user-source tokens).
@@ -37,7 +41,7 @@ import Task
37
41
  /**
38
42
  * A stackful coroutine: lightweight, cooperatively scheduled, parks instead of blocking
39
43
  **/
40
- pub class Fiber<T> : Sendable, Spawnable<T> {
44
+ pub mv struct Fiber<T> : Spawnable<T> {
41
45
  // The construction hook (see Thread.nm): the deferred-call special form.
42
46
  #spawn = () {
43
47
  }
@@ -67,7 +71,7 @@ pub class Fiber<T> : Sendable, Spawnable<T> {
67
71
  // out of the instance (started; #destroy no-ops), return the handle.
68
72
  // While the fiber waits, it parks and frees its worker instead of
69
73
  // blocking it.
70
- pub func start = (ref self, move out Task<T>) {
74
+ pub func start = (ref self, mv out Task<T>) {
71
75
  ```
72
76
  #arch: c
73
77
  struct nomen_future *_f = (struct nomen_future *)self->future;