nomen-lang 0.0.17 → 0.0.19

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.
@@ -30,7 +30,7 @@ pub struct Array<T>: Viewable {
30
30
  ```
31
31
  }
32
32
 
33
- pub func at = (self, int index: index >= 0 && index < self.length, out T) {
33
+ pub inline func at = (self, int index: index >= 0 && index < self.length, out T) {
34
34
  ```
35
35
  #arch: c
36
36
  T* _data = (T*)((char*)self + sizeof(*self));
@@ -160,6 +160,26 @@ pub struct Array<T>: Viewable {
160
160
  ```
161
161
  }
162
162
 
163
+ // Bounds-checked accessors — the runtime-checked escape hatch for
164
+ // indices the constraint checker can't prove (see PERF.md gap 5). Unlike
165
+ // every other Array method these have Nomen-level bodies: the method-call
166
+ // receiver conventions for Array receivers (first-element pointer on
167
+ // aarch64, struct Array_<T>* on C) are passed through unchanged, and the
168
+ // bodies read self.length / self.at through them.
169
+ pub func at_or = (self, int index, T fallback, out T) {
170
+ if index >= 0 && index < self.length {
171
+ return self.at(index)
172
+ }
173
+ return fallback
174
+ }
175
+
176
+ pub func at_or_panic = (self, int index, out T) {
177
+ if index >= 0 && index < self.length {
178
+ return self.at(index)
179
+ }
180
+ panic("index out of range")
181
+ }
182
+
163
183
  pub func at_end = (self, out T) {
164
184
  ```
165
185
  #arch: c
@@ -553,6 +553,78 @@ pub struct Buffer<T> {
553
553
  ```
554
554
  }
555
555
 
556
+ // Move slot src into slot dst: overwrite dst with src's bytes and zero
557
+ // src, so exactly ONE slot owns the value afterwards. The
558
+ // ownership-transferring primitive behind backward-shift deletion
559
+ // (Map/Set.remove) — unlike store_T, which gives the slot its own deep
560
+ // copy and leaves the source slot intact, a shift transfers the source's
561
+ // heap pointers wholesale. For owning elements (string / value structs
562
+ // with string fields) the build replaces this body with a specialized
563
+ // version that also reclaims dst's previous value first (see
564
+ // owning_buffer_specialize.ts); this raw form is correct for
565
+ // trivially-destructible elements only.
566
+ inline func shift_T = (ref self, int dst: dst >= 0 && dst < self.cap, int src: src >= 0 && src < self.cap) {
567
+ ```
568
+ #arch: c
569
+ T* _slots = (T*)(unsigned long long)self->data;
570
+ if (dst != src) {
571
+ _slots[dst] = _slots[src];
572
+ memset((void*)&_slots[src], 0, T_SIZE);
573
+ }
574
+ ```
575
+ ```
576
+ #arch: aarch64
577
+ // x19 = self, x1 = dst, x2 = src
578
+ ldr x4, [x19, #8]
579
+ mov x3, #T_SIZE
580
+ madd x5, x1, x3, x4
581
+ madd x6, x2, x3, x4
582
+ cmp x5, x6
583
+ b.eq .Lbuffer_shift_T_end
584
+ cmp x3, #8
585
+ b.gt .Lbuffer_shift_T_copy
586
+ // Width-matched move: an 8-byte access on a sub-8 element would
587
+ // clobber the following slot (and run past the slab's end).
588
+ cmp x3, #1
589
+ b.eq .Lbuffer_shift_T_1
590
+ cmp x3, #2
591
+ b.eq .Lbuffer_shift_T_2
592
+ cmp x3, #4
593
+ b.eq .Lbuffer_shift_T_4
594
+ ldr x7, [x6]
595
+ str x7, [x5]
596
+ str xzr, [x6]
597
+ b .Lbuffer_shift_T_end
598
+ .Lbuffer_shift_T_1:
599
+ ldrb w7, [x6]
600
+ strb w7, [x5]
601
+ strb wzr, [x6]
602
+ b .Lbuffer_shift_T_end
603
+ .Lbuffer_shift_T_2:
604
+ ldrh w7, [x6]
605
+ strh w7, [x5]
606
+ strh wzr, [x6]
607
+ b .Lbuffer_shift_T_end
608
+ .Lbuffer_shift_T_4:
609
+ ldr w7, [x6]
610
+ str w7, [x5]
611
+ str wzr, [x6]
612
+ b .Lbuffer_shift_T_end
613
+ .Lbuffer_shift_T_copy:
614
+ mov x0, x5
615
+ mov x1, x6
616
+ mov x2, x3
617
+ stp x5, x6, [sp, #-16]!
618
+ bl _memcpy
619
+ ldp x5, x6, [sp], #16
620
+ mov x0, x6
621
+ mov x1, #0
622
+ mov x2, x3
623
+ bl _memset
624
+ .Lbuffer_shift_T_end:
625
+ ```
626
+ }
627
+
556
628
  // A non-owning (ptr, len) slice [start, end) over this buffer's element
557
629
  // storage, returned as a `view T`. It borrows from self: it may not outlive
558
630
  // self's scope and is invalidated if self is reassigned. This is the single
@@ -299,6 +299,51 @@ pub struct ClassBuffer<T> {
299
299
  ```
300
300
  }
301
301
 
302
+ // Move slot src into slot dst: reclaim dst's previous instance (destroy +
303
+ // free), take over src's pointer, and zero src — exactly one slot owns the
304
+ // instance afterwards. The class-buffer counterpart of Buffer.shift_T,
305
+ // used by Map/Set.remove's backward-shift so shifting entries neither
306
+ // duplicates nor orphans owned instances.
307
+ func shift_T = (ref self, int dst: dst >= 0 && dst < self.cap, int src: src >= 0 && src < self.cap) {
308
+ ```
309
+ #arch: c
310
+ long *slots = (long*)(unsigned long long)self->data;
311
+ if (dst != src) {
312
+ if (slots[dst]) {
313
+ T_destroy((void*)slots[dst]);
314
+ free((void*)slots[dst]);
315
+ }
316
+ slots[dst] = slots[src];
317
+ slots[src] = 0;
318
+ }
319
+ ```
320
+ ```
321
+ #arch: aarch64
322
+ stp x20, x21, [sp, #-16]!
323
+ str x22, [sp, #-16]!
324
+ ldr x9, [x19, #8]
325
+ lsl x3, x1, #3
326
+ add x20, x9, x3
327
+ lsl x3, x2, #3
328
+ add x21, x9, x3
329
+ cmp x20, x21
330
+ b.eq .Lcb_shift_T_done
331
+ ldr x0, [x20]
332
+ cbz x0, .Lcb_shift_T_move
333
+ mov x22, x0
334
+ bl T_destroy
335
+ mov x0, x22
336
+ bl _free
337
+ .Lcb_shift_T_move:
338
+ ldr x9, [x21]
339
+ str x9, [x20]
340
+ str xzr, [x21]
341
+ .Lcb_shift_T_done:
342
+ ldr x22, [sp], #16
343
+ ldp x20, x21, [sp], #16
344
+ ```
345
+ }
346
+
302
347
  // A non-owning (ptr, len) slice [start, end) over this buffer's class
303
348
  // pointers, returned as a `view T` (T is a class, so each element is an
304
349
  // 8-byte pointer). Borrows from self — invalidated on reassignment. Mirrors
@@ -27,7 +27,7 @@ pub struct List<T>: Viewable {
27
27
  return self.items.move_T(idx)
28
28
  }
29
29
 
30
- pub func at = (self, int i: i >= 0 && i < self.length, out T) {
30
+ pub inline func at = (self, int i: i >= 0 && i < self.length, out T) {
31
31
  return self.items.load_T(i)
32
32
  }
33
33
 
@@ -134,8 +134,13 @@ pub struct Map<TK: Hashable + Equatable, TV> {
134
134
  dk = dk + cap
135
135
  }
136
136
  if dgap < dk {
137
- self.keys.store_T(gap, self.keys.load_T(k))
138
- self.values.store_T(gap, self.values.load_T(k))
137
+ // shift_T (not store_T): transfers the entry's owned pointers
138
+ // wholesale and reclaims the displaced slot's value. store_T
139
+ // would strdup a fresh copy into gap while leaving the source
140
+ // slot's pointer stranded at the vacated slot — leaked once
141
+ // used.store marks it empty (the buffer destroy skips it).
142
+ self.keys.shift_T(gap, k)
143
+ self.values.shift_T(gap, k)
139
144
  self.used.store(gap, 1)
140
145
  gap = k
141
146
  }
@@ -117,7 +117,12 @@ pub struct Set<T: Hashable + Equatable> {
117
117
  dk = dk + cap
118
118
  }
119
119
  if dgap < dk {
120
- self.slots.store_T(gap, self.slots.load_T(k))
120
+ // shift_T (not store_T): transfers the entry wholesale and
121
+ // reclaims the displaced slot's value — store_T would strdup a
122
+ // fresh copy into gap while stranding the source slot's
123
+ // pointer at the vacated slot (leaked once used.store marks it
124
+ // empty; the buffer destroy skips unused slots).
125
+ self.slots.shift_T(gap, k)
121
126
  self.used.store(gap, 1)
122
127
  gap = k
123
128
  }
@@ -7,6 +7,8 @@ A fixed-length array of values, created with a literal (`[1, 2, 3]`) and address
7
7
  **Members:**
8
8
 
9
9
  - `at(int index) -> T`
10
+ - `at_or(int index, T fallback) -> T`
11
+ - `at_or_panic(int index) -> T`
10
12
  - `first() -> T`
11
13
  - `set(int index, T value)`
12
14
  - `at_end() -> T`