nomen-lang 0.5.0 → 0.6.0

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.
@@ -21,7 +21,9 @@
21
21
  // The pool infrastructure (types, worker loop, submit, shutdown, cancel
22
22
  // thread-local) lives in build_spawn_node and is emitted as file-scope C
23
23
  // on the first spawn — not in Thread's own methods — so that Thread can be
24
- // generic without duplicating the pool per instantiation.
24
+ // generic without duplicating the pool per instantiation. The construction
25
+ // (`Thread(fn(args))`, the deferred-call special form) is compiler-emitted;
26
+ // `.start()` / `.detach()` are regular methods over the runtime seam.
25
27
  //
26
28
  // MUST-START: a Thread value that is destroyed without ever being started
27
29
  // is a programming error — #destroy reports it and aborts. start/detach
@@ -30,10 +32,23 @@
30
32
  //
31
33
  // See ASYNC.md for the design.
32
34
 
35
+ // The launch surface's return type (ASYNC.md: the dependency is
36
+ // declared by the library file, not inferred from user-source tokens).
37
+ import Task
38
+
33
39
  /**
34
40
  * A deferred function call, startable on the shared worker pool
35
41
  **/
36
- pub class Thread<T> : Sendable {
42
+ pub class Thread<T> : Sendable, Spawnable<T> {
43
+ // The construction hook (ASYNC.md): declares this class's
44
+ // construction as the deferred-call special form — the single argument
45
+ // is a call (args packed eagerly, call deferred) or a zero-arg function
46
+ // value. The compiler matches this member, never the class name; the
47
+ // construction itself is compiler-generated (pack the args, allocate the
48
+ // future machinery, build the instance), so the body is a declaration.
49
+ #spawn = () {
50
+ }
51
+
37
52
  // The packed task closure (a `struct nomen_closure *`); owned by this
38
53
  // value until start/detach/nursery.start transfers it to the runtime.
39
54
  pub var uint64 task = 0
@@ -43,6 +58,107 @@ pub class Thread<T> : Sendable {
43
58
  pub var uint64 future = 0
44
59
  // Must-start flag: set by .start() / .detach() / nursery.start.
45
60
  pub var started = false
61
+ // LEXICAL NURSERY CAPTURE (ASYNC.md): the tracking slots of the
62
+ // `async` block that lexically encloses the CONSTRUCTION, or 0 when the
63
+ // construction is outside any block. `.start()` registers the future
64
+ // through these stored pointers, so registration follows the scope that
65
+ // created the deferred call — not the one that happens to start it — and
66
+ // works through an indirect receiver. The pointers address the block's
67
+ // own futures list slots (the block cannot exit until every registered
68
+ // task has finished, so a started-before-exit task never registers into
69
+ // dead storage).
70
+ pub var uint64 nursery_futures = 0
71
+ pub var uint64 nursery_count = 0
72
+ pub var uint64 nursery_cap = 0
73
+
74
+ // Start the deferred call on the shared worker pool and yield the
75
+ // Task<T> handle. Consumes the instance's launch machinery (submit, then
76
+ // register with the construction-time nursery, if any) and zeroes the
77
+ // fields, so #destroy becomes a no-op afterwards. The future's refs
78
+ // account for the trampoline, the returned handle, and the nursery (when
79
+ // captured).
80
+ pub func start = (ref self, move out Task<T>) {
81
+ ```
82
+ #arch: c
83
+ struct nomen_future *_f = (struct nomen_future *)self->future;
84
+ _f->refs = self->nursery_futures ? 3 : 2;
85
+ __nomen_pool_submit((struct nomen_closure *)self->task);
86
+ if (self->nursery_futures) {
87
+ __nomen_nursery_track((void **)self->nursery_futures, (int *)self->nursery_count, (int *)self->nursery_cap, _f);
88
+ }
89
+ ```
90
+ ```
91
+ #arch: aarch64
92
+ // x19 = self. f = self->future (#32); nursery_futures at #48.
93
+ ldr x0, [x19, #32]
94
+ ldr x1, [x19, #48]
95
+ mov w2, #2
96
+ cbz x1, .Lnomen_start_refs
97
+ mov w2, #3
98
+ .Lnomen_start_refs:
99
+ str w2, [x0, #116]
100
+ // __nomen_pool_submit(self->task)
101
+ ldr x0, [x19, #8]
102
+ bl ___nomen_pool_submit
103
+ // if (self->nursery_futures) __nomen_nursery_track(futures, count, cap, f)
104
+ ldr x0, [x19, #48]
105
+ cbz x0, .Lnomen_start_notrack
106
+ ldr x1, [x19, #56]
107
+ ldr x2, [x19, #64]
108
+ ldr x3, [x19, #32]
109
+ bl ___nomen_nursery_track
110
+ .Lnomen_start_notrack:
111
+ ```
112
+ // The handle is a fresh heap Task built through the internal #init;
113
+ // the caller owns it (a discarded statement form is reclaimed at
114
+ // scope exit, releasing its refs share).
115
+ var t = Task<T>()
116
+ t.result_slot = self.result_slot
117
+ t.cancel_flag = self.cancel_flag
118
+ t.future = self.future
119
+ // Transfer the handles out of the instance: the runtime owns
120
+ // everything now, and #destroy must not touch (or must-start-abort).
121
+ self.task = 0
122
+ self.future = 0
123
+ self.result_slot = 0
124
+ self.cancel_flag = 0
125
+ self.started = true
126
+ return t
127
+ }
128
+
129
+ // Run the deferred call on a dedicated detached pthread — the daemon
130
+ // form. Never a pool worker, never joined; process exit kills it
131
+ // mid-execution BY DESIGN. The unused future (a Thread always carries
132
+ // the full machinery) is released — first detaching the closure from it,
133
+ // so the daemon runner owns the closure now.
134
+ pub func detach = (ref self) {
135
+ ```
136
+ #arch: c
137
+ struct nomen_future *_uf = (struct nomen_future *)self->future;
138
+ if (_uf) {
139
+ _uf->owner_args = NULL;
140
+ __nomen_future_release(_uf);
141
+ }
142
+ __nomen_task_detach((struct nomen_closure *)self->task);
143
+ ```
144
+ ```
145
+ #arch: aarch64
146
+ // if (self->future) { owner_args = NULL; release it }
147
+ ldr x0, [x19, #32]
148
+ cbz x0, .Lnomen_detach_nofut
149
+ str xzr, [x0, #136]
150
+ bl ___nomen_future_release
151
+ .Lnomen_detach_nofut:
152
+ // __nomen_task_detach(self->task)
153
+ ldr x0, [x19, #8]
154
+ bl ___nomen_task_detach
155
+ ```
156
+ self.task = 0
157
+ self.future = 0
158
+ self.result_slot = 0
159
+ self.cancel_flag = 0
160
+ self.started = true
161
+ }
46
162
 
47
163
  // Destroying an unstarted Thread is a programming error (the wrapped
48
164
  // call would silently never run) — report it and abort. A started
@@ -7,7 +7,7 @@
7
7
  * A tree of values connected by parent/child links
8
8
  **/
9
9
  pub struct Tree<T>: Enumerable {
10
- var Buffer<T> values = Buffer<T>()
10
+ var values = Buffer<T>()
11
11
  var lefts = Buffer<int>()
12
12
  var rights = Buffer<int>()
13
13
  var parents = Buffer<int>()