nomen-lang 0.6.7 → 0.6.9

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 CHANGED
@@ -219,9 +219,9 @@ Special function names: `#init` (constructor), `#destroy` (auto-raii destructor)
219
219
 
220
220
  ```nomen
221
221
  if cond { ... }
222
- switch x {
223
- 0 { ... }
224
- 1 { ... }
222
+ switch {
223
+ case x == 0 { ... }
224
+ case x == 1 { ... }
225
225
  else { ... }
226
226
  }
227
227
  for i of 0 .. 10 { ... } // exclusive range
@@ -280,6 +280,15 @@ const typed = Array<int>(1, 2, 3)
280
280
  for n of nums { Console.write("\{n}\n") }
281
281
  ```
282
282
 
283
+ ### Compile-time embedding
284
+
285
+ ```nomen
286
+ const corpus = #embed_file("bench/full-markdown.md") // string literal of the
287
+ // file's contents; path
288
+ // resolves from the
289
+ // package root
290
+ ```
291
+
283
292
  ## Reference
284
293
 
285
294
  - Full language spec: [SPEC.md](https://github.com/andrewjk/nomen/blob/main/SPEC.md)
@@ -0,0 +1,50 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ // Atomic: worker threads from the pool malloc/free concurrently, and a
6
+ // plain `long` would lose updates under that contention (showing up as
7
+ // spurious LEAK/negative-count failures in tests that use spawns).
8
+ static volatile long nomen_malloc_count = 0;
9
+
10
+ void *nomen_malloc_wrap(unsigned long size) {
11
+ void *ptr = malloc(size);
12
+ __atomic_add_fetch(&nomen_malloc_count, 1, __ATOMIC_SEQ_CST);
13
+ return ptr;
14
+ }
15
+
16
+ void *nomen_calloc_wrap(unsigned long count, unsigned long size) {
17
+ void *ptr = calloc(count, size);
18
+ __atomic_add_fetch(&nomen_malloc_count, 1, __ATOMIC_SEQ_CST);
19
+ return ptr;
20
+ }
21
+
22
+ void *nomen_realloc_wrap(void *old_ptr, unsigned long size) {
23
+ if (!old_ptr) {
24
+ __atomic_add_fetch(&nomen_malloc_count, 1, __ATOMIC_SEQ_CST);
25
+ }
26
+ void *ptr = realloc(old_ptr, size);
27
+ return ptr;
28
+ }
29
+
30
+ void nomen_free_wrap(void *ptr) {
31
+ if (ptr) {
32
+ free(ptr);
33
+ __atomic_sub_fetch(&nomen_malloc_count, 1, __ATOMIC_SEQ_CST);
34
+ }
35
+ }
36
+
37
+ void *nomen_strdup_wrap(const char *s) {
38
+ unsigned long len = strlen(s) + 1;
39
+ void *ptr = malloc(len);
40
+ if (ptr) memcpy(ptr, s, len);
41
+ __atomic_add_fetch(&nomen_malloc_count, 1, __ATOMIC_SEQ_CST);
42
+ return ptr;
43
+ }
44
+
45
+ void nomen_audit_check(void) {
46
+ long count = __atomic_load_n(&nomen_malloc_count, __ATOMIC_SEQ_CST);
47
+ if (count != 0) {
48
+ printf("LEAK: %ld allocation(s)\n", count);
49
+ }
50
+ }
@@ -510,6 +510,17 @@ pub struct Buffer<T> {
510
510
  ```
511
511
  }
512
512
 
513
+ // Move-taking write, mirroring `List.set`: the caller's value is
514
+ // consumed and an independent copy is installed in the slot (replace
515
+ // deep-copies owning elements). The owning entry point a caller uses
516
+ // when it wants to hand over a value — `replace`'s by-value parameter
517
+ // cannot accept the `move` keyword, so a borrow being transferred
518
+ // (e.g. a loaded element) must go through here rather than be bound to
519
+ // a freed local.
520
+ pub func set = (ref self, int i: i >= 0 && i < self.cap, move T value) {
521
+ self.replace(i, value)
522
+ }
523
+
513
524
  // Move slot src into slot dst: overwrite dst with src's bytes and zero
514
525
  // src, so exactly ONE slot owns the value afterwards. The
515
526
  // ownership-transferring primitive behind backward-shift deletion
@@ -620,6 +631,33 @@ pub struct Buffer<T> {
620
631
  memset(self.data, 0, len * T_SIZE)
621
632
  }
622
633
 
634
+ // An independent copy: fresh slab, per-element deep copies. Each slot
635
+ // round-trips load→replace through a local, so owning element types get
636
+ // the same treatment a List<T>.copy slot does (the load materializes an
637
+ // owned copy, replace gives the destination its own). Class elements
638
+ // never reach this body (a `Buffer<T>` with T a class monomorphizes to
639
+ // `ClassBuffer<T>`, which has no copy).
640
+ pub func copy = (self, out Buffer<T>: out.cap == self.cap) {
641
+ var dst = Buffer<T>()
642
+ if self.cap > 0 {
643
+ dst.alloc(self.cap)
644
+ var i = 0
645
+ while i < self.cap {
646
+ // Bind the loaded element and hand it to `set` (move): for a
647
+ // string element load returns a BORROW of the source slot, and
648
+ // the move transfers it into the write without a scope-exit
649
+ // reclaim (which would free the source's buffer); for an owning
650
+ // struct element load returns an owned copy that transfers the
651
+ // same way. Mirrors List.copy's `var T v = self.at(i)` +
652
+ // `dst.push(v)`.
653
+ var T v = self.load(i)
654
+ dst.set(i, v)
655
+ i += 1
656
+ }
657
+ }
658
+ return dst
659
+ }
660
+
623
661
  internal inline func store_or_int = (ref self, int i: i >= 0 && i < self.cap, int val) {
624
662
  ```
625
663
  #arch: c
@@ -241,7 +241,10 @@ pub struct StringBuilder {
241
241
  }
242
242
 
243
243
  // Finalize: null-terminate, return the byte buffer as a string, and
244
- // release ownership (sets `data` to 0 so the destructor won't free it).
244
+ // release ownership (sets `data` to 0 so the destructor won't free it,
245
+ // and resets `len`/`cap` so the builder is a valid empty builder again —
246
+ // a stale `cap` would let a later append skip the grow and memcpy to a
247
+ // null buffer). Reuse after `to_string` yields a fresh builder.
245
248
  // Explicitly `pub`: struct members default to pub, but this is the
246
249
  // builder's primary read-back — the contract should not depend on the
247
250
  // default.
@@ -260,6 +263,8 @@ pub struct StringBuilder {
260
263
  ((unsigned char*)(unsigned long long)self->data)[idx] = 0;
261
264
  unsigned long long result = self->data;
262
265
  self->data = 0;
266
+ self->len = 0;
267
+ self->cap = 0;
263
268
  return (nomen_string){ (char*)result, (long)idx };
264
269
  ```
265
270
  ```
@@ -290,6 +295,10 @@ pub struct StringBuilder {
290
295
  strb wzr, [x0, x1] // data[len] = 0
291
296
  // transfer ownership: clear self->data. x0 retains the old ptr.
292
297
  str xzr, [x19, #8]
298
+ // reset the stale bookkeeping so reuse yields a valid empty builder
299
+ // (a stale cap would skip the append's grow against the null buffer)
300
+ str xzr, [x19, #16]
301
+ str xzr, [x19, #24]
293
302
  // Fat-string ABI: (x0 = data, x1 = len) is already the return pair.
294
303
  ```
295
304
  }