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.
Files changed (115) hide show
  1. package/NOMEN_AGENTS.md +235 -0
  2. package/core/System/Ansi.nm +150 -0
  3. package/core/System/Array.nm +358 -0
  4. package/core/System/BigInt.nm +887 -0
  5. package/core/System/Buffer.nm +526 -0
  6. package/core/System/Channel.nm +198 -0
  7. package/core/System/ClassBuffer.nm +229 -0
  8. package/core/System/Console.nm +211 -0
  9. package/core/System/Controls/Button.nm +138 -0
  10. package/core/System/Controls/CheckBox.nm +158 -0
  11. package/core/System/Controls/Container.nm +1562 -0
  12. package/core/System/Controls/Control.nm +28 -0
  13. package/core/System/Controls/Geometry.nm +101 -0
  14. package/core/System/Controls/Layout.nm +228 -0
  15. package/core/System/Controls/LayoutParams.nm +50 -0
  16. package/core/System/Controls/Text.nm +129 -0
  17. package/core/System/Controls/TextBox.nm +157 -0
  18. package/core/System/Controls/Window.nm +280 -0
  19. package/core/System/Disposable.nm +8 -0
  20. package/core/System/Enumerable.nm +10 -0
  21. package/core/System/Equatable.nm +10 -0
  22. package/core/System/Graph.nm +68 -0
  23. package/core/System/Hashable.nm +13 -0
  24. package/core/System/Init.nm +21 -0
  25. package/core/System/LinkedList.nm +64 -0
  26. package/core/System/List.nm +44 -0
  27. package/core/System/Map.nm +153 -0
  28. package/core/System/Math.nm +54 -0
  29. package/core/System/Mutex.nm +78 -0
  30. package/core/System/Nursery.nm +27 -0
  31. package/core/System/Sendable.nm +9 -0
  32. package/core/System/Set.nm +97 -0
  33. package/core/System/Stream/Directory.nm +176 -0
  34. package/core/System/Stream/File.nm +432 -0
  35. package/core/System/Stream/Http.nm +453 -0
  36. package/core/System/String.nm +154 -0
  37. package/core/System/StringBuilder.nm +249 -0
  38. package/core/System/Stringable.nm +8 -0
  39. package/core/System/Task.nm +263 -0
  40. package/core/System/Test.nm +241 -0
  41. package/core/System/Text/Json.nm +377 -0
  42. package/core/System/Text/JsonTree.nm +187 -0
  43. package/core/System/Text/Regex.nm +655 -0
  44. package/core/System/Time.nm +112 -0
  45. package/core/System/Tree.nm +70 -0
  46. package/core/System/Viewable.nm +27 -0
  47. package/core/System/bool.nm +66 -0
  48. package/core/System/char.nm +42 -0
  49. package/core/System/float.nm +43 -0
  50. package/core/System/int.nm +54 -0
  51. package/core/System/int64.nm +42 -0
  52. package/core/System/int8.nm +42 -0
  53. package/core/System/uint.nm +42 -0
  54. package/core/System/uint64.nm +42 -0
  55. package/core/System/uint8.nm +42 -0
  56. package/core/docs/System/Ansi.md +40 -0
  57. package/core/docs/System/Array.md +16 -0
  58. package/core/docs/System/BigInt.md +30 -0
  59. package/core/docs/System/Buffer.md +31 -0
  60. package/core/docs/System/Channel.md +10 -0
  61. package/core/docs/System/ClassBuffer.md +15 -0
  62. package/core/docs/System/Console.md +13 -0
  63. package/core/docs/System/Controls/Button.md +12 -0
  64. package/core/docs/System/Controls/CheckBox.md +15 -0
  65. package/core/docs/System/Controls/Container.md +82 -0
  66. package/core/docs/System/Controls/Control.md +5 -0
  67. package/core/docs/System/Controls/Geometry.md +26 -0
  68. package/core/docs/System/Controls/Layout.md +37 -0
  69. package/core/docs/System/Controls/LayoutParams.md +13 -0
  70. package/core/docs/System/Controls/Text.md +12 -0
  71. package/core/docs/System/Controls/TextBox.md +13 -0
  72. package/core/docs/System/Controls/Window.md +20 -0
  73. package/core/docs/System/Disposable.md +5 -0
  74. package/core/docs/System/Enumerable.md +5 -0
  75. package/core/docs/System/Graph.md +17 -0
  76. package/core/docs/System/Init.md +9 -0
  77. package/core/docs/System/LinkedList.md +16 -0
  78. package/core/docs/System/List.md +13 -0
  79. package/core/docs/System/Map.md +14 -0
  80. package/core/docs/System/Math.md +11 -0
  81. package/core/docs/System/Mutex.md +10 -0
  82. package/core/docs/System/Nursery.md +5 -0
  83. package/core/docs/System/Sendable.md +5 -0
  84. package/core/docs/System/Set.md +14 -0
  85. package/core/docs/System/Stream/Directory.md +12 -0
  86. package/core/docs/System/Stream/File.md +21 -0
  87. package/core/docs/System/String.md +14 -0
  88. package/core/docs/System/StringBuilder.md +12 -0
  89. package/core/docs/System/Stringable.md +5 -0
  90. package/core/docs/System/Task.md +15 -0
  91. package/core/docs/System/Text/Json.md +12 -0
  92. package/core/docs/System/Text/JsonTree.md +21 -0
  93. package/core/docs/System/Text/Regex.md +12 -0
  94. package/core/docs/System/Time.md +11 -0
  95. package/core/docs/System/Tree.md +18 -0
  96. package/core/docs/System/Viewable.md +5 -0
  97. package/core/docs/System/bool.md +9 -0
  98. package/core/docs/System/char.md +9 -0
  99. package/core/docs/System/float.md +9 -0
  100. package/core/docs/System/int.md +10 -0
  101. package/core/docs/System/int64.md +9 -0
  102. package/core/docs/System/int8.md +9 -0
  103. package/core/docs/System/uint.md +9 -0
  104. package/core/docs/System/uint64.md +9 -0
  105. package/core/docs/System/uint8.md +9 -0
  106. package/core/package.jsonc +4 -0
  107. package/dist/index.mjs +17039 -21482
  108. package/package.json +33 -30
  109. package/src/args.ts +171 -0
  110. package/src/bench_loop.nm +113 -0
  111. package/src/index.ts +61 -95
  112. package/src/init.ts +128 -0
  113. package/src/test.ts +522 -0
  114. package/tsconfig.json +0 -21
  115. 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,8 @@
1
+ /**
2
+ * A trait for resources that must be explicitly cleaned up via `dispose`
3
+ **/
4
+ pub trait Disposable {
5
+ func dispose = (self) {
6
+ Console.write("\nboom!")
7
+ }
8
+ }
@@ -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
+ }