nomen-lang 0.7.1 → 0.9.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/audit_runtime.c +12 -2
- package/core/System/Arena.nm +8 -1
- package/core/System/Buffer.nm +397 -8
- package/core/System/ClassBuffer.nm +156 -0
- package/core/System/Controls/Alert.nm +326 -0
- package/core/System/Controls/App.nm +147 -0
- package/core/System/Controls/Button.nm +119 -1
- package/core/System/Controls/CheckBox.nm +25 -1
- package/core/System/Controls/ColorPicker.nm +307 -0
- package/core/System/Controls/ComboBox.nm +430 -0
- package/core/System/Controls/Container.nm +843 -9
- package/core/System/Controls/Control.nm +443 -0
- package/core/System/Controls/DatePicker.nm +288 -0
- package/core/System/Controls/Form.nm +70 -0
- package/core/System/Controls/GroupBox.nm +267 -0
- package/core/System/Controls/ImageView.nm +311 -0
- package/core/System/Controls/LevelIndicator.nm +305 -0
- package/core/System/Controls/ListView.nm +633 -0
- package/core/System/Controls/Menu.nm +428 -0
- package/core/System/Controls/NumberInput.nm +56 -0
- package/core/System/Controls/OtpInput.nm +50 -0
- package/core/System/Controls/OutlineView.nm +598 -0
- package/core/System/Controls/Pagination.nm +142 -0
- package/core/System/Controls/Popover.nm +296 -0
- package/core/System/Controls/Progress.nm +348 -0
- package/core/System/Controls/Radio.nm +292 -0
- package/core/System/Controls/Scrollable.nm +584 -0
- package/core/System/Controls/SearchField.nm +326 -0
- package/core/System/Controls/SecureField.nm +344 -0
- package/core/System/Controls/Segmented.nm +380 -0
- package/core/System/Controls/Select.nm +340 -0
- package/core/System/Controls/Separator.nm +198 -0
- package/core/System/Controls/Sheet.nm +329 -0
- package/core/System/Controls/Slider.nm +315 -0
- package/core/System/Controls/Spinner.nm +287 -0
- package/core/System/Controls/SplitView.nm +509 -0
- package/core/System/Controls/Stepper.nm +349 -0
- package/core/System/Controls/Switch.nm +259 -0
- package/core/System/Controls/Table.nm +833 -0
- package/core/System/Controls/Tabs.nm +500 -0
- package/core/System/Controls/Text.nm +108 -11
- package/core/System/Controls/TextBox.nm +113 -2
- package/core/System/Controls/TextView.nm +329 -0
- package/core/System/Controls/Toggle.nm +346 -0
- package/core/System/Controls/Toolbar.nm +501 -0
- package/core/System/Controls/Tooltip.nm +76 -0
- package/core/System/Controls/Window.nm +1548 -91
- package/core/System/LinkedList.nm +8 -1
- package/core/System/List.nm +97 -7
- package/core/System/Map.nm +191 -18
- package/core/System/Mutex.nm +4 -4
- package/core/System/Random.nm +3 -4
- package/core/System/Set.nm +101 -13
- package/core/System/StableList.nm +371 -0
- package/core/System/Stream/Directory.nm +2 -2
- package/core/System/Stream/File.nm +2 -2
- package/core/System/Stream/Http.nm +2 -2
- package/core/System/String.nm +10 -5
- package/core/System/StringBuilder.nm +213 -2
- package/core/System/Text/CharIndex.nm +9 -9
- package/core/System/Text/Json.nm +60 -46
- package/core/System/Text/JsonTree.nm +120 -92
- package/core/System/Text/Regex.nm +23 -18
- package/core/System/Text/Utf8.nm +5 -5
- package/core/System/float.nm +36 -22
- package/core/System/int.nm +80 -28
- package/core/System/int16.nm +11 -0
- package/core/System/int32.nm +11 -0
- package/core/System/int64.nm +11 -0
- package/core/System/int8.nm +11 -0
- package/core/System/uint.nm +11 -0
- package/core/System/uint16.nm +11 -0
- package/core/System/uint32.nm +11 -0
- package/core/System/uint64.nm +11 -0
- package/core/System/uint8.nm +11 -0
- package/core/docs/System/StringBuilder.md +6 -0
- package/core/docs/System/Text/JsonTree.md +3 -2
- package/dist/index.mjs +38332 -30604
- package/package.json +1 -1
- package/src/bench_loop.nm +9 -9
|
@@ -58,6 +58,30 @@ pub struct ClassBuffer<T> {
|
|
|
58
58
|
```
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Address of slot `i` (library-only): the ELEMENT BORROW primitive for
|
|
62
|
+
// trait/class elements — `ref T x = list.at(i)` (docs/HANDLERS.md Stage
|
|
63
|
+
// 4) reaches here through the List wrapper when the element is a trait
|
|
64
|
+
// (the items buffer is a ClassBuffer). ClassBuffer slots are 8-byte
|
|
65
|
+
// handles, so the slot's CONTENT is the instance pointer: return the
|
|
66
|
+
// stored word, not the slot's address. Library-internal: bounds are the
|
|
67
|
+
// caller's obligation (the List wrapper constrains them).
|
|
68
|
+
internal func slot_ptr = (ref self, int i, out ptr T) {
|
|
69
|
+
```
|
|
70
|
+
#arch: c
|
|
71
|
+
// The slot's address: through the alias, reads and writes hit the
|
|
72
|
+
// stored handle word. void* converts to the caller's `T*` spelling.
|
|
73
|
+
return (void *)&((unsigned long long *)self->data)[i];
|
|
74
|
+
```
|
|
75
|
+
```
|
|
76
|
+
#arch: aarch64
|
|
77
|
+
// 8-byte slots: the address of slot i — loading through it yields
|
|
78
|
+
// the stored handle.
|
|
79
|
+
ldr x8, [x19, #8]
|
|
80
|
+
lsl x9, x1, #3
|
|
81
|
+
add x0, x9, x8
|
|
82
|
+
```
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
// Generic (T-typed) counterparts of the _int primitives. ClassBuffer only
|
|
62
86
|
// ever holds 8-byte class pointers (T_SIZE is 8), so these are
|
|
63
87
|
// behaviorally identical to their _int counterparts — they exist so
|
|
@@ -94,6 +118,15 @@ pub struct ClassBuffer<T> {
|
|
|
94
118
|
```
|
|
95
119
|
}
|
|
96
120
|
|
|
121
|
+
// Labeled delegation point for raw-body callers in other containers
|
|
122
|
+
// (StableList's chunked storage calls this): `load` is `inline` — spliced
|
|
123
|
+
// at Nomen call sites, so no label exists for a raw C call or `bl` to
|
|
124
|
+
// target. Mirror of Buffer.load_from (class slots are pointer words —
|
|
125
|
+
// the pointer load IS the borrow form).
|
|
126
|
+
internal func load_from = (self, int i: i >= 0 && i < self.cap, out T) {
|
|
127
|
+
return self.load(i)
|
|
128
|
+
}
|
|
129
|
+
|
|
97
130
|
// Store the owned class pointer `val` into slot `i`, which MUST be fresh
|
|
98
131
|
// (calloc'd, or zeroed by mv/move_int). Takes OWNERSHIP of `val`
|
|
99
132
|
// (`mv`): the slot's #destroy reclaims the instance, so the caller must
|
|
@@ -117,6 +150,42 @@ pub struct ClassBuffer<T> {
|
|
|
117
150
|
```
|
|
118
151
|
}
|
|
119
152
|
|
|
153
|
+
// Initialize this buffer as a VIEW over a foreign slab (INTERNAL — the
|
|
154
|
+
// chunked-container primitive): `data` becomes `slab` and `cap` becomes
|
|
155
|
+
// `fill`, and the buffer owns NOTHING — the slab keeps its real owner
|
|
156
|
+
// (never grown, never freed by the view). Mirror of Buffer.init_view;
|
|
157
|
+
// class slots are pointer words.
|
|
158
|
+
internal func init_view = (ref self, uint64 slab, int fill: fill >= 0) {
|
|
159
|
+
self.data = slab
|
|
160
|
+
self.cap = fill
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Clear a view initialized by init_view (see Buffer.clear_view): the
|
|
164
|
+
// holder's own field destroy then reclaims nothing.
|
|
165
|
+
internal func clear_view = (ref self) {
|
|
166
|
+
self.data = 0
|
|
167
|
+
self.cap = 0
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Store the owned class pointer `val` into slot `slot` of a foreign slab
|
|
171
|
+
// at `slab` (fill `fill`) through this buffer as a transient view —
|
|
172
|
+
// INTERNAL (StableList's directory chunks, class elements): init the
|
|
173
|
+
// view, run the typed `store` (the ownership-transferring slot store),
|
|
174
|
+
// then clear the view so the holder's teardown reclaims nothing. The
|
|
175
|
+
// holder passes a ClassBuffer FIELD, never a local (a local owning buffer
|
|
176
|
+
// is auto-destroyed at scope exit and would free the borrowed slab).
|
|
177
|
+
internal func store_in_slab = (
|
|
178
|
+
ref self,
|
|
179
|
+
uint64 slab,
|
|
180
|
+
int fill: fill >= 0,
|
|
181
|
+
int slot: slot >= 0,
|
|
182
|
+
mv T val
|
|
183
|
+
) {
|
|
184
|
+
self.init_view(slab, fill)
|
|
185
|
+
self.store(slot, val)
|
|
186
|
+
self.clear_view()
|
|
187
|
+
}
|
|
188
|
+
|
|
120
189
|
// Move a class pointer out of a slot: return it and zero the slot so the
|
|
121
190
|
// buffer no longer references it. Declared `mv out T` so the borrow
|
|
122
191
|
// checker treats the result as OWNED — the slot is relinquished, so the
|
|
@@ -254,6 +323,40 @@ pub struct ClassBuffer<T> {
|
|
|
254
323
|
```
|
|
255
324
|
}
|
|
256
325
|
|
|
326
|
+
// Reclaim slot i's owned class pointer (destroy + free) WITHOUT writing
|
|
327
|
+
// the slot — the destroy half of replace_int, without the store, zeroing
|
|
328
|
+
// the handle so a re-destroy is a no-op. The caller (Map.set_slot_ptr's
|
|
329
|
+
// replace path — the value-side sibling of `values.replace`) overwrites
|
|
330
|
+
// the slot immediately afterwards. Contract: the slot must be
|
|
331
|
+
// overwritten before it is read or destroyed again.
|
|
332
|
+
internal func destroy_at = (ref self, int i: i >= 0 && i < self.cap) {
|
|
333
|
+
```
|
|
334
|
+
#arch: c
|
|
335
|
+
long *slots = (long*)(unsigned long long)self->data;
|
|
336
|
+
if (slots[i]) {
|
|
337
|
+
T_destroy((void*)slots[i]);
|
|
338
|
+
free((void*)slots[i]);
|
|
339
|
+
slots[i] = 0;
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
```
|
|
343
|
+
#arch: aarch64
|
|
344
|
+
stp x20, x21, [sp, #-16]!
|
|
345
|
+
ldr x20, [x19, #8]
|
|
346
|
+
lsl x3, x1, #3
|
|
347
|
+
add x20, x20, x3
|
|
348
|
+
ldr x0, [x20]
|
|
349
|
+
cbz x0, .Lcb_destroy_at_done
|
|
350
|
+
mov x21, x0
|
|
351
|
+
bl T_destroy
|
|
352
|
+
mov x0, x21
|
|
353
|
+
bl _free
|
|
354
|
+
str xzr, [x20]
|
|
355
|
+
.Lcb_destroy_at_done:
|
|
356
|
+
ldp x20, x21, [sp], #16
|
|
357
|
+
```
|
|
358
|
+
}
|
|
359
|
+
|
|
257
360
|
// T-typed alias of replace_int: free the outgoing class pointer (destroy +
|
|
258
361
|
// free) then store the new one. Used by List.set so the uniform API
|
|
259
362
|
// preserves ownership for class elements.
|
|
@@ -339,6 +442,59 @@ pub struct ClassBuffer<T> {
|
|
|
339
442
|
```
|
|
340
443
|
}
|
|
341
444
|
|
|
445
|
+
// Bulk transfer for backward-shift deletion — the ClassBuffer
|
|
446
|
+
// counterpart of Buffer.move_range (same contract: every slot in
|
|
447
|
+
// [dst, dst + count) must be DEAD — zeroed by a move-out or otherwise
|
|
448
|
+
// unowned — because the block move overwrites without reclaiming; the
|
|
449
|
+
// deletion algorithms zero and relocate in lockstep). Slots are 8-byte
|
|
450
|
+
// instance pointers, so the block is one memmove + one memset of the
|
|
451
|
+
// source slots the destination never covers — List.remove_at_or_panic's
|
|
452
|
+
// whole-tail shift instead of per-element `shift` calls.
|
|
453
|
+
internal inline func move_range = (
|
|
454
|
+
ref self,
|
|
455
|
+
int dst: dst >= 0,
|
|
456
|
+
int src: src >= dst,
|
|
457
|
+
int count: count >= 0 && src + count <= self.cap
|
|
458
|
+
) {
|
|
459
|
+
```
|
|
460
|
+
#arch: c
|
|
461
|
+
if (count > 0) {
|
|
462
|
+
long *slots = (long*)(unsigned long long)self->data;
|
|
463
|
+
memmove((void*)&slots[dst], (void*)&slots[src],
|
|
464
|
+
(unsigned long long)count * sizeof(long));
|
|
465
|
+
memset((void*)&slots[dst + count], 0,
|
|
466
|
+
(unsigned long long)(src - dst) * sizeof(long));
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
```
|
|
470
|
+
#arch: aarch64
|
|
471
|
+
// x19 = self, x1 = dst, x2 = src, x3 = count. x0-x18 die across the
|
|
472
|
+
// bl calls, so the block math parks on the stack around _memmove.
|
|
473
|
+
cbz x3, .Lcb_move_range_T_end
|
|
474
|
+
ldr x4, [x19, #8]
|
|
475
|
+
lsl x5, x1, #3
|
|
476
|
+
add x6, x4, x5
|
|
477
|
+
lsl x5, x2, #3
|
|
478
|
+
add x7, x4, x5
|
|
479
|
+
lsl x9, x3, #3
|
|
480
|
+
sub x10, x2, x1
|
|
481
|
+
lsl x10, x10, #3
|
|
482
|
+
stp x6, x9, [sp, #-16]!
|
|
483
|
+
str x10, [sp, #-16]!
|
|
484
|
+
mov x0, x6
|
|
485
|
+
mov x1, x7
|
|
486
|
+
mov x2, x9
|
|
487
|
+
bl _memmove
|
|
488
|
+
ldr x10, [sp], #16
|
|
489
|
+
ldp x6, x9, [sp], #16
|
|
490
|
+
add x0, x6, x9
|
|
491
|
+
mov x1, #0
|
|
492
|
+
mov x2, x10
|
|
493
|
+
bl _memset
|
|
494
|
+
.Lcb_move_range_T_end:
|
|
495
|
+
```
|
|
496
|
+
}
|
|
497
|
+
|
|
342
498
|
// A non-mv (ptr, len) slice [start, end) over this buffer's class
|
|
343
499
|
// pointers, returned as a `view T` (T is a class, so each element is an
|
|
344
500
|
// 8-byte pointer). Borrows from self — invalidated on reassignment. Mirrors
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A system alert dialog (NSAlert)
|
|
3
|
+
*
|
|
4
|
+
* An OWNING STRUCT (STRUCT_PLAN_3 Phase R, tranche 4 — the shape menu): the
|
|
5
|
+
* single field is a platform 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.
|
|
8
|
+
*
|
|
9
|
+
* Window-coordinated: `run` enters NSAlert's own modal loop (it blocks the
|
|
10
|
+
* caller and pumps its own events, so it works with the manual loop), and
|
|
11
|
+
* returns the clicked button's index (first button = 0). iOS defers —
|
|
12
|
+
* UIAlertController needs a presenting view controller (TODO stubs; see
|
|
13
|
+
* GUI_PLAN Tier 1 #19).
|
|
14
|
+
**/
|
|
15
|
+
pub mv struct Alert: Control {
|
|
16
|
+
var uint64 handle = 0
|
|
17
|
+
|
|
18
|
+
// The `#handle` hook synthesizes `NameHandle` — a copyable, non-owning
|
|
19
|
+
// twin (same public bare-self methods, no destroy) so closures can
|
|
20
|
+
// capture this control without moving it. See GUI.md, "Handles".
|
|
21
|
+
#handle = () { }
|
|
22
|
+
|
|
23
|
+
pub func #init = (self) {
|
|
24
|
+
```
|
|
25
|
+
#arch: c
|
|
26
|
+
#platform: macos
|
|
27
|
+
id alert = ((id(*)(id, SEL))objc_msgSend)(
|
|
28
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSAlert"), sel_registerName("alloc")),
|
|
29
|
+
sel_registerName("init"));
|
|
30
|
+
self.handle = (uint64_t)alert;
|
|
31
|
+
```
|
|
32
|
+
```
|
|
33
|
+
#arch: aarch64_use_c
|
|
34
|
+
#platform: macos
|
|
35
|
+
id alert = ((id(*)(id, SEL))objc_msgSend)(
|
|
36
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSAlert"), sel_registerName("alloc")),
|
|
37
|
+
sel_registerName("init"));
|
|
38
|
+
self->handle = (uint64_t)alert;
|
|
39
|
+
```
|
|
40
|
+
```
|
|
41
|
+
#arch: c
|
|
42
|
+
#platform: ios
|
|
43
|
+
/* TODO: iOS — UIAlertController needs a presenting view controller
|
|
44
|
+
* (see GUI_PLAN Tier 1 #19; defer the iOS block). */
|
|
45
|
+
```
|
|
46
|
+
```
|
|
47
|
+
#arch: aarch64_use_c
|
|
48
|
+
#platform: ios
|
|
49
|
+
/* TODO: iOS — UIAlertController needs a presenting view controller
|
|
50
|
+
* (see GUI_PLAN Tier 1 #19; defer the iOS block). */
|
|
51
|
+
```
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// The alert's headline (bold first line).
|
|
55
|
+
pub func set_title = (self, string title) {
|
|
56
|
+
```
|
|
57
|
+
#arch: c
|
|
58
|
+
#platform: macos
|
|
59
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
60
|
+
(id)self->handle, sel_registerName("setMessageText:"),
|
|
61
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
62
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
63
|
+
```
|
|
64
|
+
```
|
|
65
|
+
#arch: aarch64_use_c
|
|
66
|
+
#platform: macos
|
|
67
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
68
|
+
(id)self->handle, sel_registerName("setMessageText:"),
|
|
69
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
70
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
71
|
+
```
|
|
72
|
+
```
|
|
73
|
+
#arch: c
|
|
74
|
+
#platform: ios
|
|
75
|
+
/* TODO: iOS (see #init) */
|
|
76
|
+
```
|
|
77
|
+
```
|
|
78
|
+
#arch: aarch64_use_c
|
|
79
|
+
#platform: ios
|
|
80
|
+
/* TODO: iOS (see #init) */
|
|
81
|
+
```
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
pub func title = (self, out string) {
|
|
85
|
+
```
|
|
86
|
+
#arch: c
|
|
87
|
+
#platform: macos
|
|
88
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
89
|
+
(id)self->handle, sel_registerName("messageText"));
|
|
90
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
91
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
92
|
+
str, sel_registerName("UTF8String"));
|
|
93
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
94
|
+
```
|
|
95
|
+
```
|
|
96
|
+
#arch: aarch64_use_c
|
|
97
|
+
#platform: macos
|
|
98
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
99
|
+
(id)self->handle, sel_registerName("messageText"));
|
|
100
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
101
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
102
|
+
str, sel_registerName("UTF8String"));
|
|
103
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
104
|
+
```
|
|
105
|
+
```
|
|
106
|
+
#arch: c
|
|
107
|
+
#platform: ios
|
|
108
|
+
/* TODO: iOS (see #init) */
|
|
109
|
+
return (nomen_string){ strdup(""), 0 };
|
|
110
|
+
```
|
|
111
|
+
```
|
|
112
|
+
#arch: aarch64_use_c
|
|
113
|
+
#platform: ios
|
|
114
|
+
/* TODO: iOS (see #init) */
|
|
115
|
+
return (nomen_string){ strdup(""), 0 };
|
|
116
|
+
```
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// The explanatory second line.
|
|
120
|
+
pub func set_message = (self, string message) {
|
|
121
|
+
```
|
|
122
|
+
#arch: c
|
|
123
|
+
#platform: macos
|
|
124
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
125
|
+
(id)self->handle, sel_registerName("setInformativeText:"),
|
|
126
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
127
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), message.ptr));
|
|
128
|
+
```
|
|
129
|
+
```
|
|
130
|
+
#arch: aarch64_use_c
|
|
131
|
+
#platform: macos
|
|
132
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
133
|
+
(id)self->handle, sel_registerName("setInformativeText:"),
|
|
134
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
135
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), message.ptr));
|
|
136
|
+
```
|
|
137
|
+
```
|
|
138
|
+
#arch: c
|
|
139
|
+
#platform: ios
|
|
140
|
+
/* TODO: iOS (see #init) */
|
|
141
|
+
```
|
|
142
|
+
```
|
|
143
|
+
#arch: aarch64_use_c
|
|
144
|
+
#platform: ios
|
|
145
|
+
/* TODO: iOS (see #init) */
|
|
146
|
+
```
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
pub func message = (self, out string) {
|
|
150
|
+
```
|
|
151
|
+
#arch: c
|
|
152
|
+
#platform: macos
|
|
153
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
154
|
+
(id)self->handle, sel_registerName("informativeText"));
|
|
155
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
156
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
157
|
+
str, sel_registerName("UTF8String"));
|
|
158
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
159
|
+
```
|
|
160
|
+
```
|
|
161
|
+
#arch: aarch64_use_c
|
|
162
|
+
#platform: macos
|
|
163
|
+
id str = ((id(*)(id, SEL))objc_msgSend)(
|
|
164
|
+
(id)self->handle, sel_registerName("informativeText"));
|
|
165
|
+
if (!str) return (nomen_string){ strdup(""), 0 };
|
|
166
|
+
const char *cstr = ((const char*(*)(id, SEL))objc_msgSend)(
|
|
167
|
+
str, sel_registerName("UTF8String"));
|
|
168
|
+
return (nomen_string){ strdup(cstr), (long)strlen(cstr) };
|
|
169
|
+
```
|
|
170
|
+
```
|
|
171
|
+
#arch: c
|
|
172
|
+
#platform: ios
|
|
173
|
+
/* TODO: iOS (see #init) */
|
|
174
|
+
return (nomen_string){ strdup(""), 0 };
|
|
175
|
+
```
|
|
176
|
+
```
|
|
177
|
+
#arch: aarch64_use_c
|
|
178
|
+
#platform: ios
|
|
179
|
+
/* TODO: iOS (see #init) */
|
|
180
|
+
return (nomen_string){ strdup(""), 0 };
|
|
181
|
+
```
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Append a button (left to right). The FIRST button is the default
|
|
185
|
+
// (Return); the clicked one's index is what `run` returns. A fresh
|
|
186
|
+
// NSAlert carries one default button ("OK") — the first
|
|
187
|
+
// `add_button` REPLACES it, so the count stays what the app adds.
|
|
188
|
+
pub func add_button = (self, string title) {
|
|
189
|
+
```
|
|
190
|
+
#arch: c
|
|
191
|
+
#platform: macos
|
|
192
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
193
|
+
(id)self->handle, sel_registerName("addButtonWithTitle:"),
|
|
194
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
195
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
196
|
+
```
|
|
197
|
+
```
|
|
198
|
+
#arch: aarch64_use_c
|
|
199
|
+
#platform: macos
|
|
200
|
+
((void(*)(id, SEL, id))objc_msgSend)(
|
|
201
|
+
(id)self->handle, sel_registerName("addButtonWithTitle:"),
|
|
202
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
203
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title.ptr));
|
|
204
|
+
```
|
|
205
|
+
```
|
|
206
|
+
#arch: c
|
|
207
|
+
#platform: ios
|
|
208
|
+
/* TODO: iOS (see #init) */
|
|
209
|
+
```
|
|
210
|
+
```
|
|
211
|
+
#arch: aarch64_use_c
|
|
212
|
+
#platform: ios
|
|
213
|
+
/* TODO: iOS (see #init) */
|
|
214
|
+
```
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// How many buttons the alert carries.
|
|
218
|
+
pub func button_count = (self, out int) {
|
|
219
|
+
```
|
|
220
|
+
#arch: c
|
|
221
|
+
#platform: macos
|
|
222
|
+
id buttons = ((id(*)(id, SEL))objc_msgSend)(
|
|
223
|
+
(id)self->handle, sel_registerName("buttons"));
|
|
224
|
+
return (int)((long(*)(id, SEL))objc_msgSend)(buttons, sel_registerName("count"));
|
|
225
|
+
```
|
|
226
|
+
```
|
|
227
|
+
#arch: aarch64_use_c
|
|
228
|
+
#platform: macos
|
|
229
|
+
id buttons = ((id(*)(id, SEL))objc_msgSend)(
|
|
230
|
+
(id)self->handle, sel_registerName("buttons"));
|
|
231
|
+
return (int)((long(*)(id, SEL))objc_msgSend)(buttons, sel_registerName("count"));
|
|
232
|
+
```
|
|
233
|
+
```
|
|
234
|
+
#arch: c
|
|
235
|
+
#platform: ios
|
|
236
|
+
/* TODO: iOS (see #init) */
|
|
237
|
+
return 0;
|
|
238
|
+
```
|
|
239
|
+
```
|
|
240
|
+
#arch: aarch64_use_c
|
|
241
|
+
#platform: ios
|
|
242
|
+
/* TODO: iOS (see #init) */
|
|
243
|
+
return 0;
|
|
244
|
+
```
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Show the alert modally and return the clicked button's index (0 =
|
|
248
|
+
// first button). BLOCKS in NSAlert's own modal loop until dismissed —
|
|
249
|
+
// call it from the event thread when the manual loop can afford to
|
|
250
|
+
// pause (NSAlert pumps its own events, so the UI stays live).
|
|
251
|
+
pub func run = (self, out int) {
|
|
252
|
+
```
|
|
253
|
+
#arch: c
|
|
254
|
+
#platform: macos
|
|
255
|
+
long code = ((long(*)(id, SEL))objc_msgSend)(
|
|
256
|
+
(id)self->handle, sel_registerName("runModal"));
|
|
257
|
+
return (int)(code - 1000); // NSModalResponseOK = 1000 + button index
|
|
258
|
+
```
|
|
259
|
+
```
|
|
260
|
+
#arch: aarch64_use_c
|
|
261
|
+
#platform: macos
|
|
262
|
+
long code = ((long(*)(id, SEL))objc_msgSend)(
|
|
263
|
+
(id)self->handle, sel_registerName("runModal"));
|
|
264
|
+
return (int)(code - 1000); // NSModalResponseOK = 1000 + button index
|
|
265
|
+
```
|
|
266
|
+
```
|
|
267
|
+
#arch: c
|
|
268
|
+
#platform: ios
|
|
269
|
+
/* TODO: iOS (see #init) */
|
|
270
|
+
return 0;
|
|
271
|
+
```
|
|
272
|
+
```
|
|
273
|
+
#arch: aarch64_use_c
|
|
274
|
+
#platform: ios
|
|
275
|
+
/* TODO: iOS (see #init) */
|
|
276
|
+
return 0;
|
|
277
|
+
```
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ── Control trait conformance ──
|
|
281
|
+
// An alert is a modal, not an in-window view: it measures to nothing and
|
|
282
|
+
// the layout engine never frames it. The conformance exists so an Alert
|
|
283
|
+
// can sit in a Control-typed slot without special-casing.
|
|
284
|
+
pub func set_frame = (ref self, int x, int y, int width, int height) {
|
|
285
|
+
// No-op: modals are positioned by the window server.
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
pub func intrinsic_size = (self, out Size) {
|
|
289
|
+
var s = Size()
|
|
290
|
+
return s
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
pub func measure = (self, BoxConstraints constraints, out Size) {
|
|
294
|
+
var s = Size()
|
|
295
|
+
return s
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
func #destroy = () {
|
|
299
|
+
```
|
|
300
|
+
#arch: c
|
|
301
|
+
#platform: macos
|
|
302
|
+
if (self->handle) {
|
|
303
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
304
|
+
self->handle = 0;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
```
|
|
308
|
+
#arch: aarch64_use_c
|
|
309
|
+
#platform: macos
|
|
310
|
+
if (self->handle) {
|
|
311
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
312
|
+
self->handle = 0;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
```
|
|
316
|
+
#arch: c
|
|
317
|
+
#platform: ios
|
|
318
|
+
/* TODO: iOS (see #init) */
|
|
319
|
+
```
|
|
320
|
+
```
|
|
321
|
+
#arch: aarch64_use_c
|
|
322
|
+
#platform: ios
|
|
323
|
+
/* TODO: iOS (see #init) */
|
|
324
|
+
```
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The App contract: the object Window.run drives
|
|
3
|
+
*
|
|
4
|
+
* The WinForms/Swift shape for a manual-loop toolkit: instead of pumping
|
|
5
|
+
* `Window.process_events` and re-checking sizes in a `while` loop, the app
|
|
6
|
+
* declares a struct conforming to `App`, moves it into `win.run(mv app)`,
|
|
7
|
+
* and the WINDOW owns everything else — the event pump, the autorelease
|
|
8
|
+
* pool, resize detection, and the relayout of the hosted content (the root
|
|
9
|
+
* `Container` from `win.set_content` plus every `Scrollable.set_content`
|
|
10
|
+
* document). The app implements four hooks:
|
|
11
|
+
*
|
|
12
|
+
* - `start` — called once, after the app has been moved into its final
|
|
13
|
+
* storage but before the window is shown. Register the layout roots here
|
|
14
|
+
* (`win.set_content(ref grid)`, `scroll.set_content(ref grid)`) and do
|
|
15
|
+
* any wiring that needs stable addresses — including click handlers
|
|
16
|
+
* (`self.btn.on_click(func () { ... })`).
|
|
17
|
+
* - `frame` — called every iteration of the run loop with a `FrameEvents`
|
|
18
|
+
* value: the full input record for this frame (click kind/coordinates,
|
|
19
|
+
* `mouse_button`/`mouse_click_count`/`mouse_modifiers` — every button,
|
|
20
|
+
* `scroll_dx`/`scroll_dy`, the keyboard record
|
|
21
|
+
* `key_code`/`key_modifiers`/`key_repeat`/`key_up_code`, the pointer
|
|
22
|
+
* position `mouse_x`/`mouse_y`, and frame time `dt`), and `resized`
|
|
23
|
+
* + the new size when the window's content rect changed. Per-frame value
|
|
24
|
+
* polling (slider → progress mirrors), coordinate-driven input that no
|
|
25
|
+
* event names, and app-owned pane relayouts live here — registered
|
|
26
|
+
* click, right-click, mouse-down, scroll, key, move, and resize handlers
|
|
27
|
+
* dispatch earlier, in `handle_events` (the `.on_click` /
|
|
28
|
+
* `.on_right_click` / `.on_mouse_down` / `.on_scroll` / `.on_key_down` /
|
|
29
|
+
* `.on_key_up` / `.on_mouse_move` / `.on_resize` desugars), and close
|
|
30
|
+
* requests consult `close_requested`.
|
|
31
|
+
* - `handle_events` — the per-frame event pump: drains every registered
|
|
32
|
+
* control event (clicks, focus/blur, text input). Declared here as a
|
|
33
|
+
* default-empty method; the `.on_<event>(closure)` desugars
|
|
34
|
+
* (docs/HANDLERS.md) synthesize the override on conformers with
|
|
35
|
+
* registrations, so user code only writes the registration and never
|
|
36
|
+
* sees the machinery. New control events extend the pump's arms — the
|
|
37
|
+
* App contract is fixed.
|
|
38
|
+
* - `run_handler` — the up-call protocol (Stage 3): a composite with an
|
|
39
|
+
* enrolled event calls back `owner.run_handler(id, ref win)` from its
|
|
40
|
+
* `tick` (the app forwards itself down once per tick). Default-empty;
|
|
41
|
+
* the desugar synthesizes the override dispatching ids to the app's
|
|
42
|
+
* `.on_<event>` handlers.
|
|
43
|
+
*
|
|
44
|
+
* Handlers are METHODS on the app (the `ref self` receiver), so app state —
|
|
45
|
+
* every control field — is reachable without lambda captures (capturing a
|
|
46
|
+
* control MOVES it; a capture-free method reference moves nothing). The
|
|
47
|
+
* `.on_click` desugar is that shape with registration ergonomics: the
|
|
48
|
+
* closure you write IS hoisted into a hidden method, and the dispatch
|
|
49
|
+
* borrow of `self` is taken by the run loop per frame.
|
|
50
|
+
**/
|
|
51
|
+
pub trait App {
|
|
52
|
+
// Called once before the window is shown, after the app is in its
|
|
53
|
+
// final storage. Register layout roots here.
|
|
54
|
+
func start = (ref self, ref Window win) {
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Called every frame until the window closes.
|
|
58
|
+
func frame = (ref self, ref Window win, FrameEvents ev) {
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// The per-frame event pump: drains every registered control event —
|
|
62
|
+
// clicks, focus/blur, text input — through arms the `.on_<event>`
|
|
63
|
+
// desugar (docs/HANDLERS.md) synthesizes on conformers with
|
|
64
|
+
// registrations: one hidden method per closure, one drain arm per
|
|
65
|
+
// registered control, one event-source prologue per family.
|
|
66
|
+
// `Window.run` calls it before `frame`. New control events are new arms
|
|
67
|
+
// in this one slot — the App contract never grows with the event
|
|
68
|
+
// catalog. Conformers without registrations inherit this empty default
|
|
69
|
+
// (trait defaults have precedent: `Enumerable.length`).
|
|
70
|
+
func handle_events = (ref self, ref Window win) {
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The up-call protocol (docs/HANDLERS.md Stage 3): a composite the app
|
|
74
|
+
// has enrolled events on calls back into this — `owner.run_handler(id,
|
|
75
|
+
// ref win)` from its `tick` — one vtable hop into the desugar's
|
|
76
|
+
// synthesized override, whose arms dispatch the id to the app's handler.
|
|
77
|
+
// The borrow flows down per call; nothing outlives it. Default-empty,
|
|
78
|
+
// like `handle_events`.
|
|
79
|
+
func run_handler = (ref self, int id, ref Window win) {
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Close interception (the unsaved-changes pattern): run consults this
|
|
83
|
+
// on the frame after the user requests close (the red button — the
|
|
84
|
+
// delegate refuses the native close and sets a pending flag). Return
|
|
85
|
+
// false to refuse: the window stays, the flag is cleared, and a later
|
|
86
|
+
// close request consults again. Programmatic `win.close()` is FORCED
|
|
87
|
+
// and bypasses this — handlers closing their own window never trip the
|
|
88
|
+
// interception. Default: allow.
|
|
89
|
+
func close_requested = (ref self, ref Window win, out bool) {
|
|
90
|
+
return true
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* One frame's input state, passed to App.frame
|
|
96
|
+
*
|
|
97
|
+
* Pure scalars, so the by-value parameter copies safely (no destroy).
|
|
98
|
+
* Click coordinates are the window's content coordinates, top-left origin
|
|
99
|
+
* (the same values `Window.click_x`/`click_y` report) — translate through
|
|
100
|
+
* `content_click` before hit-testing controls hosted on a Scrollable.
|
|
101
|
+
**/
|
|
102
|
+
pub mv struct FrameEvents {
|
|
103
|
+
// 0 = no mouse-down this frame, 1 = left, 2 = right (edge-triggered:
|
|
104
|
+
// only the frame that pumped the event reports it).
|
|
105
|
+
pub var click = 0
|
|
106
|
+
pub var int click_x = -1
|
|
107
|
+
pub var int click_y = -1
|
|
108
|
+
// The full mouse record for this frame (0 = no mouse-down): the 1-based
|
|
109
|
+
// button number (1 left, 2 right, 3 middle, 4+ extra buttons), the
|
|
110
|
+
// AppKit click count (2 = double-click), and the device-independent
|
|
111
|
+
// modifier flags (Command = 0x100000, Option = 0x80000, Control =
|
|
112
|
+
// 0x40000, Shift = 0x20000). The same values the `win.mouse_button()` /
|
|
113
|
+
// `mouse_click_count()` / `mouse_modifiers()` getters report to
|
|
114
|
+
// `on_mouse_down` handlers. `click` remains the left/right compat view.
|
|
115
|
+
pub var mouse_button = 0
|
|
116
|
+
pub var mouse_click_count = 0
|
|
117
|
+
pub var mouse_modifiers = 0
|
|
118
|
+
// This frame's accumulated scroll-wheel deltas (dy positive scrolling
|
|
119
|
+
// up/away, dx positive right; trackpad frames sum every small event).
|
|
120
|
+
// `Scrollable.on_scroll` is the registered-handler form.
|
|
121
|
+
pub var scroll_dx = 0
|
|
122
|
+
pub var scroll_dy = 0
|
|
123
|
+
// The keyboard record for this frame (-1 = no key this frame): the
|
|
124
|
+
// hardware keycode of the last key-down (Space = 49, Return = 36,
|
|
125
|
+
// arrows = 123–126, letters a…z = 0–25), the modifiers at key-down,
|
|
126
|
+
// whether it was an auto-repeat, and the keycode of the last key-up.
|
|
127
|
+
// `on_key_down` / `on_key_up` are the registered-handler forms; text
|
|
128
|
+
// ENTRY flows through `on_input` (the field editor), not here.
|
|
129
|
+
pub var int key_code = -1
|
|
130
|
+
pub var key_modifiers = 0
|
|
131
|
+
pub var key_repeat = false
|
|
132
|
+
pub var int key_up_code = -1
|
|
133
|
+
// The pointer-MOVE record for this frame (-1 = no movement): the
|
|
134
|
+
// current pointer position. `on_mouse_move` is the registered-handler
|
|
135
|
+
// form; hover/tooltips hit-test this against Container.contains.
|
|
136
|
+
pub var int mouse_x = -1
|
|
137
|
+
pub var int mouse_y = -1
|
|
138
|
+
// Milliseconds since the previous frame (0 on the first) — the
|
|
139
|
+
// animation clock. `win.dt()` reports the same value.
|
|
140
|
+
pub var dt = 0
|
|
141
|
+
// True when the window's content rect changed since the last frame —
|
|
142
|
+
// the framework has already re-laid-out the registered roots; re-layout
|
|
143
|
+
// App-owned panes (tab pages, split panes) here.
|
|
144
|
+
pub var resized = false
|
|
145
|
+
pub var width = 0
|
|
146
|
+
pub var height = 0
|
|
147
|
+
}
|