nomen-lang 0.0.6 → 0.0.8
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 +235 -0
- package/core/System/Ansi.nm +150 -0
- package/core/System/Array.nm +358 -0
- package/core/System/BigInt.nm +887 -0
- package/core/System/Buffer.nm +526 -0
- package/core/System/Channel.nm +198 -0
- package/core/System/ClassBuffer.nm +229 -0
- package/core/System/Console.nm +211 -0
- package/core/System/Controls/Button.nm +138 -0
- package/core/System/Controls/CheckBox.nm +158 -0
- package/core/System/Controls/Container.nm +1562 -0
- package/core/System/Controls/Control.nm +28 -0
- package/core/System/Controls/Geometry.nm +101 -0
- package/core/System/Controls/Layout.nm +228 -0
- package/core/System/Controls/LayoutParams.nm +50 -0
- package/core/System/Controls/Text.nm +129 -0
- package/core/System/Controls/TextBox.nm +157 -0
- package/core/System/Controls/Window.nm +280 -0
- package/core/System/Disposable.nm +8 -0
- package/core/System/Enumerable.nm +10 -0
- package/core/System/Equatable.nm +10 -0
- package/core/System/Graph.nm +68 -0
- package/core/System/Hashable.nm +13 -0
- package/core/System/Init.nm +21 -0
- package/core/System/LinkedList.nm +64 -0
- package/core/System/List.nm +44 -0
- package/core/System/Map.nm +153 -0
- package/core/System/Math.nm +54 -0
- package/core/System/Mutex.nm +78 -0
- package/core/System/Nursery.nm +27 -0
- package/core/System/Sendable.nm +9 -0
- package/core/System/Set.nm +97 -0
- package/core/System/Stream/Directory.nm +176 -0
- package/core/System/Stream/File.nm +432 -0
- package/core/System/Stream/Http.nm +453 -0
- package/core/System/String.nm +154 -0
- package/core/System/StringBuilder.nm +249 -0
- package/core/System/Stringable.nm +8 -0
- package/core/System/Task.nm +263 -0
- package/core/System/Test.nm +241 -0
- package/core/System/Text/Json.nm +377 -0
- package/core/System/Text/JsonTree.nm +187 -0
- package/core/System/Text/Regex.nm +655 -0
- package/core/System/Time.nm +112 -0
- package/core/System/Tree.nm +70 -0
- package/core/System/Viewable.nm +27 -0
- package/core/System/bool.nm +66 -0
- package/core/System/char.nm +42 -0
- package/core/System/float.nm +43 -0
- package/core/System/int.nm +54 -0
- package/core/System/int64.nm +42 -0
- package/core/System/int8.nm +42 -0
- package/core/System/uint.nm +42 -0
- package/core/System/uint64.nm +42 -0
- package/core/System/uint8.nm +42 -0
- package/core/docs/System/Ansi.md +40 -0
- package/core/docs/System/Array.md +16 -0
- package/core/docs/System/BigInt.md +30 -0
- package/core/docs/System/Buffer.md +31 -0
- package/core/docs/System/Channel.md +10 -0
- package/core/docs/System/ClassBuffer.md +15 -0
- package/core/docs/System/Console.md +13 -0
- package/core/docs/System/Controls/Button.md +12 -0
- package/core/docs/System/Controls/CheckBox.md +15 -0
- package/core/docs/System/Controls/Container.md +82 -0
- package/core/docs/System/Controls/Control.md +5 -0
- package/core/docs/System/Controls/Geometry.md +26 -0
- package/core/docs/System/Controls/Layout.md +37 -0
- package/core/docs/System/Controls/LayoutParams.md +13 -0
- package/core/docs/System/Controls/Text.md +12 -0
- package/core/docs/System/Controls/TextBox.md +13 -0
- package/core/docs/System/Controls/Window.md +20 -0
- package/core/docs/System/Disposable.md +5 -0
- package/core/docs/System/Enumerable.md +5 -0
- package/core/docs/System/Graph.md +17 -0
- package/core/docs/System/Init.md +9 -0
- package/core/docs/System/LinkedList.md +16 -0
- package/core/docs/System/List.md +13 -0
- package/core/docs/System/Map.md +14 -0
- package/core/docs/System/Math.md +11 -0
- package/core/docs/System/Mutex.md +10 -0
- package/core/docs/System/Nursery.md +5 -0
- package/core/docs/System/Sendable.md +5 -0
- package/core/docs/System/Set.md +14 -0
- package/core/docs/System/Stream/Directory.md +12 -0
- package/core/docs/System/Stream/File.md +21 -0
- package/core/docs/System/String.md +14 -0
- package/core/docs/System/StringBuilder.md +12 -0
- package/core/docs/System/Stringable.md +5 -0
- package/core/docs/System/Task.md +15 -0
- package/core/docs/System/Text/Json.md +12 -0
- package/core/docs/System/Text/JsonTree.md +21 -0
- package/core/docs/System/Text/Regex.md +12 -0
- package/core/docs/System/Time.md +11 -0
- package/core/docs/System/Tree.md +18 -0
- package/core/docs/System/Viewable.md +5 -0
- package/core/docs/System/bool.md +9 -0
- package/core/docs/System/char.md +9 -0
- package/core/docs/System/float.md +9 -0
- package/core/docs/System/int.md +10 -0
- package/core/docs/System/int64.md +9 -0
- package/core/docs/System/int8.md +9 -0
- package/core/docs/System/uint.md +9 -0
- package/core/docs/System/uint64.md +9 -0
- package/core/docs/System/uint8.md +9 -0
- package/core/package.jsonc +4 -0
- package/dist/index.mjs +17039 -21482
- package/package.json +33 -30
- package/src/args.ts +171 -0
- package/src/bench_loop.nm +113 -0
- package/src/index.ts +61 -95
- package/src/init.ts +128 -0
- package/src/test.ts +522 -0
- package/tsconfig.json +0 -21
- package/vite.config.ts +0 -7
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A top-level native window that hosts controls and dispatches events
|
|
3
|
+
**/
|
|
4
|
+
pub class Window: Control {
|
|
5
|
+
var uint64 handle = 0
|
|
6
|
+
|
|
7
|
+
pub func #init = (self, string title, int width, int height) {
|
|
8
|
+
```
|
|
9
|
+
#arch: c, aarch64_use_c
|
|
10
|
+
#platform: macos
|
|
11
|
+
// Set up NSApplication first
|
|
12
|
+
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
13
|
+
((void(*)(id, SEL, long))objc_msgSend)(app, sel_registerName("setActivationPolicy:"), 0);
|
|
14
|
+
((void(*)(id, SEL, BOOL))objc_msgSend)(app, sel_registerName("activateIgnoringOtherApps:"), 1);
|
|
15
|
+
// Create window
|
|
16
|
+
unsigned long style = 1 | 2 | 4 | 8;
|
|
17
|
+
id win = ((id(*)(id, SEL, double, double, double, double, unsigned long, unsigned long, BOOL))objc_msgSend)(
|
|
18
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSWindow"), sel_registerName("alloc")),
|
|
19
|
+
sel_registerName("initWithContentRect:styleMask:backing:defer:"),
|
|
20
|
+
0.0, 0.0, (double)width, (double)height,
|
|
21
|
+
style, 2, 0);
|
|
22
|
+
((id(*)(id, SEL, id))objc_msgSend)(
|
|
23
|
+
win, sel_registerName("setTitle:"),
|
|
24
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
25
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title));
|
|
26
|
+
((void(*)(id, SEL, double, double))objc_msgSend)(
|
|
27
|
+
win, sel_registerName("setFrameTopLeftPoint:"), 100.0, 100.0);
|
|
28
|
+
((void(*)(id, SEL, id))objc_msgSend)(win, sel_registerName("makeKeyAndOrderFront:"), (id)0);
|
|
29
|
+
// The content view must resize with the window and autoresize its
|
|
30
|
+
// subviews so each control's autoresizingMask takes effect during a
|
|
31
|
+
// live resize (AppKit's blocking drag loop bypasses our event loop).
|
|
32
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)(win, sel_registerName("contentView"));
|
|
33
|
+
((void(*)(id, SEL, unsigned long))objc_msgSend)(cv, sel_registerName("setAutoresizingMask:"), 18UL);
|
|
34
|
+
((void(*)(id, SEL, BOOL))objc_msgSend)(cv, sel_registerName("setAutoresizesSubviews:"), 1);
|
|
35
|
+
self->handle = (uint64_t)win;
|
|
36
|
+
```
|
|
37
|
+
```
|
|
38
|
+
#arch: c, aarch64_use_c
|
|
39
|
+
#platform: ios
|
|
40
|
+
id win = ((id(*)(id, SEL))objc_msgSend)(
|
|
41
|
+
((id(*)(id, SEL))objc_msgSend)(objc_getClass("UIWindow"), sel_registerName("alloc")),
|
|
42
|
+
sel_registerName("initWithFrame:"),
|
|
43
|
+
((CGRect(*)(double, double, double, double))CGRectMake)(0, 0, (double)width, (double)height));
|
|
44
|
+
((void(*)(id, SEL))objc_msgSend)(win, sel_registerName("makeKeyAndVisible"));
|
|
45
|
+
self->handle = (uint64_t)win;
|
|
46
|
+
```
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub func show = (self) {
|
|
50
|
+
```
|
|
51
|
+
#arch: c, aarch64_use_c
|
|
52
|
+
#platform: macos
|
|
53
|
+
((void(*)(id, SEL, id))objc_msgSend)((id)self->handle, sel_registerName("makeKeyAndOrderFront:"), 0);
|
|
54
|
+
```
|
|
55
|
+
```
|
|
56
|
+
#arch: c, aarch64_use_c
|
|
57
|
+
#platform: ios
|
|
58
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("makeKeyAndVisible"));
|
|
59
|
+
```
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
pub func set_title = (self, string title) {
|
|
63
|
+
```
|
|
64
|
+
#arch: c, aarch64_use_c
|
|
65
|
+
#platform: macos
|
|
66
|
+
((id(*)(id, SEL, id))objc_msgSend)(
|
|
67
|
+
(id)self->handle, sel_registerName("setTitle:"),
|
|
68
|
+
((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
69
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), title));
|
|
70
|
+
```
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
pub func run = () {
|
|
74
|
+
```
|
|
75
|
+
#arch: c, aarch64_use_c
|
|
76
|
+
#platform: macos
|
|
77
|
+
((void(*)(id, SEL))objc_msgSend)(
|
|
78
|
+
((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")), sel_registerName("run"));
|
|
79
|
+
```
|
|
80
|
+
```
|
|
81
|
+
#arch: c, aarch64_use_c
|
|
82
|
+
#platform: ios
|
|
83
|
+
UIApplicationMain(0, 0, 0, 0);
|
|
84
|
+
```
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Process pending events without blocking. Returns 1 if a left-mouse-down
|
|
88
|
+
// was among the events (i.e. a click happened), 0 otherwise. This lets a
|
|
89
|
+
// manual event loop detect clicks for re-layout without target/action.
|
|
90
|
+
// Also runs the run loop briefly to process Apple Events (e.g. dock Quit).
|
|
91
|
+
pub func process_events = (out int) {
|
|
92
|
+
```
|
|
93
|
+
#arch: c, aarch64_use_c
|
|
94
|
+
#platform: macos
|
|
95
|
+
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
96
|
+
id distant_past = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSDate"), sel_registerName("distantPast"));
|
|
97
|
+
id default_mode = ((id(*)(id, SEL, const char*))objc_msgSend)(
|
|
98
|
+
(id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "kCFRunLoopDefaultMode");
|
|
99
|
+
int had_click = 0;
|
|
100
|
+
while (1) {
|
|
101
|
+
id event = ((id(*)(id, SEL, unsigned long long, id, id, BOOL))objc_msgSend)(
|
|
102
|
+
app, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"),
|
|
103
|
+
0xFFFFFFFFFFFFFFFFULL, // NSEventMaskAny
|
|
104
|
+
distant_past, // untilDate — returns immediately if no events
|
|
105
|
+
default_mode, // inMode
|
|
106
|
+
1); // dequeue
|
|
107
|
+
if (!event) break;
|
|
108
|
+
((void(*)(id, SEL, id))objc_msgSend)(app, sel_registerName("sendEvent:"), event);
|
|
109
|
+
long type = ((long(*)(id, SEL))objc_msgSend)(event, sel_registerName("type"));
|
|
110
|
+
if (type == 1) had_click = 1; // NSLeftMouseDown = 1
|
|
111
|
+
}
|
|
112
|
+
// Process run loop sources (Apple Events, timers) so that dock Quit
|
|
113
|
+
// and other system interactions work without NSApplication.run().
|
|
114
|
+
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 1);
|
|
115
|
+
return had_click;
|
|
116
|
+
```
|
|
117
|
+
```
|
|
118
|
+
#arch: c, aarch64_use_c
|
|
119
|
+
#platform: ios
|
|
120
|
+
return 0;
|
|
121
|
+
```
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Returns true if the window is still on screen. Use this to exit a
|
|
125
|
+
// manual event loop when the user closes the window.
|
|
126
|
+
pub func is_visible = (self, out bool) {
|
|
127
|
+
```
|
|
128
|
+
#arch: c, aarch64_use_c
|
|
129
|
+
#platform: macos
|
|
130
|
+
BOOL vis = ((BOOL(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("isVisible"));
|
|
131
|
+
return vis;
|
|
132
|
+
```
|
|
133
|
+
```
|
|
134
|
+
#arch: c, aarch64_use_c
|
|
135
|
+
#platform: ios
|
|
136
|
+
BOOL vis = ((BOOL(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("isKeyWindow"));
|
|
137
|
+
return vis;
|
|
138
|
+
```
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Returns the x coordinate (in the window's content view) of the most
|
|
142
|
+
// recent mouse-down. Call after process_events returned 1.
|
|
143
|
+
pub func click_x = (self, out int) {
|
|
144
|
+
```
|
|
145
|
+
#arch: c, aarch64_use_c
|
|
146
|
+
#platform: macos
|
|
147
|
+
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
148
|
+
id event = ((id(*)(id, SEL))objc_msgSend)(app, sel_registerName("currentEvent"));
|
|
149
|
+
if (!event) return -1;
|
|
150
|
+
long type = ((long(*)(id, SEL))objc_msgSend)(event, sel_registerName("type"));
|
|
151
|
+
if (type != 1) return -1; // NSLeftMouseDown = 1
|
|
152
|
+
// locationInWindow is a CGPoint inside the event; read it via struct-return
|
|
153
|
+
CGPoint loc = ((CGPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
|
|
154
|
+
return (int)loc.x;
|
|
155
|
+
```
|
|
156
|
+
```
|
|
157
|
+
#arch: c, aarch64_use_c
|
|
158
|
+
#platform: ios
|
|
159
|
+
return -1;
|
|
160
|
+
```
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Returns the y coordinate (flipped to top-left origin) of the most
|
|
164
|
+
// recent mouse-down, in the window's content view.
|
|
165
|
+
pub func click_y = (self, out int) {
|
|
166
|
+
```
|
|
167
|
+
#arch: c, aarch64_use_c
|
|
168
|
+
#platform: macos
|
|
169
|
+
id app = ((id(*)(id, SEL))objc_msgSend)((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
|
|
170
|
+
id event = ((id(*)(id, SEL))objc_msgSend)(app, sel_registerName("currentEvent"));
|
|
171
|
+
if (!event) return -1;
|
|
172
|
+
long type = ((long(*)(id, SEL))objc_msgSend)(event, sel_registerName("type"));
|
|
173
|
+
if (type != 1) return -1; // NSLeftMouseDown = 1
|
|
174
|
+
CGPoint loc = ((CGPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
|
|
175
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
|
|
176
|
+
CGRect frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
|
|
177
|
+
// NSWindow coords are bottom-left origin; flip to top-left for layout math
|
|
178
|
+
return (int)(frame.size.height - loc.y);
|
|
179
|
+
```
|
|
180
|
+
```
|
|
181
|
+
#arch: c, aarch64_use_c
|
|
182
|
+
#platform: ios
|
|
183
|
+
return -1;
|
|
184
|
+
```
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Returns the width of the window's content view.
|
|
188
|
+
pub func content_width = (self, out int) {
|
|
189
|
+
```
|
|
190
|
+
#arch: c, aarch64_use_c
|
|
191
|
+
#platform: macos
|
|
192
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
|
|
193
|
+
CGRect frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
|
|
194
|
+
return (int)frame.size.width;
|
|
195
|
+
```
|
|
196
|
+
```
|
|
197
|
+
#arch: c, aarch64_use_c
|
|
198
|
+
#platform: ios
|
|
199
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)(
|
|
200
|
+
((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("rootViewController")),
|
|
201
|
+
sel_registerName("view"));
|
|
202
|
+
CGRect frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
|
|
203
|
+
return (int)frame.size.width;
|
|
204
|
+
```
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Returns the height of the window's content view (for coordinate flipping).
|
|
208
|
+
pub func content_height = (self, out int) {
|
|
209
|
+
```
|
|
210
|
+
#arch: c, aarch64_use_c
|
|
211
|
+
#platform: macos
|
|
212
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("contentView"));
|
|
213
|
+
CGRect frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
|
|
214
|
+
return (int)frame.size.height;
|
|
215
|
+
```
|
|
216
|
+
```
|
|
217
|
+
#arch: c, aarch64_use_c
|
|
218
|
+
#platform: ios
|
|
219
|
+
id cv = ((id(*)(id, SEL))objc_msgSend)(
|
|
220
|
+
((id(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("rootViewController")),
|
|
221
|
+
sel_registerName("view"));
|
|
222
|
+
CGRect frame = ((CGRect(*)(id, SEL))objc_msgSend)(cv, sel_registerName("frame"));
|
|
223
|
+
return (int)frame.size.height;
|
|
224
|
+
```
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ── Control trait conformance ──
|
|
228
|
+
// The window is the layout root: it measures to its content-view size and
|
|
229
|
+
// applies a frame to the native NSWindow/UIWindow.
|
|
230
|
+
|
|
231
|
+
pub func measure = (self, BoxConstraints constraints, out Size) {
|
|
232
|
+
var s = Size()
|
|
233
|
+
s.width = self.content_width()
|
|
234
|
+
s.height = self.content_height()
|
|
235
|
+
return s
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
pub func intrinsic_size = (self, out Size) {
|
|
239
|
+
var s = Size()
|
|
240
|
+
s.width = self.content_width()
|
|
241
|
+
s.height = self.content_height()
|
|
242
|
+
return s
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
pub func set_frame = (ref self, int x, int y, int width, int height) {
|
|
246
|
+
```
|
|
247
|
+
#arch: c, aarch64_use_c
|
|
248
|
+
#platform: macos
|
|
249
|
+
((void(*)(id, SEL, CGRect))objc_msgSend)(
|
|
250
|
+
(id)self->handle, sel_registerName("setFrame:"),
|
|
251
|
+
((CGRect(*)(double, double, double, double))CGRectMake)((double)x, (double)y, (double)width, (double)height));
|
|
252
|
+
```
|
|
253
|
+
```
|
|
254
|
+
#arch: c, aarch64_use_c
|
|
255
|
+
#platform: ios
|
|
256
|
+
((void(*)(id, SEL, CGRect))objc_msgSend)(
|
|
257
|
+
(id)self->handle, sel_registerName("setFrame:"),
|
|
258
|
+
((CGRect(*)(double, double, double, double))CGRectMake)((double)x, (double)y, (double)width, (double)height));
|
|
259
|
+
```
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
func #destroy = () {
|
|
263
|
+
```
|
|
264
|
+
#arch: c, aarch64_use_c
|
|
265
|
+
#platform: macos
|
|
266
|
+
if (self->handle) {
|
|
267
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
268
|
+
self->handle = 0;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
```
|
|
272
|
+
#arch: c, aarch64_use_c
|
|
273
|
+
#platform: ios
|
|
274
|
+
if (self->handle) {
|
|
275
|
+
((void(*)(id, SEL))objc_msgSend)((id)self->handle, sel_registerName("release"));
|
|
276
|
+
self->handle = 0;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Trait for collection types that can be iterated with `for x of collection`.
|
|
2
|
+
// The loop variable receives int indices 0..length-1; use .at(i) to access values.
|
|
3
|
+
/**
|
|
4
|
+
* A trait for collections that can be iterated with `for x of collection`
|
|
5
|
+
**/
|
|
6
|
+
pub trait Enumerable {
|
|
7
|
+
func length = (self, out int) {
|
|
8
|
+
return 0
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marker trait for value equality. A struct that conforms to `Equatable` and
|
|
3
|
+
* does not define its own `#op_eq` gets a field-by-field equality method
|
|
4
|
+
* derived automatically, so `==` and `!=` work between two instances. The
|
|
5
|
+
* derivation only fires when every field is itself equatable (a primitive or
|
|
6
|
+
* another `Equatable` type); otherwise the struct must supply `#op_eq` by
|
|
7
|
+
* hand.
|
|
8
|
+
**/
|
|
9
|
+
pub trait Equatable {
|
|
10
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Arena-backed directed graph. Node values and edges live in flat Buffers;
|
|
2
|
+
// edges are stored as a per-node linked list of edge records (CSR-style), so
|
|
3
|
+
// there is a single owner and cleanup is a flat free. Node and edge identifiers
|
|
4
|
+
// are stable int indices; -1 means "none".
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A graph of values connected by edges
|
|
8
|
+
**/
|
|
9
|
+
pub struct Graph<T>: Enumerable {
|
|
10
|
+
var Buffer<T> values = Buffer<T>()
|
|
11
|
+
var head_edge = Buffer<int>()
|
|
12
|
+
var edge_target = Buffer<int>()
|
|
13
|
+
var edge_next = Buffer<int>()
|
|
14
|
+
var node_count = 0
|
|
15
|
+
var edge_count = 0
|
|
16
|
+
|
|
17
|
+
pub func add_node = (ref self, mov T value) {
|
|
18
|
+
var int idx = self.node_count
|
|
19
|
+
self.values.grow_int(idx + 1)
|
|
20
|
+
var int v = value
|
|
21
|
+
self.values.store_int(idx, v)
|
|
22
|
+
self.head_edge.grow_int(idx + 1)
|
|
23
|
+
self.head_edge.store_int(idx, -1)
|
|
24
|
+
self.node_count = self.node_count + 1
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub func add_edge = (ref self, int from, int to) {
|
|
28
|
+
var int e = self.edge_count
|
|
29
|
+
self.edge_target.grow_int(e + 1)
|
|
30
|
+
self.edge_target.store_int(e, to)
|
|
31
|
+
self.edge_next.grow_int(e + 1)
|
|
32
|
+
if from >= 0 && from < self.head_edge.cap {
|
|
33
|
+
self.edge_next.store_int(e, self.head_edge.load_int(from))
|
|
34
|
+
}
|
|
35
|
+
if from >= 0 && from < self.head_edge.cap {
|
|
36
|
+
self.head_edge.store_int(from, e)
|
|
37
|
+
}
|
|
38
|
+
self.edge_count = self.edge_count + 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
pub func edges_of = (self, int node, out int: out >= -1 && out < self.edge_count) {
|
|
42
|
+
return self.head_edge.load_int(node)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pub func edge_target = (self, int e, out int: out >= 0 && out < self.node_count) {
|
|
46
|
+
return self.edge_target.load_int(e)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub func next_edge = (self, int e, out int: out >= -1 && out < self.edge_count) {
|
|
50
|
+
return self.edge_next.load_int(e)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
pub func first = (self: self.node_count > 0, out T) {
|
|
54
|
+
return self.values.load_int(0)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pub func at = (self, int idx: idx >= 0 && idx < self.node_count, out T) {
|
|
58
|
+
return self.values.load_int(idx)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub func node_length = (self, out int) {
|
|
62
|
+
return self.node_count
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
pub func edge_length = (self, out int) {
|
|
66
|
+
return self.edge_count
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A trait for values that can be hashed to an unsigned integer. A struct that
|
|
3
|
+
* conforms to `Hashable` and does not define its own `hash` method gets one
|
|
4
|
+
* derived automatically by combining each field's value (integer fields are
|
|
5
|
+
* cast to `uint`, and `Hashable` struct fields call their own `hash`). The
|
|
6
|
+
* derivation only fires when every field is hashable; otherwise the default
|
|
7
|
+
* body (which returns `0`) is used.
|
|
8
|
+
**/
|
|
9
|
+
pub trait Hashable {
|
|
10
|
+
func hash = (self, out uint) {
|
|
11
|
+
return 0
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program startup state — the argument count and argument list passed to `main`
|
|
3
|
+
**/
|
|
4
|
+
pub struct Init {
|
|
5
|
+
var int argc
|
|
6
|
+
var string[16] args
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parses a decimal string into an int
|
|
11
|
+
**/
|
|
12
|
+
pub func parse_int = (string s, out int) {
|
|
13
|
+
```
|
|
14
|
+
#arch: c
|
|
15
|
+
return atoi(s);
|
|
16
|
+
```
|
|
17
|
+
```
|
|
18
|
+
#arch: aarch64
|
|
19
|
+
bl _atoi
|
|
20
|
+
```
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Arena-backed doubly-linked list. Values and next/prev links live in flat
|
|
2
|
+
// Buffers, so there is a single owner and cleanup is a flat free — no recursive
|
|
3
|
+
// pointer chasing, no borrow lifetimes. Node identifiers are stable int indices
|
|
4
|
+
// (read `count` before `add`); -1 means "no node" / "end".
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A doubly-linked list of values
|
|
8
|
+
**/
|
|
9
|
+
pub struct LinkedList<T>: Enumerable {
|
|
10
|
+
var Buffer<T> values = Buffer<T>()
|
|
11
|
+
var nexts = Buffer<int>()
|
|
12
|
+
var prevs = Buffer<int>()
|
|
13
|
+
var int head = -1
|
|
14
|
+
var count = 0
|
|
15
|
+
|
|
16
|
+
pub func add = (ref self, mov T value) {
|
|
17
|
+
var int idx = self.count
|
|
18
|
+
self.values.grow_int(idx + 1)
|
|
19
|
+
var int v = value
|
|
20
|
+
self.values.store_int(idx, v)
|
|
21
|
+
self.nexts.grow_int(idx + 1)
|
|
22
|
+
self.nexts.store_int(idx, -1)
|
|
23
|
+
self.prevs.grow_int(idx + 1)
|
|
24
|
+
self.prevs.store_int(idx, -1)
|
|
25
|
+
self.count += 1
|
|
26
|
+
if self.head == -1 {
|
|
27
|
+
self.head = idx
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub func set_next = (ref self, int idx, int next) {
|
|
32
|
+
self.nexts.store_int(idx, next)
|
|
33
|
+
if next >= 0 && next < self.prevs.cap {
|
|
34
|
+
self.prevs.store_int(next, idx)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pub func set_previous = (ref self, int idx, int prev) {
|
|
39
|
+
self.prevs.store_int(idx, prev)
|
|
40
|
+
if prev >= 0 && prev < self.nexts.cap {
|
|
41
|
+
self.nexts.store_int(prev, idx)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pub func next_at = (self, int idx, out int: out >= -1 && out < self.count) {
|
|
46
|
+
return self.nexts.load_int(idx)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pub func previous_at = (self, int idx, out int: out >= -1 && out < self.count) {
|
|
50
|
+
return self.prevs.load_int(idx)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
pub func first = (self: self.count > 0, out T) {
|
|
54
|
+
return self.values.load_int(0)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pub func at = (self, int idx: idx >= 0 && idx < self.count, out T) {
|
|
58
|
+
return self.values.load_int(idx)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub func length = (self, out int) {
|
|
62
|
+
return self.count
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A growable, ordered list of values (`push`/`pop`/`at`)
|
|
3
|
+
**/
|
|
4
|
+
pub struct List<T>: Viewable {
|
|
5
|
+
var length = 0
|
|
6
|
+
var Buffer<T> items = Buffer<T>()
|
|
7
|
+
|
|
8
|
+
pub func push = (ref self, mov T value) {
|
|
9
|
+
if self.length >= self.items.cap {
|
|
10
|
+
var new_cap = 4
|
|
11
|
+
var int old_cap = self.items.cap
|
|
12
|
+
if old_cap >= 4 {
|
|
13
|
+
new_cap = old_cap * 2
|
|
14
|
+
}
|
|
15
|
+
self.items.grow_int(new_cap)
|
|
16
|
+
}
|
|
17
|
+
self.items.store_int(self.length, value)
|
|
18
|
+
self.length += 1
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub func pop = (ref self, mov out T) {
|
|
22
|
+
if self.length <= 0 {
|
|
23
|
+
return 0
|
|
24
|
+
}
|
|
25
|
+
var int idx = self.length - 1
|
|
26
|
+
self.length = idx
|
|
27
|
+
return self.items.move_int(idx)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub func at = (self, int i: i >= 0 && i < self.length, out T) {
|
|
31
|
+
return self.items.load_int(i)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// A non-owning `view T` over [start, end). Delegates to the backing Buffer's
|
|
35
|
+
// #arch slice primitive — no #arch code here. Borrows from self.
|
|
36
|
+
pub func slice = (self, int start: start >= 0, int end: end >= start, out view T) {
|
|
37
|
+
return self.items.slice(start, end)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub func set = (ref self, int i: i >= 0 && i < self.length, mov T value) {
|
|
41
|
+
var int v = value
|
|
42
|
+
self.items.replace_int(i, v)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An ordered key-value map with `set`/`get`/`has`/`remove`
|
|
3
|
+
**/
|
|
4
|
+
pub struct Map<TK, TV> {
|
|
5
|
+
var length = 0
|
|
6
|
+
var Buffer<TK> keys = Buffer<TK>()
|
|
7
|
+
var Buffer<TV> values = Buffer<TV>()
|
|
8
|
+
var used = Buffer<int>()
|
|
9
|
+
|
|
10
|
+
// Variadic-tuple constructor: Map<string, int>(["a", 1], ["b", 2]) or
|
|
11
|
+
// Map(["a", 1], ["b", 2]) (type args inferred from the first pair).
|
|
12
|
+
// Zero pairs yields an empty Map, so this also covers Map<K, V>().
|
|
13
|
+
pub func #init = (self, ...[TK, TV] pairs) {
|
|
14
|
+
var i = 0
|
|
15
|
+
while i < pairs.length; i += 1 {
|
|
16
|
+
self.set(pairs.at(i)._0, pairs.at(i)._1)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub func set = (ref self, mov TK key, mov TV value) {
|
|
21
|
+
var int cap = self.keys.cap
|
|
22
|
+
if cap == 0 {
|
|
23
|
+
cap = self.keys.alloc_int(8)
|
|
24
|
+
self.values.alloc_int(8)
|
|
25
|
+
self.used.alloc(8)
|
|
26
|
+
}
|
|
27
|
+
if self.length * 4 >= cap * 3 {
|
|
28
|
+
self.rehash(cap * 2)
|
|
29
|
+
cap = self.keys.cap
|
|
30
|
+
}
|
|
31
|
+
var int idx = self.find_slot(key, cap)
|
|
32
|
+
if self.used.load(idx) == 0 {
|
|
33
|
+
self.used.store(idx, 1)
|
|
34
|
+
self.keys.store_int(idx, key)
|
|
35
|
+
self.values.store_int(idx, value)
|
|
36
|
+
self.length += 1
|
|
37
|
+
} else {
|
|
38
|
+
self.values.store_int(idx, value)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pub func get = (self, TK key, out TV) {
|
|
43
|
+
var int cap = self.keys.cap
|
|
44
|
+
if cap == 0 {
|
|
45
|
+
return 0
|
|
46
|
+
}
|
|
47
|
+
var int idx = self.find_slot(key, cap)
|
|
48
|
+
if self.used.load(idx) == 0 {
|
|
49
|
+
return 0
|
|
50
|
+
}
|
|
51
|
+
return self.values.load_int(idx)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
pub func has = (self, TK key, out bool) {
|
|
55
|
+
var int cap = self.keys.cap
|
|
56
|
+
if cap == 0 {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
var int idx = self.find_slot(key, cap)
|
|
60
|
+
return self.used.load(idx) != 0
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pub func remove = (ref self, TK key) {
|
|
64
|
+
var int cap = self.keys.cap
|
|
65
|
+
if cap == 0 {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
var int idx = self.find_slot(key, cap)
|
|
69
|
+
if self.used.load(idx) == 0 {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
// Backward-shift deletion for linear probing. `gap` is the empty slot
|
|
73
|
+
// walking forward through the cluster; `k` scans ahead of it. An entry
|
|
74
|
+
// at k shifts into the gap only if the gap still lies within its valid
|
|
75
|
+
// probe range ([home, k) cyclically); otherwise the entry stays put and
|
|
76
|
+
// we keep scanning, because a later entry may still belong behind the
|
|
77
|
+
// gap. This is the subtle point: k advances independently of the gap,
|
|
78
|
+
// so entries past a non-moveable one are not stranded behind an empty
|
|
79
|
+
// slot (which would make find_slot miss them). No tombstones, so
|
|
80
|
+
// find_slot/get/has/set are unchanged, and the cost is the local cluster
|
|
81
|
+
// length — not a full O(cap) rehash on every delete.
|
|
82
|
+
var int gap = idx
|
|
83
|
+
var int k = idx
|
|
84
|
+
while true {
|
|
85
|
+
k += 1
|
|
86
|
+
if k >= cap {
|
|
87
|
+
k = 0
|
|
88
|
+
}
|
|
89
|
+
if self.used.load(k) == 0 {
|
|
90
|
+
break
|
|
91
|
+
}
|
|
92
|
+
var int home = self.keys.load_int(k) % cap
|
|
93
|
+
if home < 0 {
|
|
94
|
+
home = home + cap
|
|
95
|
+
}
|
|
96
|
+
var int dgap = gap - home
|
|
97
|
+
if dgap < 0 {
|
|
98
|
+
dgap = dgap + cap
|
|
99
|
+
}
|
|
100
|
+
var int dk = k - home
|
|
101
|
+
if dk < 0 {
|
|
102
|
+
dk = dk + cap
|
|
103
|
+
}
|
|
104
|
+
if dgap < dk {
|
|
105
|
+
self.keys.store_int(gap, self.keys.load_int(k))
|
|
106
|
+
self.values.store_int(gap, self.values.load_int(k))
|
|
107
|
+
self.used.store(gap, 1)
|
|
108
|
+
gap = k
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
self.used.store(gap, 0)
|
|
112
|
+
self.keys.store_int(gap, 0)
|
|
113
|
+
self.values.store_int(gap, 0)
|
|
114
|
+
self.length = self.length - 1
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func find_slot = (self, TK key, int cap, out int: out >= 0 && out < cap) {
|
|
118
|
+
var int k = key
|
|
119
|
+
var int idx = k % cap
|
|
120
|
+
if idx < 0 {
|
|
121
|
+
idx = idx + cap
|
|
122
|
+
}
|
|
123
|
+
while self.used.load(idx) != 0 {
|
|
124
|
+
if self.keys.load_int(idx) == k {
|
|
125
|
+
return idx
|
|
126
|
+
}
|
|
127
|
+
idx += 1
|
|
128
|
+
if idx >= cap {
|
|
129
|
+
idx = 0
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return idx
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func rehash = (ref self, int new_cap) {
|
|
136
|
+
var Buffer<TK> old_keys = mov self.keys swap Buffer<TK>()
|
|
137
|
+
var Buffer<TV> old_values = mov self.values swap Buffer<TV>()
|
|
138
|
+
var Buffer<int> old_used = mov self.used swap Buffer<int>()
|
|
139
|
+
var int old_cap = old_keys.cap
|
|
140
|
+
|
|
141
|
+
self.keys.alloc_int(new_cap)
|
|
142
|
+
self.values.alloc_int(new_cap)
|
|
143
|
+
self.used.alloc(new_cap)
|
|
144
|
+
self.length = 0
|
|
145
|
+
|
|
146
|
+
var i = 0
|
|
147
|
+
while i < old_cap; i += 1 {
|
|
148
|
+
if old_used.load(i) != 0 {
|
|
149
|
+
self.set(old_keys.load_int(i), old_values.load_int(i))
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|