nomen-lang 0.0.7 → 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 +417 -5490
- package/package.json +33 -30
- package/src/args.ts +171 -0
- package/src/index.ts +53 -104
- package/src/init.ts +128 -0
- package/src/test.ts +6 -2
- package/test/fixtures/build/calc.test +0 -0
- package/test/fixtures/build/calc.test.c +0 -969
- package/test/fixtures/build/main.h +0 -170
- package/test/fixtures/calc.test.nm +0 -32
- package/tsconfig.json +0 -21
- package/vite.config.ts +0 -7
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
// Buffer<T>: a flat buffer of value slots of type T. The value counterpart to
|
|
2
|
+
// ClassBuffer<T>: no per-element freeing, store_int unconstrained. When T is a
|
|
3
|
+
// class, the monomorphizer rewrites a Buffer<T> field to ClassBuffer<T>.
|
|
4
|
+
/**
|
|
5
|
+
* A flat, low-level buffer of value slots of type T — the backing store for arrays and collections
|
|
6
|
+
**/
|
|
7
|
+
pub struct Buffer<T> {
|
|
8
|
+
var uint64 data = 0
|
|
9
|
+
var cap = 0
|
|
10
|
+
|
|
11
|
+
func alloc = (ref self, int size, out int: out >= size) {
|
|
12
|
+
```
|
|
13
|
+
#arch: c
|
|
14
|
+
self->cap = size;
|
|
15
|
+
self->data = (unsigned long long)(unsigned int*)calloc(size, sizeof(unsigned int));
|
|
16
|
+
return self->cap;
|
|
17
|
+
```
|
|
18
|
+
```
|
|
19
|
+
#arch: aarch64
|
|
20
|
+
str x1, [x19, #16]
|
|
21
|
+
mov x0, x1
|
|
22
|
+
mov x1, #4
|
|
23
|
+
bl _calloc
|
|
24
|
+
str x0, [x19, #8]
|
|
25
|
+
ldr x0, [x19, #16]
|
|
26
|
+
```
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func grow = (ref self, int needed, out int: out >= needed) {
|
|
30
|
+
```
|
|
31
|
+
#arch: c
|
|
32
|
+
if (self->cap >= needed) return self->cap;
|
|
33
|
+
int new_cap = self->cap;
|
|
34
|
+
if (new_cap == 0) new_cap = 8;
|
|
35
|
+
while (new_cap < needed) new_cap *= 2;
|
|
36
|
+
self->data = (unsigned long long)(unsigned int*)realloc((unsigned int*)(unsigned long long)self->data, new_cap * sizeof(unsigned int));
|
|
37
|
+
memset((unsigned int*)(unsigned long long)self->data + self->cap, 0, (new_cap - self->cap) * sizeof(unsigned int));
|
|
38
|
+
self->cap = new_cap;
|
|
39
|
+
return self->cap;
|
|
40
|
+
```
|
|
41
|
+
```
|
|
42
|
+
#arch: aarch64
|
|
43
|
+
ldr x2, [x19, #16]
|
|
44
|
+
cmp x2, x1
|
|
45
|
+
b.ge .Lbuffer_grow_end
|
|
46
|
+
mov x3, #8
|
|
47
|
+
cmp x2, #0
|
|
48
|
+
csel x3, x3, x2, eq
|
|
49
|
+
cmp x3, x1
|
|
50
|
+
b.ge .Lbuffer_grow_got
|
|
51
|
+
.Lbuffer_grow_loop:
|
|
52
|
+
lsl x3, x3, #1
|
|
53
|
+
cmp x3, x1
|
|
54
|
+
b.lt .Lbuffer_grow_loop
|
|
55
|
+
.Lbuffer_grow_got:
|
|
56
|
+
sub sp, sp, #16
|
|
57
|
+
str x2, [sp, #0]
|
|
58
|
+
str x3, [sp, #8]
|
|
59
|
+
ldr x0, [x19, #8]
|
|
60
|
+
lsl x1, x3, #2
|
|
61
|
+
bl _realloc
|
|
62
|
+
str x0, [x19, #8]
|
|
63
|
+
ldr x2, [sp, #0]
|
|
64
|
+
ldr x3, [sp, #8]
|
|
65
|
+
add sp, sp, #16
|
|
66
|
+
str x3, [x19, #16]
|
|
67
|
+
add x0, x0, x2, lsl #2
|
|
68
|
+
mov x1, #0
|
|
69
|
+
sub x2, x3, x2
|
|
70
|
+
lsl x2, x2, #2
|
|
71
|
+
bl _memset
|
|
72
|
+
.Lbuffer_grow_end:
|
|
73
|
+
ldr x0, [x19, #16]
|
|
74
|
+
```
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func zero = (ref self, int len) {
|
|
78
|
+
```
|
|
79
|
+
#arch: c
|
|
80
|
+
memset((unsigned int*)(unsigned long long)self->data, 0, len * sizeof(unsigned int));
|
|
81
|
+
```
|
|
82
|
+
```
|
|
83
|
+
#arch: aarch64
|
|
84
|
+
ldr x0, [x19, #8]
|
|
85
|
+
lsl x2, x1, #2
|
|
86
|
+
mov x1, #0
|
|
87
|
+
bl _memset
|
|
88
|
+
```
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
inline func load = (self, int i: i >= 0 && i < self.cap, out uint32) {
|
|
92
|
+
```
|
|
93
|
+
#arch: c
|
|
94
|
+
return ((unsigned int*)(unsigned long long)self->data)[i];
|
|
95
|
+
```
|
|
96
|
+
```
|
|
97
|
+
#arch: aarch64
|
|
98
|
+
ldr x0, [x19, #8]
|
|
99
|
+
lsl x1, x1, #2
|
|
100
|
+
add x0, x0, x1
|
|
101
|
+
ldr w0, [x0]
|
|
102
|
+
and x0, x0, #0xFFFFFFFF
|
|
103
|
+
```
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
inline func store = (ref self, int i: i >= 0 && i < self.cap, uint32 val) {
|
|
107
|
+
```
|
|
108
|
+
#arch: c
|
|
109
|
+
((unsigned int*)(unsigned long long)self->data)[i] = val;
|
|
110
|
+
```
|
|
111
|
+
```
|
|
112
|
+
#arch: aarch64
|
|
113
|
+
ldr x0, [x19, #8]
|
|
114
|
+
lsl x3, x1, #2
|
|
115
|
+
add x0, x0, x3
|
|
116
|
+
str w2, [x0]
|
|
117
|
+
```
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
inline func store_or = (ref self, int i: i >= 0 && i < self.cap, uint32 val) {
|
|
121
|
+
```
|
|
122
|
+
#arch: c
|
|
123
|
+
((unsigned int*)(unsigned long long)self->data)[i] |= val;
|
|
124
|
+
```
|
|
125
|
+
```
|
|
126
|
+
#arch: aarch64
|
|
127
|
+
ldr x0, [x19, #8]
|
|
128
|
+
lsl x3, x1, #2
|
|
129
|
+
add x0, x0, x3
|
|
130
|
+
ldr w3, [x0]
|
|
131
|
+
orr w3, w3, w2
|
|
132
|
+
str w3, [x0]
|
|
133
|
+
```
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
func alloc_int = (ref self, int size, out int: out >= size) {
|
|
137
|
+
```
|
|
138
|
+
#arch: c
|
|
139
|
+
self->cap = size;
|
|
140
|
+
self->data = (unsigned long long)(long*)calloc(size, sizeof(long));
|
|
141
|
+
return self->cap;
|
|
142
|
+
```
|
|
143
|
+
```
|
|
144
|
+
#arch: aarch64
|
|
145
|
+
str x1, [x19, #16]
|
|
146
|
+
mov x0, x1
|
|
147
|
+
mov x1, #8
|
|
148
|
+
bl _calloc
|
|
149
|
+
str x0, [x19, #8]
|
|
150
|
+
ldr x0, [x19, #16]
|
|
151
|
+
```
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
func grow_int = (ref self, int needed, out int: out >= needed) {
|
|
155
|
+
```
|
|
156
|
+
#arch: c
|
|
157
|
+
if (self->cap >= needed) return self->cap;
|
|
158
|
+
int new_cap = self->cap;
|
|
159
|
+
if (new_cap == 0) new_cap = 4;
|
|
160
|
+
while (new_cap < needed) new_cap *= 2;
|
|
161
|
+
self->data = (unsigned long long)(long*)realloc((long*)(unsigned long long)self->data, new_cap * sizeof(long));
|
|
162
|
+
memset((long*)(unsigned long long)self->data + self->cap, 0, (new_cap - self->cap) * sizeof(long));
|
|
163
|
+
self->cap = new_cap;
|
|
164
|
+
return self->cap;
|
|
165
|
+
```
|
|
166
|
+
```
|
|
167
|
+
#arch: aarch64
|
|
168
|
+
ldr x2, [x19, #16]
|
|
169
|
+
cmp x2, x1
|
|
170
|
+
b.ge .Lbuffer_grow_int_end
|
|
171
|
+
mov x3, #4
|
|
172
|
+
cmp x2, #0
|
|
173
|
+
csel x3, x3, x2, eq
|
|
174
|
+
cmp x3, x1
|
|
175
|
+
b.ge .Lbuffer_grow_int_got
|
|
176
|
+
.Lbuffer_grow_int_loop:
|
|
177
|
+
lsl x3, x3, #1
|
|
178
|
+
cmp x3, x1
|
|
179
|
+
b.lt .Lbuffer_grow_int_loop
|
|
180
|
+
.Lbuffer_grow_int_got:
|
|
181
|
+
sub sp, sp, #16
|
|
182
|
+
str x2, [sp, #0]
|
|
183
|
+
str x3, [sp, #8]
|
|
184
|
+
ldr x0, [x19, #8]
|
|
185
|
+
lsl x1, x3, #3
|
|
186
|
+
bl _realloc
|
|
187
|
+
str x0, [x19, #8]
|
|
188
|
+
ldr x2, [sp, #0]
|
|
189
|
+
ldr x3, [sp, #8]
|
|
190
|
+
add sp, sp, #16
|
|
191
|
+
str x3, [x19, #16]
|
|
192
|
+
add x0, x0, x2, lsl #3
|
|
193
|
+
mov x1, #0
|
|
194
|
+
sub x2, x3, x2
|
|
195
|
+
lsl x2, x2, #3
|
|
196
|
+
bl _memset
|
|
197
|
+
.Lbuffer_grow_int_end:
|
|
198
|
+
ldr x0, [x19, #16]
|
|
199
|
+
```
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
inline func load_int = (self, int i: i >= 0 && i < self.cap, out int) {
|
|
203
|
+
```
|
|
204
|
+
#arch: c
|
|
205
|
+
return ((long*)(unsigned long long)self->data)[i];
|
|
206
|
+
```
|
|
207
|
+
```
|
|
208
|
+
#arch: aarch64
|
|
209
|
+
ldr x0, [x19, #8]
|
|
210
|
+
lsl x1, x1, #3
|
|
211
|
+
add x0, x0, x1
|
|
212
|
+
ldr x0, [x0]
|
|
213
|
+
```
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
inline func store_int = (ref self, int i: i >= 0 && i < self.cap, int val) {
|
|
217
|
+
```
|
|
218
|
+
#arch: c
|
|
219
|
+
((long*)(unsigned long long)self->data)[i] = val;
|
|
220
|
+
```
|
|
221
|
+
```
|
|
222
|
+
#arch: aarch64
|
|
223
|
+
ldr x0, [x19, #8]
|
|
224
|
+
lsl x3, x1, #3
|
|
225
|
+
add x0, x0, x3
|
|
226
|
+
str x2, [x0]
|
|
227
|
+
```
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Move a value out of a slot: return it and clear the slot to 0. This is
|
|
231
|
+
// the ownership-extracting primitive (used by e.g. List.pop) — unlike
|
|
232
|
+
// load_int (a borrow read), it relinquishes the slot so the buffer no
|
|
233
|
+
// longer owns the value.
|
|
234
|
+
inline func move_int = (ref self, int i: i >= 0 && i < self.cap, out int) {
|
|
235
|
+
```
|
|
236
|
+
#arch: c
|
|
237
|
+
long *slots = (long*)(unsigned long long)self->data;
|
|
238
|
+
long val = slots[i];
|
|
239
|
+
slots[i] = 0;
|
|
240
|
+
return val;
|
|
241
|
+
```
|
|
242
|
+
```
|
|
243
|
+
#arch: aarch64
|
|
244
|
+
ldr x0, [x19, #8]
|
|
245
|
+
lsl x3, x1, #3
|
|
246
|
+
add x3, x0, x3
|
|
247
|
+
ldr x0, [x3]
|
|
248
|
+
str xzr, [x3]
|
|
249
|
+
```
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Store into a slot, freeing the previous value when the buffer holds
|
|
253
|
+
// owned class pointers (has_class_refs). For non-class buffers this is a
|
|
254
|
+
// plain store, so it is safe to use anywhere store_int would be.
|
|
255
|
+
inline func replace_int = (ref self, int i: i >= 0 && i < self.cap, int val) {
|
|
256
|
+
```
|
|
257
|
+
#arch: c
|
|
258
|
+
((long*)(unsigned long long)self->data)[i] = val;
|
|
259
|
+
```
|
|
260
|
+
```
|
|
261
|
+
#arch: aarch64
|
|
262
|
+
ldr x0, [x19, #8]
|
|
263
|
+
lsl x3, x1, #3
|
|
264
|
+
add x0, x0, x3
|
|
265
|
+
str x2, [x0]
|
|
266
|
+
```
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
inline func zero_int = (ref self, int len) {
|
|
270
|
+
```
|
|
271
|
+
#arch: c
|
|
272
|
+
memset((long*)(unsigned long long)self->data, 0, len * sizeof(long));
|
|
273
|
+
```
|
|
274
|
+
```
|
|
275
|
+
#arch: aarch64
|
|
276
|
+
ldr x0, [x19, #8]
|
|
277
|
+
lsl x2, x1, #3
|
|
278
|
+
mov x1, #0
|
|
279
|
+
bl _memset
|
|
280
|
+
```
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// T_SIZE-aware primitives for value-struct elements. Slab is sized in
|
|
284
|
+
// multiples of T_SIZE; load/store use memcpy so multi-word structs work
|
|
285
|
+
// correctly. Classes route to ClassBuffer<T> (per-element destroy), so T
|
|
286
|
+
// reaching here is always a value type (primitive or struct).
|
|
287
|
+
|
|
288
|
+
func alloc_T = (ref self, int size, out int: out >= size) {
|
|
289
|
+
```
|
|
290
|
+
#arch: c
|
|
291
|
+
self->cap = size;
|
|
292
|
+
self->data = (unsigned long long)(T*)calloc(size, T_SIZE);
|
|
293
|
+
return self->cap;
|
|
294
|
+
```
|
|
295
|
+
```
|
|
296
|
+
#arch: aarch64
|
|
297
|
+
str x1, [x19, #16]
|
|
298
|
+
mov x0, x1
|
|
299
|
+
mov x1, #T_SIZE
|
|
300
|
+
bl _calloc
|
|
301
|
+
str x0, [x19, #8]
|
|
302
|
+
ldr x0, [x19, #16]
|
|
303
|
+
```
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
func grow_T = (ref self, int needed, out int: out >= needed) {
|
|
307
|
+
```
|
|
308
|
+
#arch: c
|
|
309
|
+
if (self->cap >= needed) return self->cap;
|
|
310
|
+
int new_cap = self->cap;
|
|
311
|
+
if (new_cap == 0) new_cap = 4;
|
|
312
|
+
while (new_cap < needed) new_cap *= 2;
|
|
313
|
+
self->data = (unsigned long long)(T*)realloc((T*)(unsigned long long)self->data, new_cap * T_SIZE);
|
|
314
|
+
memset((char*)(unsigned long long)self->data + self->cap * T_SIZE, 0, (new_cap - self->cap) * T_SIZE);
|
|
315
|
+
self->cap = new_cap;
|
|
316
|
+
return self->cap;
|
|
317
|
+
```
|
|
318
|
+
```
|
|
319
|
+
#arch: aarch64
|
|
320
|
+
ldr x2, [x19, #16]
|
|
321
|
+
cmp x2, x1
|
|
322
|
+
b.ge .Lbuffer_grow_T_end
|
|
323
|
+
mov x3, #4
|
|
324
|
+
cmp x2, #0
|
|
325
|
+
csel x3, x3, x2, eq
|
|
326
|
+
cmp x3, x1
|
|
327
|
+
b.ge .Lbuffer_grow_T_got
|
|
328
|
+
.Lbuffer_grow_T_loop:
|
|
329
|
+
lsl x3, x3, #1
|
|
330
|
+
cmp x3, x1
|
|
331
|
+
b.lt .Lbuffer_grow_T_loop
|
|
332
|
+
.Lbuffer_grow_T_got:
|
|
333
|
+
sub sp, sp, #32
|
|
334
|
+
str x2, [sp, #0]
|
|
335
|
+
str x3, [sp, #8]
|
|
336
|
+
mov x4, #T_SIZE
|
|
337
|
+
str x4, [sp, #16]
|
|
338
|
+
ldr x0, [x19, #8]
|
|
339
|
+
madd x1, x3, x4, xzr
|
|
340
|
+
bl _realloc
|
|
341
|
+
str x0, [x19, #8]
|
|
342
|
+
ldr x2, [sp, #0]
|
|
343
|
+
ldr x3, [sp, #8]
|
|
344
|
+
ldr x4, [sp, #16]
|
|
345
|
+
add sp, sp, #32
|
|
346
|
+
str x3, [x19, #16]
|
|
347
|
+
ldr x0, [x19, #8]
|
|
348
|
+
mul x5, x2, x4
|
|
349
|
+
add x0, x0, x5
|
|
350
|
+
sub x2, x3, x2
|
|
351
|
+
mul x2, x2, x4
|
|
352
|
+
mov x1, #0
|
|
353
|
+
bl _memset
|
|
354
|
+
.Lbuffer_grow_T_end:
|
|
355
|
+
ldr x0, [x19, #16]
|
|
356
|
+
```
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
func load_T = (self, int i: i >= 0 && i < self.cap, out T) {
|
|
360
|
+
```
|
|
361
|
+
#arch: c
|
|
362
|
+
return ((T*)(unsigned long long)self->data)[i];
|
|
363
|
+
```
|
|
364
|
+
```
|
|
365
|
+
#arch: aarch64
|
|
366
|
+
// x19 = self, x1 = i, x8 = return buf for structs
|
|
367
|
+
ldr x0, [x19, #8]
|
|
368
|
+
mov x3, #T_SIZE
|
|
369
|
+
madd x1, x1, x3, xzr
|
|
370
|
+
add x0, x0, x1
|
|
371
|
+
cmp x3, #8
|
|
372
|
+
b.gt .Lbuffer_load_T_copy
|
|
373
|
+
ldr x0, [x0]
|
|
374
|
+
b .Lbuffer_load_T_end
|
|
375
|
+
.Lbuffer_load_T_copy:
|
|
376
|
+
mov x1, x0
|
|
377
|
+
mov x0, x8
|
|
378
|
+
mov x2, x3
|
|
379
|
+
bl _memcpy
|
|
380
|
+
.Lbuffer_load_T_end:
|
|
381
|
+
```
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
func store_T = (ref self, int i: i >= 0 && i < self.cap, T val) {
|
|
385
|
+
```
|
|
386
|
+
#arch: c
|
|
387
|
+
((T*)(unsigned long long)self->data)[i] = val;
|
|
388
|
+
```
|
|
389
|
+
```
|
|
390
|
+
#arch: aarch64
|
|
391
|
+
// x19 = self, x1 = i, x2 = val (value if T_SIZE<=8, address if struct)
|
|
392
|
+
ldr x0, [x19, #8]
|
|
393
|
+
mov x3, #T_SIZE
|
|
394
|
+
madd x1, x1, x3, xzr
|
|
395
|
+
add x0, x0, x1
|
|
396
|
+
cmp x3, #8
|
|
397
|
+
b.gt .Lbuffer_store_T_copy
|
|
398
|
+
str x2, [x0]
|
|
399
|
+
b .Lbuffer_store_T_end
|
|
400
|
+
.Lbuffer_store_T_copy:
|
|
401
|
+
mov x1, x2
|
|
402
|
+
mov x2, x3
|
|
403
|
+
bl _memcpy
|
|
404
|
+
.Lbuffer_store_T_end:
|
|
405
|
+
```
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// A non-owning (ptr, len) slice [start, end) over this buffer's element
|
|
409
|
+
// storage, returned as a `view T`. It borrows from self: it may not outlive
|
|
410
|
+
// self's scope and is invalidated if self is reassigned. This is the single
|
|
411
|
+
// primitive every other slice (Array<T>, List<T>, user containers) builds
|
|
412
|
+
// on — higher layers just `return self.items.slice(start, end)`.
|
|
413
|
+
func slice = (self, int start: start >= 0, int end: end >= start, out view T) {
|
|
414
|
+
```
|
|
415
|
+
#arch: c
|
|
416
|
+
nomen_view _r;
|
|
417
|
+
_r.ptr = (void*)((T*)(unsigned long long)self->data + start);
|
|
418
|
+
_r.len = (long)(end - start);
|
|
419
|
+
return _r;
|
|
420
|
+
```
|
|
421
|
+
```
|
|
422
|
+
#arch: aarch64
|
|
423
|
+
// x19 = self (Buffer struct ptr), x1 = start, x2 = end.
|
|
424
|
+
// self->data lives at [x19, #8]. Return (ptr, len) in x0/x1.
|
|
425
|
+
ldr x0, [x19, #8]
|
|
426
|
+
mov x3, #T_SIZE
|
|
427
|
+
madd x0, x1, x3, x0
|
|
428
|
+
sub x1, x2, x1
|
|
429
|
+
```
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
inline func zero_T = (ref self, int len) {
|
|
433
|
+
```
|
|
434
|
+
#arch: c
|
|
435
|
+
memset((T*)(unsigned long long)self->data, 0, len * T_SIZE);
|
|
436
|
+
```
|
|
437
|
+
```
|
|
438
|
+
#arch: aarch64
|
|
439
|
+
ldr x0, [x19, #8]
|
|
440
|
+
mov x2, #T_SIZE
|
|
441
|
+
mul x2, x1, x2
|
|
442
|
+
mov x1, #0
|
|
443
|
+
bl _memset
|
|
444
|
+
```
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
inline func store_or_int = (ref self, int i: i >= 0 && i < self.cap, int val) {
|
|
448
|
+
```
|
|
449
|
+
#arch: c
|
|
450
|
+
((long*)(unsigned long long)self->data)[i] |= val;
|
|
451
|
+
```
|
|
452
|
+
```
|
|
453
|
+
#arch: aarch64
|
|
454
|
+
ldr x0, [x19, #8]
|
|
455
|
+
lsl x3, x1, #3
|
|
456
|
+
add x0, x0, x3
|
|
457
|
+
ldr x3, [x0]
|
|
458
|
+
orr x3, x3, x2
|
|
459
|
+
str x3, [x0]
|
|
460
|
+
```
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
func alloc_float = (ref self, int size, out int: out >= size) {
|
|
464
|
+
```
|
|
465
|
+
#arch: c
|
|
466
|
+
self->cap = size;
|
|
467
|
+
self->data = (unsigned long long)(double*)calloc(size, sizeof(double));
|
|
468
|
+
return self->cap;
|
|
469
|
+
```
|
|
470
|
+
```
|
|
471
|
+
#arch: aarch64
|
|
472
|
+
str x1, [x19, #16]
|
|
473
|
+
mov x0, x1
|
|
474
|
+
mov x1, #8
|
|
475
|
+
bl _calloc
|
|
476
|
+
str x0, [x19, #8]
|
|
477
|
+
ldr x0, [x19, #16]
|
|
478
|
+
```
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
inline func load_float = (self, int i: i >= 0 && i < self.cap, out float) {
|
|
482
|
+
```
|
|
483
|
+
#arch: c
|
|
484
|
+
return ((double*)(unsigned long long)self->data)[i];
|
|
485
|
+
```
|
|
486
|
+
```
|
|
487
|
+
#arch: aarch64
|
|
488
|
+
ldr x0, [x19, #8]
|
|
489
|
+
lsl x1, x1, #3
|
|
490
|
+
add x0, x0, x1
|
|
491
|
+
ldr x0, [x0]
|
|
492
|
+
```
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
inline func store_float = (ref self, int i: i >= 0 && i < self.cap, float val) {
|
|
496
|
+
```
|
|
497
|
+
#arch: c
|
|
498
|
+
((double*)(unsigned long long)self->data)[i] = val;
|
|
499
|
+
```
|
|
500
|
+
```
|
|
501
|
+
#arch: aarch64
|
|
502
|
+
ldr x0, [x19, #8]
|
|
503
|
+
lsl x3, x1, #3
|
|
504
|
+
add x0, x0, x3
|
|
505
|
+
str x2, [x0]
|
|
506
|
+
```
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
func #destroy = () {
|
|
510
|
+
```
|
|
511
|
+
#arch: c
|
|
512
|
+
if (self->data) free((unsigned int*)(unsigned long long)self->data);
|
|
513
|
+
self->data = 0;
|
|
514
|
+
self->cap = 0;
|
|
515
|
+
```
|
|
516
|
+
```
|
|
517
|
+
#arch: aarch64
|
|
518
|
+
ldr x0, [x19, #8]
|
|
519
|
+
cbz x0, .Lbuffer_destroy_end
|
|
520
|
+
bl _free
|
|
521
|
+
.Lbuffer_destroy_end:
|
|
522
|
+
str xzr, [x19, #8]
|
|
523
|
+
str xzr, [x19, #16]
|
|
524
|
+
```
|
|
525
|
+
}
|
|
526
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Channel — thread-safe single-direction queue for passing values between
|
|
2
|
+
// tasks. Unbounded, FIFO, blocking receive.
|
|
3
|
+
//
|
|
4
|
+
// Stores uint64 values (Nomen values are pointer-sized on every target we
|
|
5
|
+
// care about). A typed Channel<T> wrapper can come later — the storage story
|
|
6
|
+
// is identical, only the call-site types change.
|
|
7
|
+
//
|
|
8
|
+
// Default stance in Nomen is "no shared mutable state" — channels are the
|
|
9
|
+
// preferred way for tasks to communicate. See ASYNC.md.
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A thread-safe, blocking FIFO queue for passing values between tasks
|
|
13
|
+
**/
|
|
14
|
+
pub class Channel: Sendable {
|
|
15
|
+
pub var uint64 mu = 0
|
|
16
|
+
pub var uint64 not_empty_cv = 0
|
|
17
|
+
pub var uint64 head = 0
|
|
18
|
+
pub var uint64 tail = 0
|
|
19
|
+
|
|
20
|
+
pub func #init = (self) {
|
|
21
|
+
```
|
|
22
|
+
#arch: c
|
|
23
|
+
#scope: file
|
|
24
|
+
#include <pthread.h>
|
|
25
|
+
struct nomen_channel_node {
|
|
26
|
+
unsigned long long value;
|
|
27
|
+
struct nomen_channel_node *next;
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
```
|
|
31
|
+
#arch: c
|
|
32
|
+
self->mu = (unsigned long long)malloc(sizeof(pthread_mutex_t));
|
|
33
|
+
self->not_empty_cv = (unsigned long long)malloc(sizeof(pthread_cond_t));
|
|
34
|
+
pthread_mutex_init((pthread_mutex_t *)self->mu, NULL);
|
|
35
|
+
pthread_cond_init((pthread_cond_t *)self->not_empty_cv, NULL);
|
|
36
|
+
self->head = 0;
|
|
37
|
+
self->tail = 0;
|
|
38
|
+
```
|
|
39
|
+
```
|
|
40
|
+
#arch: aarch64
|
|
41
|
+
mov x0, #64
|
|
42
|
+
bl _malloc
|
|
43
|
+
str x0, [x19, #8]
|
|
44
|
+
mov x1, #0
|
|
45
|
+
bl _pthread_mutex_init
|
|
46
|
+
mov x0, #64
|
|
47
|
+
bl _malloc
|
|
48
|
+
str x0, [x19, #16]
|
|
49
|
+
mov x1, #0
|
|
50
|
+
bl _pthread_cond_init
|
|
51
|
+
str xzr, [x19, #24]
|
|
52
|
+
str xzr, [x19, #32]
|
|
53
|
+
```
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub func send = (self, uint64 value) {
|
|
57
|
+
```
|
|
58
|
+
#arch: c
|
|
59
|
+
struct nomen_channel_node *n = (struct nomen_channel_node *)malloc(sizeof(struct nomen_channel_node));
|
|
60
|
+
n->value = value;
|
|
61
|
+
n->next = NULL;
|
|
62
|
+
pthread_mutex_lock((pthread_mutex_t *)self->mu);
|
|
63
|
+
if (self->tail) {
|
|
64
|
+
((struct nomen_channel_node *)self->tail)->next = n;
|
|
65
|
+
} else {
|
|
66
|
+
self->head = (unsigned long long)n;
|
|
67
|
+
}
|
|
68
|
+
self->tail = (unsigned long long)n;
|
|
69
|
+
pthread_cond_signal((pthread_cond_t *)self->not_empty_cv);
|
|
70
|
+
pthread_mutex_unlock((pthread_mutex_t *)self->mu);
|
|
71
|
+
```
|
|
72
|
+
```
|
|
73
|
+
#arch: aarch64
|
|
74
|
+
// x19 = self (set by prologue), x1 = value
|
|
75
|
+
str x1, [sp, #-16]! // save value on stack
|
|
76
|
+
mov x0, #16
|
|
77
|
+
bl _malloc // x0 = node
|
|
78
|
+
ldr x1, [sp], #16 // restore value
|
|
79
|
+
str x1, [x0, #0] // node->value = value
|
|
80
|
+
str xzr, [x0, #8] // node->next = NULL
|
|
81
|
+
str x0, [sp, #-16]! // save node on stack
|
|
82
|
+
ldr x0, [x19, #8] // self->mu
|
|
83
|
+
bl _pthread_mutex_lock
|
|
84
|
+
ldr x2, [sp], #16 // restore node
|
|
85
|
+
ldr x1, [x19, #32] // tail
|
|
86
|
+
cbz x1, .Lchannel_send_empty
|
|
87
|
+
str x2, [x1, #8] // tail->next = node
|
|
88
|
+
b .Lchannel_send_enqueued
|
|
89
|
+
.Lchannel_send_empty:
|
|
90
|
+
str x2, [x19, #24] // head = node
|
|
91
|
+
.Lchannel_send_enqueued:
|
|
92
|
+
str x2, [x19, #32] // tail = node
|
|
93
|
+
ldr x0, [x19, #16] // not_empty_cv
|
|
94
|
+
bl _pthread_cond_signal
|
|
95
|
+
ldr x0, [x19, #8] // self->mu
|
|
96
|
+
bl _pthread_mutex_unlock
|
|
97
|
+
```
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
pub func receive = (self, out uint64) {
|
|
101
|
+
```
|
|
102
|
+
#arch: c
|
|
103
|
+
pthread_mutex_lock((pthread_mutex_t *)self->mu);
|
|
104
|
+
while (!self->head) {
|
|
105
|
+
pthread_cond_wait((pthread_cond_t *)self->not_empty_cv, (pthread_mutex_t *)self->mu);
|
|
106
|
+
}
|
|
107
|
+
struct nomen_channel_node *n = (struct nomen_channel_node *)self->head;
|
|
108
|
+
self->head = (unsigned long long)n->next;
|
|
109
|
+
if (!self->head) self->tail = 0;
|
|
110
|
+
unsigned long long v = n->value;
|
|
111
|
+
free(n);
|
|
112
|
+
pthread_mutex_unlock((pthread_mutex_t *)self->mu);
|
|
113
|
+
return v;
|
|
114
|
+
```
|
|
115
|
+
```
|
|
116
|
+
#arch: aarch64
|
|
117
|
+
// x19 = self (set by prologue)
|
|
118
|
+
ldr x0, [x19, #8] // self->mu
|
|
119
|
+
bl _pthread_mutex_lock
|
|
120
|
+
.Lchannel_receive_wait:
|
|
121
|
+
ldr x1, [x19, #24] // head
|
|
122
|
+
cbnz x1, .Lchannel_receive_got
|
|
123
|
+
ldr x0, [x19, #16] // not_empty_cv
|
|
124
|
+
ldr x1, [x19, #8] // mu
|
|
125
|
+
bl _pthread_cond_wait
|
|
126
|
+
b .Lchannel_receive_wait
|
|
127
|
+
.Lchannel_receive_got:
|
|
128
|
+
// x1 = node
|
|
129
|
+
ldr x2, [x1, #8] // node->next
|
|
130
|
+
str x2, [x19, #24] // head = node->next
|
|
131
|
+
cbnz x2, .Lchannel_receive_not_empty
|
|
132
|
+
str xzr, [x19, #32] // tail = 0
|
|
133
|
+
.Lchannel_receive_not_empty:
|
|
134
|
+
ldr x0, [x1, #0] // x0 = value
|
|
135
|
+
str x0, [sp, #-16]! // push value
|
|
136
|
+
mov x0, x1 // x0 = node (for free)
|
|
137
|
+
bl _free
|
|
138
|
+
ldr x0, [x19, #8] // self->mu
|
|
139
|
+
bl _pthread_mutex_unlock
|
|
140
|
+
ldr x0, [sp], #16 // pop value → x0 (return)
|
|
141
|
+
```
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pub func #destroy = () {
|
|
145
|
+
```
|
|
146
|
+
#arch: c
|
|
147
|
+
if (self->mu) {
|
|
148
|
+
// Drain any pending nodes.
|
|
149
|
+
struct nomen_channel_node *n = (struct nomen_channel_node *)self->head;
|
|
150
|
+
while (n) {
|
|
151
|
+
struct nomen_channel_node *next = n->next;
|
|
152
|
+
free(n);
|
|
153
|
+
n = next;
|
|
154
|
+
}
|
|
155
|
+
pthread_mutex_destroy((pthread_mutex_t *)self->mu);
|
|
156
|
+
pthread_cond_destroy((pthread_cond_t *)self->not_empty_cv);
|
|
157
|
+
free((void *)self->mu);
|
|
158
|
+
free((void *)self->not_empty_cv);
|
|
159
|
+
self->mu = 0;
|
|
160
|
+
self->not_empty_cv = 0;
|
|
161
|
+
self->head = 0;
|
|
162
|
+
self->tail = 0;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
```
|
|
166
|
+
#arch: aarch64
|
|
167
|
+
// x19 = self (set by prologue)
|
|
168
|
+
ldr x0, [x19, #8] // self->mu
|
|
169
|
+
cbz x0, .Lchannel_destroy_done
|
|
170
|
+
// Drain nodes
|
|
171
|
+
ldr x1, [x19, #24] // head
|
|
172
|
+
.Lchannel_destroy_drain:
|
|
173
|
+
cbz x1, .Lchannel_destroy_drained
|
|
174
|
+
ldr x2, [x1, #8] // next (before free clobbers it)
|
|
175
|
+
str x2, [sp, #-16]! // save next on stack
|
|
176
|
+
bl _free
|
|
177
|
+
ldr x1, [sp], #16 // restore next
|
|
178
|
+
b .Lchannel_destroy_drain
|
|
179
|
+
.Lchannel_destroy_drained:
|
|
180
|
+
// Destroy mutex and condvar
|
|
181
|
+
ldr x0, [x19, #8]
|
|
182
|
+
bl _pthread_mutex_destroy
|
|
183
|
+
ldr x0, [x19, #16]
|
|
184
|
+
bl _pthread_cond_destroy
|
|
185
|
+
// Free mutex and condvar allocations
|
|
186
|
+
ldr x0, [x19, #8]
|
|
187
|
+
bl _free
|
|
188
|
+
ldr x0, [x19, #16]
|
|
189
|
+
bl _free
|
|
190
|
+
// Zero all fields
|
|
191
|
+
str xzr, [x19, #8]
|
|
192
|
+
str xzr, [x19, #16]
|
|
193
|
+
str xzr, [x19, #24]
|
|
194
|
+
str xzr, [x19, #32]
|
|
195
|
+
.Lchannel_destroy_done:
|
|
196
|
+
```
|
|
197
|
+
}
|
|
198
|
+
}
|