@pilates/core 1.0.1 → 2.0.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.
Files changed (77) hide show
  1. package/dist/algorithm/cache.d.ts +7 -19
  2. package/dist/algorithm/cache.d.ts.map +1 -1
  3. package/dist/algorithm/cache.js +31 -27
  4. package/dist/algorithm/cache.js.map +1 -1
  5. package/dist/algorithm/index.d.ts +31 -0
  6. package/dist/algorithm/index.d.ts.map +1 -1
  7. package/dist/algorithm/index.js +105 -13
  8. package/dist/algorithm/index.js.map +1 -1
  9. package/dist/algorithm/round.d.ts +13 -0
  10. package/dist/algorithm/round.d.ts.map +1 -1
  11. package/dist/algorithm/round.js +33 -16
  12. package/dist/algorithm/round.js.map +1 -1
  13. package/dist/algorithm/spineless/classify.d.ts +47 -0
  14. package/dist/algorithm/spineless/classify.d.ts.map +1 -0
  15. package/dist/algorithm/spineless/classify.js +109 -0
  16. package/dist/algorithm/spineless/classify.js.map +1 -0
  17. package/dist/algorithm/spineless/field-id-pool.d.ts +28 -0
  18. package/dist/algorithm/spineless/field-id-pool.d.ts.map +1 -0
  19. package/dist/algorithm/spineless/field-id-pool.js +35 -0
  20. package/dist/algorithm/spineless/field-id-pool.js.map +1 -0
  21. package/dist/algorithm/spineless/flex-grammar.d.ts +394 -0
  22. package/dist/algorithm/spineless/flex-grammar.d.ts.map +1 -0
  23. package/dist/algorithm/spineless/flex-grammar.js +2509 -0
  24. package/dist/algorithm/spineless/flex-grammar.js.map +1 -0
  25. package/dist/algorithm/spineless/grammar.d.ts +156 -0
  26. package/dist/algorithm/spineless/grammar.d.ts.map +1 -0
  27. package/dist/algorithm/spineless/grammar.js +145 -0
  28. package/dist/algorithm/spineless/grammar.js.map +1 -0
  29. package/dist/algorithm/spineless/layout.d.ts +167 -0
  30. package/dist/algorithm/spineless/layout.d.ts.map +1 -0
  31. package/dist/algorithm/spineless/layout.js +893 -0
  32. package/dist/algorithm/spineless/layout.js.map +1 -0
  33. package/dist/algorithm/spineless/order-maintenance.bench.d.ts +25 -0
  34. package/dist/algorithm/spineless/order-maintenance.bench.d.ts.map +1 -0
  35. package/dist/algorithm/spineless/order-maintenance.bench.js +78 -0
  36. package/dist/algorithm/spineless/order-maintenance.bench.js.map +1 -0
  37. package/dist/algorithm/spineless/order-maintenance.d.ts +201 -0
  38. package/dist/algorithm/spineless/order-maintenance.d.ts.map +1 -0
  39. package/dist/algorithm/spineless/order-maintenance.js +300 -0
  40. package/dist/algorithm/spineless/order-maintenance.js.map +1 -0
  41. package/dist/algorithm/spineless/priority-queue.bench.d.ts +17 -0
  42. package/dist/algorithm/spineless/priority-queue.bench.d.ts.map +1 -0
  43. package/dist/algorithm/spineless/priority-queue.bench.js +57 -0
  44. package/dist/algorithm/spineless/priority-queue.bench.js.map +1 -0
  45. package/dist/algorithm/spineless/priority-queue.d.ts +73 -0
  46. package/dist/algorithm/spineless/priority-queue.d.ts.map +1 -0
  47. package/dist/algorithm/spineless/priority-queue.js +149 -0
  48. package/dist/algorithm/spineless/priority-queue.js.map +1 -0
  49. package/dist/algorithm/spineless/runtime.d.ts +292 -0
  50. package/dist/algorithm/spineless/runtime.d.ts.map +1 -0
  51. package/dist/algorithm/spineless/runtime.js +609 -0
  52. package/dist/algorithm/spineless/runtime.js.map +1 -0
  53. package/dist/algorithm/spineless/style-dirty.d.ts +65 -0
  54. package/dist/algorithm/spineless/style-dirty.d.ts.map +1 -0
  55. package/dist/algorithm/spineless/style-dirty.js +75 -0
  56. package/dist/algorithm/spineless/style-dirty.js.map +1 -0
  57. package/dist/dirty-flags.d.ts +30 -0
  58. package/dist/dirty-flags.d.ts.map +1 -0
  59. package/dist/dirty-flags.js +35 -0
  60. package/dist/dirty-flags.js.map +1 -0
  61. package/dist/index.d.ts +4 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +9 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/inspect.d.ts +27 -0
  66. package/dist/inspect.d.ts.map +1 -0
  67. package/dist/inspect.js +61 -0
  68. package/dist/inspect.js.map +1 -0
  69. package/dist/layout-pool.d.ts +49 -0
  70. package/dist/layout-pool.d.ts.map +1 -0
  71. package/dist/layout-pool.js +75 -0
  72. package/dist/layout-pool.js.map +1 -0
  73. package/dist/node.d.ts +20 -3
  74. package/dist/node.d.ts.map +1 -1
  75. package/dist/node.js +63 -42
  76. package/dist/node.js.map +1 -1
  77. package/package.json +1 -1
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Order Maintenance (OM) data structure.
3
+ *
4
+ * Maintains a totally-ordered set of items under insertions, deletions,
5
+ * and `compare(a, b)` queries that return the relative order in O(1) (or
6
+ * O(1) amortized). Foundational primitive for Spineless Traversal
7
+ * (Kirisame, Wang, Panchekha — PLDI 2025): the priority queue that
8
+ * drives incremental layout invalidation is keyed on OM timestamps,
9
+ * so a fast OM comparator dominates per-operation cost.
10
+ *
11
+ * Reference: Bender, Cole, Demaine, Farach-Colton, Zito. "Two
12
+ * simplified algorithms for maintaining order in a list." ESA 2002.
13
+ *
14
+ * ## What this file ships
15
+ *
16
+ * **The interface** — `OMNode`, `OrderMaintenance` — is the surface the
17
+ * Spineless runtime will consume. We design it so the implementation
18
+ * can be swapped (naive ↔ Bender amortized O(1)) without ripple.
19
+ *
20
+ * **The naive implementation** — `NaiveOrderMaintenance` — uses a single
21
+ * doubly-linked list with sequential integer tags assigned on insert.
22
+ * Inserts trigger O(N) renumbering of trailing nodes. Compare is O(1).
23
+ *
24
+ * This is the **scaffolding implementation**: correct, simple, lets us
25
+ * write all the consumer code (priority queue, runtime, attribute grammar
26
+ * interpreter) without waiting for the optimized impl. The Bender et al.
27
+ * amortized-O(1) implementation lands as a drop-in replacement once the
28
+ * Spineless runtime is wired and we can benchmark end-to-end. The naive
29
+ * impl stays in tree forever as a reference oracle: every Bender op is
30
+ * differentially compared against naive in the property-based test.
31
+ *
32
+ * ## Why JS and not WASM
33
+ *
34
+ * The paper's reference (Megatron) emits C++ and uses inline `cmov` for
35
+ * branchless compare. We can't use inline assembly in JS, but we don't
36
+ * have to: V8 already lowers `a < b` on 32-bit-integer hidden classes
37
+ * to a branchless `cmp` + `setb` sequence on x86-64. The TS-side cost is
38
+ * predominantly in the `lookup` (Map.get) and the unboxed compare itself.
39
+ *
40
+ * @internal
41
+ */
42
+ /**
43
+ * Naive O(N)-per-insert Order Maintenance. Correctness-only impl
44
+ * for scaffolding and as a fuzzer oracle for the future Bender impl.
45
+ *
46
+ * Invariants:
47
+ * - `_omTag` is strictly increasing along the `next` chain.
48
+ * - `_omTag` values are arbitrary integers but always orderable.
49
+ * - Insert renumbers all trailing nodes to maintain monotonicity.
50
+ *
51
+ * @internal
52
+ */
53
+ export class NaiveOrderMaintenance {
54
+ firstNode = null;
55
+ nodeCount = 0;
56
+ get size() {
57
+ return this.nodeCount;
58
+ }
59
+ /**
60
+ * Returns the first node in the order, or `null` if empty. Exposed
61
+ * for tests and for the priority queue's extract-min operation.
62
+ *
63
+ * @internal
64
+ */
65
+ first() {
66
+ return this.firstNode;
67
+ }
68
+ init() {
69
+ const first = { _omTag: 0, prev: null, next: null };
70
+ this.firstNode = first;
71
+ this.nodeCount = 1;
72
+ return first;
73
+ }
74
+ insertAfter(after) {
75
+ const afterNode = after;
76
+ const newNode = {
77
+ _omTag: afterNode._omTag + 1,
78
+ prev: afterNode,
79
+ next: afterNode.next,
80
+ };
81
+ if (afterNode.next !== null) {
82
+ afterNode.next.prev = newNode;
83
+ }
84
+ afterNode.next = newNode;
85
+ // Renumber trailing nodes to maintain strict monotonicity.
86
+ // O(N) worst case; this is the scaffolding-only cost the Bender
87
+ // impl removes.
88
+ let cursor = newNode.next;
89
+ let nextTag = newNode._omTag + 1;
90
+ while (cursor !== null) {
91
+ cursor._omTag = nextTag;
92
+ nextTag++;
93
+ cursor = cursor.next;
94
+ }
95
+ this.nodeCount++;
96
+ return newNode;
97
+ }
98
+ delete(node) {
99
+ const n = node;
100
+ if (n.prev !== null) {
101
+ n.prev.next = n.next;
102
+ }
103
+ else {
104
+ this.firstNode = n.next;
105
+ }
106
+ if (n.next !== null) {
107
+ n.next.prev = n.prev;
108
+ }
109
+ // Renumbering is not strictly required after delete (gaps in tags
110
+ // are harmless), but consistency with insertAfter's invariant
111
+ // (consecutive tags) simplifies reasoning. Skipped for now to
112
+ // avoid an extra O(N) walk; tests should not rely on consecutive
113
+ // tags after deletes.
114
+ this.nodeCount--;
115
+ }
116
+ compare(a, b) {
117
+ const ta = a._omTag;
118
+ const tb = b._omTag;
119
+ return ta - tb;
120
+ }
121
+ predecessor(node) {
122
+ return node.prev;
123
+ }
124
+ }
125
+ // --- Bender et al. 2002 Algorithm 1 (list-labeling with windowed relabel) ---
126
+ /**
127
+ * Label space. Labels live in `[0, LABEL_MAX)`. Using 2^30 keeps every
128
+ * arithmetic op (midpoint, double, mask) in V8's 31-bit SMI range, so
129
+ * the JIT lowers everything to native int instructions. At 2^30 we can
130
+ * host ~50M items before any global rebalance is forced — far above
131
+ * typical TUI scale.
132
+ *
133
+ * @internal
134
+ */
135
+ const LABEL_MAX = 1 << 30;
136
+ /**
137
+ * Bender, Cole, Demaine, Farach-Colton, Zito (2002): "Two simplified
138
+ * algorithms for maintaining order in a list." Algorithm 1 — list-
139
+ * labeling with exponentially-growing window relabel.
140
+ *
141
+ * Operations:
142
+ * - `compare`: O(1) integer subtract.
143
+ * - `insertAfter`: amortized O(log N) per operation (looser than the
144
+ * paper's O(1) amortized when using density bound (3/2)^d at depth d;
145
+ * we trade a log factor for simpler integer arithmetic and avoid
146
+ * BigInt).
147
+ * - `delete`: O(1).
148
+ *
149
+ * Cross-validated against `NaiveOrderMaintenance` via property fuzzer.
150
+ *
151
+ * @internal
152
+ */
153
+ export class BenderOrderMaintenance {
154
+ firstNode = null;
155
+ nodeCount = 0;
156
+ get size() {
157
+ return this.nodeCount;
158
+ }
159
+ first() {
160
+ return this.firstNode;
161
+ }
162
+ init() {
163
+ // Start label at the middle of the space so first inserts have room
164
+ // both before (via the global rebalance path) and after.
165
+ const first = { _omTag: LABEL_MAX >> 1, prev: null, next: null };
166
+ this.firstNode = first;
167
+ this.nodeCount = 1;
168
+ return first;
169
+ }
170
+ insertAfter(after) {
171
+ const pred = after;
172
+ const succ = pred.next;
173
+ const succLabel = succ === null ? LABEL_MAX : succ._omTag;
174
+ const predLabel = pred._omTag;
175
+ // Midpoint between predecessor and successor labels. Integer-only.
176
+ const newLabel = (predLabel + succLabel) >> 1;
177
+ const newNode = { _omTag: newLabel, prev: pred, next: succ };
178
+ pred.next = newNode;
179
+ if (succ !== null)
180
+ succ.prev = newNode;
181
+ this.nodeCount++;
182
+ if (newLabel === predLabel) {
183
+ // No room between pred and succ — trigger a windowed relabel.
184
+ // Relabel updates newNode._omTag (and others in the window) to
185
+ // spread out across available label space.
186
+ this.relabel(newNode);
187
+ }
188
+ return newNode;
189
+ }
190
+ delete(node) {
191
+ const n = node;
192
+ if (n.prev !== null) {
193
+ n.prev.next = n.next;
194
+ }
195
+ else {
196
+ this.firstNode = n.next;
197
+ }
198
+ if (n.next !== null) {
199
+ n.next.prev = n.prev;
200
+ }
201
+ this.nodeCount--;
202
+ // Delete only creates extra label room; no rebalance needed.
203
+ }
204
+ compare(a, b) {
205
+ return a._omTag - b._omTag;
206
+ }
207
+ predecessor(node) {
208
+ return node.prev;
209
+ }
210
+ /**
211
+ * Walk exponentially-growing windows around `pivot` until a window
212
+ * with low enough density to redistribute is found. Redistribute
213
+ * labels uniformly across that window.
214
+ *
215
+ * Density bound: `count * 2 ≤ span`. This guarantees:
216
+ * - Every node gets a distinct integer label (count ≤ span).
217
+ * - Each interval between consecutive labels has at least 2 units
218
+ * of room, so subsequent midpoint inserts succeed without
219
+ * triggering relabel again at the same depth.
220
+ *
221
+ * Window definition at depth d:
222
+ * span = 2^d
223
+ * tagLow = pivot._omTag aligned down to multiple of span
224
+ * tagHigh = tagLow + span
225
+ *
226
+ * Amortized cost: O(log N) per insert. (Tighter than the paper's
227
+ * O(1) amortized with density bound (3/2)^d, but the bound here uses
228
+ * pure integer arithmetic for V8-friendly speed.)
229
+ *
230
+ * @internal
231
+ */
232
+ relabel(pivot) {
233
+ let depth = 1;
234
+ let span = 2;
235
+ while (true) {
236
+ // Find aligned window boundaries around the pivot's current label.
237
+ const mask = (LABEL_MAX - 1) ^ (span - 1);
238
+ const tagLow = pivot._omTag & mask;
239
+ const tagHigh = tagLow + span;
240
+ // Find leftmost node in the window by walking back from pivot.
241
+ let firstInWindow = pivot;
242
+ while (firstInWindow.prev !== null && firstInWindow.prev._omTag >= tagLow) {
243
+ firstInWindow = firstInWindow.prev;
244
+ }
245
+ // Count nodes in the window and collect them in-order.
246
+ const inWindow = [];
247
+ let cursor = firstInWindow;
248
+ while (cursor !== null && cursor._omTag < tagHigh) {
249
+ inWindow.push(cursor);
250
+ cursor = cursor.next;
251
+ }
252
+ const count = inWindow.length;
253
+ // Density bound: redistribute only when there's at least 2x
254
+ // headroom in the window. This guarantees distinct labels +
255
+ // future-insert room without immediate re-relabel.
256
+ if (count * 2 <= span) {
257
+ const step = Math.max(1, (span / count) | 0);
258
+ // Center the assigned range: leave equal padding at both ends.
259
+ const used = (count - 1) * step + 1;
260
+ const startPad = Math.max(0, (span - used) >> 1);
261
+ let label = tagLow + startPad;
262
+ for (const node of inWindow) {
263
+ node._omTag = label;
264
+ label += step;
265
+ }
266
+ return;
267
+ }
268
+ // Window overcrowded — expand. Doubling depth doubles span.
269
+ // If span exceeds the label space, fall back to a global relabel.
270
+ depth++;
271
+ span <<= 1;
272
+ if (span >= LABEL_MAX) {
273
+ this.globalRelabel();
274
+ return;
275
+ }
276
+ }
277
+ }
278
+ /**
279
+ * Fallback when the windowed relabel walks all the way up to the
280
+ * full label space without finding a sparse-enough window. Spreads
281
+ * every node uniformly across [0, LABEL_MAX).
282
+ *
283
+ * @internal
284
+ */
285
+ globalRelabel() {
286
+ const all = [];
287
+ let cursor = this.firstNode;
288
+ while (cursor !== null) {
289
+ all.push(cursor);
290
+ cursor = cursor.next;
291
+ }
292
+ const stride = Math.max(1, (LABEL_MAX / (all.length + 1)) | 0);
293
+ let label = stride;
294
+ for (const node of all) {
295
+ node._omTag = label;
296
+ label += stride;
297
+ }
298
+ }
299
+ }
300
+ //# sourceMappingURL=order-maintenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order-maintenance.js","sourceRoot":"","sources":["../../../src/algorithm/spineless/order-maintenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Microbenchmark for the OM-keyed priority queue.
3
+ *
4
+ * Targets (Phase 5 viability):
5
+ * - `push`: < 2µs/op at N=10k (called once per dirty field per layout)
6
+ * - `popMin`: < 2µs/op at N=10k (called once per recompute step)
7
+ *
8
+ * Each layout pass under Spineless may process up to ~5k field-recomputes
9
+ * on a 1k-node TUI tree. Total PQ overhead must stay well under the
10
+ * 50-100µs target for incremental layout to beat imperative.
11
+ *
12
+ * Run with: `tsx packages/core/src/algorithm/spineless/priority-queue.bench.ts`
13
+ *
14
+ * @internal
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=priority-queue.bench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-queue.bench.d.ts","sourceRoot":"","sources":["../../../src/algorithm/spineless/priority-queue.bench.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Microbenchmark for the OM-keyed priority queue.
3
+ *
4
+ * Targets (Phase 5 viability):
5
+ * - `push`: < 2µs/op at N=10k (called once per dirty field per layout)
6
+ * - `popMin`: < 2µs/op at N=10k (called once per recompute step)
7
+ *
8
+ * Each layout pass under Spineless may process up to ~5k field-recomputes
9
+ * on a 1k-node TUI tree. Total PQ overhead must stay well under the
10
+ * 50-100µs target for incremental layout to beat imperative.
11
+ *
12
+ * Run with: `tsx packages/core/src/algorithm/spineless/priority-queue.bench.ts`
13
+ *
14
+ * @internal
15
+ */
16
+ import { BenderOrderMaintenance } from './order-maintenance.js';
17
+ import { OmPriorityQueue } from './priority-queue.js';
18
+ function median(xs) {
19
+ const sorted = [...xs].sort((a, b) => a - b);
20
+ return sorted[Math.floor(sorted.length / 2)];
21
+ }
22
+ function bench(label, sizes, opsPerTrial, trials) {
23
+ console.log(`\n## ${label}`);
24
+ for (const N of sizes) {
25
+ const trialMsPush = [];
26
+ const trialMsPop = [];
27
+ for (let t = 0; t < trials; t++) {
28
+ const om = new BenderOrderMaintenance();
29
+ const nodes = [om.init()];
30
+ for (let i = 1; i < N; i++)
31
+ nodes.push(om.insertAfter(nodes[i - 1]));
32
+ const pq = new OmPriorityQueue(om);
33
+ // Push phase
34
+ let s = performance.now();
35
+ for (let k = 0; k < opsPerTrial; k++) {
36
+ // Use a deterministic but spread-out order so the heap actually re-orders.
37
+ const i = (k * 2654435761) % N;
38
+ pq.push(k, nodes[i]);
39
+ }
40
+ let e = performance.now();
41
+ trialMsPush.push(e - s);
42
+ // Pop phase (extract everything)
43
+ s = performance.now();
44
+ while (!pq.isEmpty())
45
+ pq.popMin();
46
+ e = performance.now();
47
+ trialMsPop.push(e - s);
48
+ }
49
+ const usPush = (median(trialMsPush) * 1000) / opsPerTrial;
50
+ const usPop = (median(trialMsPop) * 1000) / opsPerTrial;
51
+ console.log(` N=${N.toString().padStart(6)} push=${usPush.toFixed(3).padStart(7)} µs popMin=${usPop.toFixed(3).padStart(7)} µs`);
52
+ }
53
+ }
54
+ console.log('OmPriorityQueue microbench (Bender OM, single-threaded JS)');
55
+ console.log('Targets: push < 2µs, popMin < 2µs at N=10k');
56
+ bench('push + popMin', [100, 1000, 10000], 10_000, 5);
57
+ //# sourceMappingURL=priority-queue.bench.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-queue.bench.js","sourceRoot":"","sources":["../../../src/algorithm/spineless/priority-queue.bench.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Order-Maintenance-keyed priority queue.
3
+ *
4
+ * The hot data structure of the Spineless Traversal runtime (Kirisame,
5
+ * Wang, Panchekha — PLDI 2025). Each item is keyed by an {@link OMNode}
6
+ * representing its position in the layout-field traversal order; the
7
+ * queue extracts items in OM-order, so the runtime always processes
8
+ * the earliest-dirty field next.
9
+ *
10
+ * Implementation: binary min-heap over `{ value, omNode }` records.
11
+ * Ordering uses `om.compare(a.omNode, b.omNode)`. Standard O(log N)
12
+ * push/popMin, O(1) peek/size.
13
+ *
14
+ * Membership tracking: an internal `Set` allows O(1) `has(value)`
15
+ * queries so the Spineless runtime can avoid enqueueing the same
16
+ * field twice. Important: this assumes `value` instances are stable
17
+ * (used as Map keys via reference equality), which fits the Spineless
18
+ * "one OMNode per (Node, field-name) pair, allocated once" model.
19
+ *
20
+ * ## Correctness under OM relabel
21
+ *
22
+ * The OM data structure may relabel internal tags on insert
23
+ * (`BenderOrderMaintenance`'s windowed redistribute). The heap
24
+ * invariant is "parent ≤ all descendants by OM compare". A relabel
25
+ * preserves the RELATIVE order of all live OM nodes, so
26
+ * `sign(compare(a, b))` is unchanged — the heap invariant holds.
27
+ *
28
+ * @internal
29
+ */
30
+ import type { OMNode, OrderMaintenance } from './order-maintenance.js';
31
+ /**
32
+ * @internal
33
+ */
34
+ export declare class OmPriorityQueue<T> {
35
+ private readonly om;
36
+ private readonly heapValue;
37
+ private readonly heapOmNode;
38
+ private readonly members;
39
+ constructor(om: OrderMaintenance);
40
+ get size(): number;
41
+ isEmpty(): boolean;
42
+ has(value: T): boolean;
43
+ /**
44
+ * Push a value at the given OM position. Caller is responsible for
45
+ * checking `has(value)` first if dedup matters (some workflows
46
+ * intentionally re-enqueue after deletion).
47
+ *
48
+ * Returns `true` if added, `false` if `value` was already present
49
+ * (no-op — the queue is unchanged, original OM position retained).
50
+ */
51
+ push(value: T, omNode: OMNode): boolean;
52
+ /**
53
+ * Return (without removing) the value at OM-minimum. Returns
54
+ * `undefined` if the queue is empty.
55
+ */
56
+ peek(): T | undefined;
57
+ /**
58
+ * Remove and return the OM-minimum value. Returns `undefined` if
59
+ * the queue is empty.
60
+ */
61
+ popMin(): T | undefined;
62
+ /**
63
+ * Sift the element at index `start` up the heap until heap property
64
+ * is restored. O(log N).
65
+ */
66
+ private siftUp;
67
+ /**
68
+ * Sift the element at index `start` down the heap until heap property
69
+ * is restored. O(log N).
70
+ */
71
+ private siftDown;
72
+ }
73
+ //# sourceMappingURL=priority-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-queue.d.ts","sourceRoot":"","sources":["../../../src/algorithm/spineless/priority-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAEvE;;GAEG;AACH,qBAAa,eAAe,CAAC,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAmB;IAMtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,EAAE,EAAE,gBAAgB;IAIhC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,IAAI,OAAO;IAIlB,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO;IAItB;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IASvC;;;OAGG;IACH,IAAI,IAAI,CAAC,GAAG,SAAS;IAIrB;;;OAGG;IACH,MAAM,IAAI,CAAC,GAAG,SAAS;IAgBvB;;;OAGG;IACH,OAAO,CAAC,MAAM;IAgBd;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAsBjB"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Order-Maintenance-keyed priority queue.
3
+ *
4
+ * The hot data structure of the Spineless Traversal runtime (Kirisame,
5
+ * Wang, Panchekha — PLDI 2025). Each item is keyed by an {@link OMNode}
6
+ * representing its position in the layout-field traversal order; the
7
+ * queue extracts items in OM-order, so the runtime always processes
8
+ * the earliest-dirty field next.
9
+ *
10
+ * Implementation: binary min-heap over `{ value, omNode }` records.
11
+ * Ordering uses `om.compare(a.omNode, b.omNode)`. Standard O(log N)
12
+ * push/popMin, O(1) peek/size.
13
+ *
14
+ * Membership tracking: an internal `Set` allows O(1) `has(value)`
15
+ * queries so the Spineless runtime can avoid enqueueing the same
16
+ * field twice. Important: this assumes `value` instances are stable
17
+ * (used as Map keys via reference equality), which fits the Spineless
18
+ * "one OMNode per (Node, field-name) pair, allocated once" model.
19
+ *
20
+ * ## Correctness under OM relabel
21
+ *
22
+ * The OM data structure may relabel internal tags on insert
23
+ * (`BenderOrderMaintenance`'s windowed redistribute). The heap
24
+ * invariant is "parent ≤ all descendants by OM compare". A relabel
25
+ * preserves the RELATIVE order of all live OM nodes, so
26
+ * `sign(compare(a, b))` is unchanged — the heap invariant holds.
27
+ *
28
+ * @internal
29
+ */
30
+ /**
31
+ * @internal
32
+ */
33
+ export class OmPriorityQueue {
34
+ om;
35
+ // Parallel arrays for the heap. heapValue[i] is the user-supplied
36
+ // value; heapOmNode[i] is its OM position. Using parallel arrays
37
+ // rather than {value, omNode} pair objects avoids per-push
38
+ // allocation, which matters at Spineless-runtime scale (10k+
39
+ // pushes per layout pass at the largest TUI tree size).
40
+ heapValue = [];
41
+ heapOmNode = [];
42
+ // Membership set keyed by reference. Allows O(1) `has` checks.
43
+ members = new Set();
44
+ constructor(om) {
45
+ this.om = om;
46
+ }
47
+ get size() {
48
+ return this.heapValue.length;
49
+ }
50
+ isEmpty() {
51
+ return this.heapValue.length === 0;
52
+ }
53
+ has(value) {
54
+ return this.members.has(value);
55
+ }
56
+ /**
57
+ * Push a value at the given OM position. Caller is responsible for
58
+ * checking `has(value)` first if dedup matters (some workflows
59
+ * intentionally re-enqueue after deletion).
60
+ *
61
+ * Returns `true` if added, `false` if `value` was already present
62
+ * (no-op — the queue is unchanged, original OM position retained).
63
+ */
64
+ push(value, omNode) {
65
+ if (this.members.has(value))
66
+ return false;
67
+ this.heapValue.push(value);
68
+ this.heapOmNode.push(omNode);
69
+ this.members.add(value);
70
+ this.siftUp(this.heapValue.length - 1);
71
+ return true;
72
+ }
73
+ /**
74
+ * Return (without removing) the value at OM-minimum. Returns
75
+ * `undefined` if the queue is empty.
76
+ */
77
+ peek() {
78
+ return this.heapValue[0];
79
+ }
80
+ /**
81
+ * Remove and return the OM-minimum value. Returns `undefined` if
82
+ * the queue is empty.
83
+ */
84
+ popMin() {
85
+ const n = this.heapValue.length;
86
+ if (n === 0)
87
+ return undefined;
88
+ const top = this.heapValue[0];
89
+ const last = n - 1;
90
+ if (last > 0) {
91
+ this.heapValue[0] = this.heapValue[last];
92
+ this.heapOmNode[0] = this.heapOmNode[last];
93
+ }
94
+ this.heapValue.length = last;
95
+ this.heapOmNode.length = last;
96
+ this.members.delete(top);
97
+ if (last > 0)
98
+ this.siftDown(0);
99
+ return top;
100
+ }
101
+ /**
102
+ * Sift the element at index `start` up the heap until heap property
103
+ * is restored. O(log N).
104
+ */
105
+ siftUp(start) {
106
+ let i = start;
107
+ const value = this.heapValue[i];
108
+ const omNode = this.heapOmNode[i];
109
+ while (i > 0) {
110
+ const parent = (i - 1) >> 1;
111
+ const parentOm = this.heapOmNode[parent];
112
+ if (this.om.compare(omNode, parentOm) >= 0)
113
+ break;
114
+ this.heapValue[i] = this.heapValue[parent];
115
+ this.heapOmNode[i] = parentOm;
116
+ i = parent;
117
+ }
118
+ this.heapValue[i] = value;
119
+ this.heapOmNode[i] = omNode;
120
+ }
121
+ /**
122
+ * Sift the element at index `start` down the heap until heap property
123
+ * is restored. O(log N).
124
+ */
125
+ siftDown(start) {
126
+ let i = start;
127
+ const n = this.heapValue.length;
128
+ const value = this.heapValue[i];
129
+ const omNode = this.heapOmNode[i];
130
+ const halfN = n >> 1;
131
+ while (i < halfN) {
132
+ let bestChild = (i << 1) | 1; // 2i + 1, left child
133
+ const right = bestChild + 1;
134
+ if (right < n) {
135
+ if (this.om.compare(this.heapOmNode[right], this.heapOmNode[bestChild]) < 0) {
136
+ bestChild = right;
137
+ }
138
+ }
139
+ if (this.om.compare(this.heapOmNode[bestChild], omNode) >= 0)
140
+ break;
141
+ this.heapValue[i] = this.heapValue[bestChild];
142
+ this.heapOmNode[i] = this.heapOmNode[bestChild];
143
+ i = bestChild;
144
+ }
145
+ this.heapValue[i] = value;
146
+ this.heapOmNode[i] = omNode;
147
+ }
148
+ }
149
+ //# sourceMappingURL=priority-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority-queue.js","sourceRoot":"","sources":["../../../src/algorithm/spineless/priority-queue.ts"],"names":[],"mappings":"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"}