nomen-lang 0.6.13 → 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.
- package/NOMEN_AGENTS.md +27 -13
- package/audit_runtime.c +2 -0
- package/core/System/Arena.nm +4 -4
- package/core/System/Array.nm +108 -78
- package/core/System/Atomic.nm +81 -0
- package/core/System/Awaitable.nm +12 -5
- package/core/System/BigInt.nm +1 -1
- package/core/System/Box.nm +32 -0
- package/core/System/Buffer.nm +18 -18
- package/core/System/Channel.nm +27 -11
- package/core/System/ClassBuffer.nm +24 -28
- package/core/System/Console.nm +4 -4
- package/core/System/Controls/Button.nm +8 -3
- package/core/System/Controls/CheckBox.nm +8 -3
- package/core/System/Controls/Container.nm +18 -11
- package/core/System/Controls/Layout.nm +1 -1
- package/core/System/Controls/Text.nm +9 -4
- package/core/System/Controls/TextBox.nm +8 -3
- package/core/System/Controls/Window.nm +10 -3
- package/core/System/Fiber.nm +6 -2
- package/core/System/Graph.nm +2 -2
- package/core/System/Init.nm +2 -2
- package/core/System/LinkedList.nm +2 -2
- package/core/System/List.nm +7 -7
- package/core/System/Map.nm +10 -7
- package/core/System/Math.nm +1 -1
- package/core/System/Mutex.nm +14 -2
- package/core/System/Random.nm +7 -1
- package/core/System/Result.nm +1 -1
- package/core/System/Sendable.nm +2 -2
- package/core/System/Set.nm +6 -6
- package/core/System/Spawnable.nm +9 -9
- package/core/System/Stream/Directory.nm +1 -2
- package/core/System/Stream/File.nm +8 -9
- package/core/System/Stream/Http.nm +2 -3
- package/core/System/Stream/Tcp.nm +13 -8
- package/core/System/String.nm +22 -12
- package/core/System/StringBuilder.nm +2 -2
- package/core/System/Task.nm +21 -29
- package/core/System/Test.nm +10 -4
- package/core/System/Text/CharIndex.nm +2 -3
- package/core/System/Text/Json.nm +8 -12
- package/core/System/Text/JsonTree.nm +4 -4
- package/core/System/Text/Regex.nm +7 -7
- package/core/System/Text/Utf8.nm +2 -3
- package/core/System/Thread.nm +9 -4
- package/core/System/Tree.nm +2 -2
- package/core/System/Viewable.nm +2 -2
- package/core/System/WeakHandle.nm +56 -0
- package/core/System/bool.nm +1 -1
- package/core/System/char.nm +1 -1
- package/core/System/float.nm +1 -1
- package/core/System/float32.nm +1 -1
- package/core/System/float64.nm +1 -1
- package/core/System/int.nm +1 -1
- package/core/System/int16.nm +1 -1
- package/core/System/int32.nm +1 -1
- package/core/System/int64.nm +1 -1
- package/core/System/int8.nm +1 -1
- package/core/System/ufloat.nm +1 -1
- package/core/System/ufloat32.nm +1 -1
- package/core/System/ufloat64.nm +1 -1
- package/core/System/uint.nm +1 -1
- package/core/System/uint16.nm +1 -1
- package/core/System/uint32.nm +1 -1
- package/core/System/uint64.nm +1 -1
- package/core/System/uint8.nm +1 -1
- package/core/docs/System/Result.md +2 -2
- package/dist/index.mjs +29031 -25546
- package/package.json +1 -1
- package/src/test.ts +26 -11
package/core/System/Channel.nm
CHANGED
|
@@ -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`
|
|
6
|
-
// kind stay 0); `send_string`/`receive_string`
|
|
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
|
|
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
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self
|
|
52
|
-
self
|
|
53
|
-
self
|
|
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,
|
|
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
|
|
99
|
-
// (`
|
|
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,
|
|
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 `
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
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` (`
|
|
266
|
-
func replace = (ref self, int i: i >= 0 && i < self.cap,
|
|
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-
|
|
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.
|
package/core/System/Console.nm
CHANGED
|
@@ -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 — `
|
|
74
|
-
pub func read_line = (
|
|
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 — `
|
|
157
|
-
pub func platform = (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1458
|
-
// `struct Container
|
|
1459
|
-
//
|
|
1460
|
-
|
|
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
|
|
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
|
|
1484
|
-
// `struct Container
|
|
1485
|
-
//
|
|
1486
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
81
|
+
self.handle = (uint64_t)win;
|
|
75
82
|
```
|
|
76
83
|
```
|
|
77
84
|
#arch: aarch64_use_c
|
package/core/System/Fiber.nm
CHANGED
|
@@ -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
|
|
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,
|
|
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;
|
package/core/System/Graph.nm
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* A graph of values connected by edges
|
|
8
8
|
**/
|
|
9
|
-
pub struct Graph<T>: Enumerable {
|
|
9
|
+
pub mv struct Graph<T>: Enumerable {
|
|
10
10
|
var values = Buffer<T>()
|
|
11
11
|
var head_edge = Buffer<int>()
|
|
12
12
|
var edge_target = Buffer<int>()
|
|
@@ -14,7 +14,7 @@ pub struct Graph<T>: Enumerable {
|
|
|
14
14
|
var node_count = 0
|
|
15
15
|
var edge_count = 0
|
|
16
16
|
|
|
17
|
-
pub func add_node = (ref self,
|
|
17
|
+
pub func add_node = (ref self, mv T value) {
|
|
18
18
|
var int idx = self.node_count
|
|
19
19
|
self.values.grow(idx + 1)
|
|
20
20
|
self.values.store(idx, value)
|
package/core/System/Init.nm
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Program startup state — the argument count and argument list passed to `main`,
|
|
3
3
|
* plus whether stdout is a terminal (for renderer selection).
|
|
4
4
|
**/
|
|
5
|
-
pub struct Init {
|
|
5
|
+
pub mv struct Init {
|
|
6
6
|
var int argc
|
|
7
7
|
var string[16] args
|
|
8
8
|
var bool is_tty
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// FFI: the C library's decimal-string parser (stdlib.h).
|
|
12
|
-
|
|
12
|
+
foreign func atoi = (string s, out int)
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Parses a decimal string into an int
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* A doubly-linked list of values
|
|
8
8
|
**/
|
|
9
|
-
pub struct LinkedList<T>: Enumerable {
|
|
9
|
+
pub mv struct LinkedList<T>: Enumerable {
|
|
10
10
|
var values = Buffer<T>()
|
|
11
11
|
var nexts = Buffer<int>()
|
|
12
12
|
var prevs = Buffer<int>()
|
|
13
13
|
var int head = -1
|
|
14
14
|
var count = 0
|
|
15
15
|
|
|
16
|
-
pub func add = (ref self,
|
|
16
|
+
pub func add = (ref self, mv T value) {
|
|
17
17
|
var int idx = self.count
|
|
18
18
|
self.values.grow(idx + 1)
|
|
19
19
|
self.values.store(idx, value)
|
package/core/System/List.nm
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A growable, ordered list of values (`push`/`pop`/`at`)
|
|
3
3
|
**/
|
|
4
|
-
pub struct List<T>: Viewable {
|
|
4
|
+
pub mv struct List<T>: Viewable {
|
|
5
5
|
var length = 0
|
|
6
6
|
var items = Buffer<T>()
|
|
7
7
|
|
|
8
|
-
pub func push = (ref self,
|
|
8
|
+
pub func push = (ref self, mv T value) {
|
|
9
9
|
if self.length >= self.items.cap {
|
|
10
10
|
var new_cap = 4
|
|
11
11
|
var int old_cap = self.items.cap
|
|
@@ -18,7 +18,7 @@ pub struct List<T>: Viewable {
|
|
|
18
18
|
self.length += 1
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
pub func pop = (ref self,
|
|
21
|
+
pub func pop = (ref self, mv out T) {
|
|
22
22
|
if self.length <= 0 {
|
|
23
23
|
return self.items.move(0)
|
|
24
24
|
}
|
|
@@ -51,13 +51,13 @@ pub struct List<T>: Viewable {
|
|
|
51
51
|
panic("index out of range")
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
// A non-
|
|
54
|
+
// A non-mv `view T` over [start, end). Delegates to the backing Buffer's
|
|
55
55
|
// #arch slice primitive — no #arch code here. Borrows from self.
|
|
56
56
|
pub func slice = (self, int start: start >= 0, int end: end >= start, out view T) {
|
|
57
57
|
return self.items.slice(start, end)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
pub func set = (ref self, int i: i >= 0 && i < self.length,
|
|
60
|
+
pub func set = (ref self, int i: i >= 0 && i < self.length, mv T value) {
|
|
61
61
|
self.items.replace(i, value)
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -65,7 +65,7 @@ pub struct List<T>: Viewable {
|
|
|
65
65
|
// for indices that can't be proven at compile time (cross-module calls
|
|
66
66
|
// can never discharge `set`'s parameter constraint) and out-of-range is
|
|
67
67
|
// a bug, not a case.
|
|
68
|
-
pub func set_or_panic = (ref self, int i,
|
|
68
|
+
pub func set_or_panic = (ref self, int i, mv T value) {
|
|
69
69
|
if i >= 0 && i < self.length {
|
|
70
70
|
self.set(i, value)
|
|
71
71
|
return
|
|
@@ -74,7 +74,7 @@ pub struct List<T>: Viewable {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
// A deep copy: a fresh List<T> with an independent copy of every element.
|
|
77
|
-
// For
|
|
77
|
+
// For mv element types (strings, mv value structs) each slot in the
|
|
78
78
|
// copy owns its own heap data (Buffer deep-copies on store), so the source
|
|
79
79
|
// and the copy share nothing. Not available for class/trait element types
|
|
80
80
|
// (the copy would share the stored instances — the checker rejects it).
|
package/core/System/Map.nm
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* it is correct for negative hashes too: two's-complement `&` already lands
|
|
9
9
|
* in `[0, cap)`, which is why no negative adjustment is needed.
|
|
10
10
|
**/
|
|
11
|
-
pub struct Map<TK: Hashable + Equatable, TV> {
|
|
11
|
+
pub mv struct Map<TK: Hashable + Equatable, TV> {
|
|
12
12
|
var length = 0
|
|
13
13
|
var keys = Buffer<TK>()
|
|
14
14
|
var values = Buffer<TV>()
|
|
@@ -17,6 +17,9 @@ pub struct Map<TK: Hashable + Equatable, TV> {
|
|
|
17
17
|
// Variadic-tuple constructor: Map<string, int>(["a", 1], ["b", 2]) or
|
|
18
18
|
// Map(["a", 1], ["b", 2]) (type args inferred from the first pair).
|
|
19
19
|
// Zero pairs yields an empty Map, so this also covers Map<K, V>().
|
|
20
|
+
// The pair reads are temp-rooted (`pairs.at(i)` is a statement temp):
|
|
21
|
+
// the element transfer is absorbed by set's mv store (store_T
|
|
22
|
+
// deep-copies string-field elements), so no explicit mv is spelled.
|
|
20
23
|
pub func #init = (self, ...[TK, TV] pairs) {
|
|
21
24
|
var i = 0
|
|
22
25
|
while i < pairs.length; i += 1 {
|
|
@@ -24,7 +27,7 @@ pub struct Map<TK: Hashable + Equatable, TV> {
|
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
pub func set = (ref self,
|
|
30
|
+
pub func set = (ref self, mv TK key, mv TV value) {
|
|
28
31
|
var int cap = self.keys.cap
|
|
29
32
|
if cap == 0 {
|
|
30
33
|
// alloc_T: for Buffer<TK> it is T_SIZE-aware (string keys are
|
|
@@ -169,9 +172,9 @@ pub struct Map<TK: Hashable + Equatable, TV> {
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
func rehash = (ref self, int new_cap) {
|
|
172
|
-
var Buffer<TK> old_keys =
|
|
173
|
-
var Buffer<TV> old_values =
|
|
174
|
-
var Buffer<int> old_used =
|
|
175
|
+
var Buffer<TK> old_keys = mv self.keys swap Buffer<TK>()
|
|
176
|
+
var Buffer<TV> old_values = mv self.values swap Buffer<TV>()
|
|
177
|
+
var Buffer<int> old_used = mv self.used swap Buffer<int>()
|
|
175
178
|
var int old_cap = old_keys.cap
|
|
176
179
|
|
|
177
180
|
self.keys.alloc(new_cap)
|
|
@@ -187,13 +190,13 @@ pub struct Map<TK: Hashable + Equatable, TV> {
|
|
|
187
190
|
// afterwards. load_T would leave the old slot referencing
|
|
188
191
|
// the same class pointer — a double-free when old_keys is
|
|
189
192
|
// destroyed. The results are bound to locals so an
|
|
190
|
-
//
|
|
193
|
+
// mv-element copy (e.g. a `Buffer<string>` slot, which
|
|
191
194
|
// store_T strdup's) is freed here once the new buffer has
|
|
192
195
|
// made its own copy — passing them inline would orphan the
|
|
193
196
|
// move_T results.
|
|
194
197
|
var TK k = old_keys.move(i)
|
|
195
198
|
var TV v = old_values.move(i)
|
|
196
|
-
self.set(
|
|
199
|
+
self.set(mv k, mv v)
|
|
197
200
|
}
|
|
198
201
|
}
|
|
199
202
|
}
|