bireactive 0.3.1 → 0.3.2

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 (89) hide show
  1. package/README.md +14 -7
  2. package/dist/core/_counts.js +5 -12
  3. package/dist/core/cell.d.ts +3 -3
  4. package/dist/core/cell.js +6 -7
  5. package/dist/core/derived-geometry.js +4 -7
  6. package/dist/core/index.d.ts +3 -1
  7. package/dist/core/index.js +3 -1
  8. package/dist/core/lenses/aggregates.d.ts +42 -52
  9. package/dist/core/lenses/aggregates.js +225 -116
  10. package/dist/core/lenses/geometry.d.ts +22 -4
  11. package/dist/core/lenses/geometry.js +59 -27
  12. package/dist/core/lenses/index.d.ts +5 -6
  13. package/dist/core/lenses/index.js +5 -6
  14. package/dist/core/lenses/memory.js +4 -17
  15. package/dist/core/lenses/numerical.d.ts +100 -0
  16. package/dist/core/lenses/{typed-factor.js → numerical.js} +136 -34
  17. package/dist/core/lenses/point-cloud.d.ts +67 -0
  18. package/dist/core/lenses/{closed-form-policies.js → point-cloud.js} +218 -81
  19. package/dist/core/lenses/snap.d.ts +1 -1
  20. package/dist/core/lenses/snap.js +3 -10
  21. package/dist/core/lenses/text.d.ts +40 -0
  22. package/dist/core/lenses/text.js +202 -0
  23. package/dist/core/lifecycle.js +3 -6
  24. package/dist/core/linalg.js +5 -11
  25. package/dist/core/optic.js +10 -15
  26. package/dist/core/optics.js +4 -8
  27. package/dist/core/store.d.ts +1 -2
  28. package/dist/core/store.js +7 -15
  29. package/dist/core/traits.d.ts +4 -7
  30. package/dist/core/traits.js +8 -12
  31. package/dist/core/values/anchor.js +0 -4
  32. package/dist/core/values/arr.d.ts +110 -0
  33. package/dist/core/values/arr.js +336 -0
  34. package/dist/core/values/audio.d.ts +8 -9
  35. package/dist/core/values/audio.js +7 -23
  36. package/dist/core/values/bool.d.ts +11 -11
  37. package/dist/core/values/bool.js +12 -22
  38. package/dist/core/values/box.d.ts +15 -20
  39. package/dist/core/values/box.js +20 -33
  40. package/dist/core/values/canvas.d.ts +18 -25
  41. package/dist/core/values/canvas.js +17 -48
  42. package/dist/core/values/color.d.ts +5 -7
  43. package/dist/core/values/color.js +5 -11
  44. package/dist/core/values/field.d.ts +6 -7
  45. package/dist/core/values/field.js +10 -35
  46. package/dist/core/values/flags.d.ts +1 -2
  47. package/dist/core/values/flags.js +1 -17
  48. package/dist/core/values/gpu.d.ts +6 -10
  49. package/dist/core/values/gpu.js +8 -22
  50. package/dist/core/values/matrix.d.ts +2 -4
  51. package/dist/core/values/matrix.js +2 -12
  52. package/dist/core/values/num.d.ts +19 -28
  53. package/dist/core/values/num.js +23 -41
  54. package/dist/core/values/pose.d.ts +2 -4
  55. package/dist/core/values/pose.js +3 -12
  56. package/dist/core/values/range.d.ts +18 -26
  57. package/dist/core/values/range.js +22 -39
  58. package/dist/core/values/reg/ambiguity.d.ts +8 -0
  59. package/dist/core/values/reg/ambiguity.js +131 -0
  60. package/dist/core/values/reg/engine.d.ts +91 -0
  61. package/dist/core/values/reg/engine.js +373 -0
  62. package/dist/core/values/reg/nfa.d.ts +42 -0
  63. package/dist/core/values/reg/nfa.js +391 -0
  64. package/dist/core/values/reg/regex.d.ts +7 -0
  65. package/dist/core/values/reg/regex.js +318 -0
  66. package/dist/core/values/reg/types.d.ts +60 -0
  67. package/dist/core/values/reg/types.js +3 -0
  68. package/dist/core/values/reg.d.ts +250 -0
  69. package/dist/core/values/reg.js +649 -0
  70. package/dist/core/values/str.d.ts +16 -60
  71. package/dist/core/values/str.js +133 -315
  72. package/dist/core/values/template.js +1 -24
  73. package/dist/core/values/transform.d.ts +3 -5
  74. package/dist/core/values/transform.js +3 -12
  75. package/dist/core/values/tri.d.ts +9 -10
  76. package/dist/core/values/tri.js +9 -15
  77. package/dist/core/values/vec.d.ts +9 -24
  78. package/dist/core/values/vec.js +9 -64
  79. package/dist/index.d.ts +0 -11
  80. package/dist/index.js +1 -11
  81. package/package.json +6 -7
  82. package/dist/coll.d.ts +0 -74
  83. package/dist/coll.js +0 -210
  84. package/dist/core/lenses/closed-form-policies.d.ts +0 -57
  85. package/dist/core/lenses/decompositions.d.ts +0 -14
  86. package/dist/core/lenses/decompositions.js +0 -224
  87. package/dist/core/lenses/domain-aggregates.d.ts +0 -42
  88. package/dist/core/lenses/domain-aggregates.js +0 -245
  89. package/dist/core/lenses/typed-factor.d.ts +0 -40
@@ -0,0 +1,391 @@
1
+ import { CharSet } from "./engine.js";
2
+ // ── structural markers ─────────────────────────────────────────────────
3
+ const ENTER = 0;
4
+ const LEAVE = 1;
5
+ const BRANCH = 2;
6
+ const SEP_START = 3;
7
+ const SEP_END = 4;
8
+ /** Compile a grammar AST to a tagged Thompson program. */
9
+ export function compileProgram(root) {
10
+ const code = [];
11
+ const idOf = new WeakMap();
12
+ let nid = 0;
13
+ const idFor = (n) => {
14
+ let x = idOf.get(n);
15
+ if (x === undefined) {
16
+ x = nid++;
17
+ idOf.set(n, x);
18
+ }
19
+ return x;
20
+ };
21
+ const emit = (ins) => {
22
+ code.push(ins);
23
+ };
24
+ const mark = (k, id, i = -1) => emit({ op: 3, ev: { k, id, i } });
25
+ // Recognition-only compilation of an engine `Re` (no structural markers).
26
+ const re = (r) => {
27
+ switch (r.k) {
28
+ case "emp":
29
+ emit({ op: 0, set: CharSet.empty() }); // never matches → thread dies
30
+ return;
31
+ case "eps":
32
+ return;
33
+ case "chr":
34
+ emit({ op: 0, set: r.set });
35
+ return;
36
+ case "seq":
37
+ re(r.a);
38
+ re(r.b);
39
+ return;
40
+ case "alt": {
41
+ const sp = { op: 1, x: 0, y: 0 };
42
+ emit(sp);
43
+ sp.x = code.length;
44
+ re(r.a);
45
+ const j = { op: 2, x: 0 };
46
+ emit(j);
47
+ sp.y = code.length;
48
+ re(r.b);
49
+ j.x = code.length;
50
+ return;
51
+ }
52
+ case "star": {
53
+ const sp = { op: 1, x: 0, y: 0 };
54
+ const back = code.length;
55
+ emit(sp);
56
+ sp.x = code.length;
57
+ re(r.r);
58
+ emit({ op: 2, x: back });
59
+ sp.y = code.length;
60
+ return;
61
+ }
62
+ }
63
+ };
64
+ // Recognition-only compilation of a separator node (no markers — the sep's
65
+ // span is captured by SEP_START/SEP_END around it, its value is discarded).
66
+ const recog = (n) => {
67
+ switch (n.kind) {
68
+ case "lit":
69
+ for (let k = 0; k < n.text.length; k++)
70
+ emit({ op: 0, set: CharSet.char(n.text.charCodeAt(k)) });
71
+ return;
72
+ case "copy":
73
+ case "of":
74
+ re(n.engine);
75
+ return;
76
+ case "seq":
77
+ for (const p of n.parts)
78
+ recog(p);
79
+ return;
80
+ case "alt": {
81
+ const jmps = [];
82
+ for (let bi = 0; bi < n.branches.length; bi++) {
83
+ if (bi < n.branches.length - 1) {
84
+ const sp = { op: 1, x: 0, y: 0 };
85
+ emit(sp);
86
+ sp.x = code.length;
87
+ recog(n.branches[bi]);
88
+ const j = { op: 2, x: 0 };
89
+ emit(j);
90
+ jmps.push(j);
91
+ sp.y = code.length;
92
+ }
93
+ else
94
+ recog(n.branches[bi]);
95
+ }
96
+ const end = code.length;
97
+ for (const j of jmps)
98
+ j.x = end;
99
+ return;
100
+ }
101
+ case "opt": {
102
+ const sp = { op: 1, x: 0, y: 0 };
103
+ emit(sp);
104
+ sp.x = code.length;
105
+ recog(n.part);
106
+ const j = { op: 2, x: 0 };
107
+ emit(j);
108
+ sp.y = code.length;
109
+ j.x = code.length;
110
+ return;
111
+ }
112
+ case "star": {
113
+ if (n.sep === undefined) {
114
+ const sp = { op: 1, x: 0, y: 0 };
115
+ const back = code.length;
116
+ emit(sp);
117
+ sp.x = code.length;
118
+ recog(n.part);
119
+ emit({ op: 2, x: back });
120
+ sp.y = code.length;
121
+ }
122
+ else {
123
+ recog(n.part);
124
+ const sp = { op: 1, x: 0, y: 0 };
125
+ const back = code.length;
126
+ emit(sp);
127
+ sp.x = code.length;
128
+ recog(n.sep);
129
+ recog(n.part);
130
+ emit({ op: 2, x: back });
131
+ sp.y = code.length;
132
+ }
133
+ return;
134
+ }
135
+ }
136
+ };
137
+ const node = (n) => {
138
+ switch (n.kind) {
139
+ case "lit":
140
+ for (let k = 0; k < n.text.length; k++)
141
+ emit({ op: 0, set: CharSet.char(n.text.charCodeAt(k)) });
142
+ return;
143
+ case "copy":
144
+ case "of": {
145
+ const id = idFor(n);
146
+ mark(ENTER, id);
147
+ re(n.engine);
148
+ mark(LEAVE, id);
149
+ return;
150
+ }
151
+ case "seq": {
152
+ const id = idFor(n);
153
+ mark(ENTER, id);
154
+ for (const p of n.parts)
155
+ node(p);
156
+ mark(LEAVE, id);
157
+ return;
158
+ }
159
+ case "alt": {
160
+ const id = idFor(n);
161
+ mark(ENTER, id);
162
+ const jmps = [];
163
+ for (let bi = 0; bi < n.branches.length; bi++) {
164
+ if (bi < n.branches.length - 1) {
165
+ const sp = { op: 1, x: 0, y: 0 };
166
+ emit(sp);
167
+ sp.x = code.length;
168
+ mark(BRANCH, id, bi);
169
+ node(n.branches[bi]);
170
+ const j = { op: 2, x: 0 };
171
+ emit(j);
172
+ jmps.push(j);
173
+ sp.y = code.length;
174
+ }
175
+ else {
176
+ mark(BRANCH, id, bi);
177
+ node(n.branches[bi]);
178
+ }
179
+ }
180
+ const end = code.length;
181
+ for (const j of jmps)
182
+ j.x = end;
183
+ mark(LEAVE, id);
184
+ return;
185
+ }
186
+ case "opt": {
187
+ const id = idFor(n);
188
+ mark(ENTER, id);
189
+ const sp = { op: 1, x: 0, y: 0 };
190
+ emit(sp);
191
+ sp.x = code.length; // present (greedy first)
192
+ mark(BRANCH, id, 1);
193
+ node(n.part);
194
+ const j = { op: 2, x: 0 };
195
+ emit(j);
196
+ sp.y = code.length; // absent
197
+ mark(BRANCH, id, 0);
198
+ j.x = code.length;
199
+ mark(LEAVE, id);
200
+ return;
201
+ }
202
+ case "star": {
203
+ const id = idFor(n);
204
+ mark(ENTER, id);
205
+ if (n.sep === undefined) {
206
+ if (n.min === 1)
207
+ node(n.part);
208
+ const sp = { op: 1, x: 0, y: 0 };
209
+ const back = code.length;
210
+ emit(sp);
211
+ sp.x = code.length; // iterate (greedy first)
212
+ node(n.part);
213
+ emit({ op: 2, x: back });
214
+ sp.y = code.length; // exit
215
+ }
216
+ else {
217
+ node(n.part); // ≥1 element, like Str.split
218
+ const sp = { op: 1, x: 0, y: 0 };
219
+ const back = code.length;
220
+ emit(sp);
221
+ sp.x = code.length; // (sep element)+
222
+ mark(SEP_START, id);
223
+ recog(n.sep);
224
+ mark(SEP_END, id);
225
+ node(n.part);
226
+ emit({ op: 2, x: back });
227
+ sp.y = code.length; // exit
228
+ }
229
+ mark(LEAVE, id);
230
+ return;
231
+ }
232
+ }
233
+ };
234
+ node(root);
235
+ emit({ op: 4 });
236
+ return { code, idOf };
237
+ }
238
+ /** Run the program over `s`, anchored to the whole string. Returns the winning
239
+ * thread's marker log wrapped in a result object, or `null` if no full parse
240
+ * exists. With `keepLog = false` no markers are allocated (recognition only),
241
+ * so a successful run reports `{ log: null }` — distinct from a `null` miss. */
242
+ function run(code, s, keepLog) {
243
+ const n = s.length;
244
+ const visited = new Int32Array(code.length).fill(-1);
245
+ const add = (list, gen, pc, log, pos) => {
246
+ if (visited[pc] === gen)
247
+ return;
248
+ visited[pc] = gen;
249
+ const ins = code[pc];
250
+ switch (ins.op) {
251
+ case 2: // jmp
252
+ add(list, gen, ins.x, log, pos);
253
+ return;
254
+ case 1: // split — x is higher priority
255
+ add(list, gen, ins.x, log, pos);
256
+ add(list, gen, ins.y, log, pos);
257
+ return;
258
+ case 3: {
259
+ // mark
260
+ const nl = keepLog
261
+ ? { k: ins.ev.k, id: ins.ev.id, i: ins.ev.i, pos, prev: log }
262
+ : null;
263
+ add(list, gen, pc + 1, nl, pos);
264
+ return;
265
+ }
266
+ default: // char (0) or match (4): a real (waiting) thread
267
+ list.push({ pc, log });
268
+ }
269
+ };
270
+ let gen = 0;
271
+ let clist = [];
272
+ add(clist, gen, 0, null, 0);
273
+ for (let pos = 0;; pos++) {
274
+ if (pos === n) {
275
+ for (const t of clist)
276
+ if (code[t.pc].op === 4)
277
+ return { log: t.log }; // highest-priority full match
278
+ return null;
279
+ }
280
+ const c = s.charCodeAt(pos);
281
+ gen++;
282
+ const nlist = [];
283
+ for (const t of clist) {
284
+ const ins = code[t.pc];
285
+ if (ins.op === 0 && ins.set.has(c))
286
+ add(nlist, gen, t.pc + 1, t.log, pos + 1);
287
+ // op === 4 (match before end-of-input) and non-matching chars: thread dies.
288
+ }
289
+ clist = nlist;
290
+ if (clist.length === 0)
291
+ return null;
292
+ }
293
+ }
294
+ // ── reconstruction (markers → value tree) ─────────────────────────────────
295
+ function logToEvs(log) {
296
+ const out = [];
297
+ for (let p = log; p !== null; p = p.prev)
298
+ out.push(p);
299
+ out.reverse();
300
+ return out;
301
+ }
302
+ /** Parse `s` fully; `null` if it doesn't match. Builds the value tree (and, if
303
+ * given, the named-capture span map) from the winning marker log. */
304
+ export function parseValue(root, prog, s, spans) {
305
+ const res = run(prog.code, s, true);
306
+ if (res === null)
307
+ return null;
308
+ const evs = res.log === null ? [] : logToEvs(res.log);
309
+ const idOf = prog.idOf;
310
+ let i = 0;
311
+ const build = (node) => {
312
+ switch (node.kind) {
313
+ case "lit":
314
+ return null; // silent: emits no markers, contributes no value
315
+ case "copy": {
316
+ const e = evs[i++];
317
+ const l = evs[i++];
318
+ const v = s.slice(e.pos, l.pos);
319
+ if (spans !== undefined && node.name !== undefined)
320
+ spans.set(node.name, [e.pos, l.pos]);
321
+ return v;
322
+ }
323
+ case "of": {
324
+ const e = evs[i++];
325
+ const l = evs[i++];
326
+ if (spans !== undefined && node.name !== undefined)
327
+ spans.set(node.name, [e.pos, l.pos]);
328
+ const v = node.codec.parse(s.slice(e.pos, l.pos));
329
+ return (v === undefined ? null : v);
330
+ }
331
+ case "seq": {
332
+ i++; // ENTER
333
+ const vals = [];
334
+ for (const p of node.parts) {
335
+ if (p.kind === "lit")
336
+ continue;
337
+ vals.push(build(p));
338
+ }
339
+ i++; // LEAVE
340
+ return vals;
341
+ }
342
+ case "alt": {
343
+ i++; // ENTER
344
+ const b = evs[i++]; // BRANCH
345
+ const val = build(node.branches[b.i]);
346
+ i++; // LEAVE
347
+ return { branch: b.i, val };
348
+ }
349
+ case "opt": {
350
+ i++; // ENTER
351
+ const b = evs[i++]; // BRANCH (1 = present, 0 = absent)
352
+ let val;
353
+ if (b.i === 1)
354
+ val = node.part.kind === "lit" ? true : build(node.part);
355
+ else
356
+ val = null;
357
+ i++; // LEAVE
358
+ return val;
359
+ }
360
+ case "star": {
361
+ const e = evs[i++]; // ENTER
362
+ const items = [];
363
+ const seps = [];
364
+ if (node.sep === undefined) {
365
+ const pid = idOf.get(node.part);
366
+ while (i < evs.length && evs[i].k === ENTER && evs[i].id === pid)
367
+ items.push(build(node.part));
368
+ }
369
+ else {
370
+ const sid = idOf.get(node);
371
+ items.push(build(node.part));
372
+ while (i < evs.length && evs[i].k === SEP_START && evs[i].id === sid) {
373
+ const ss = evs[i++];
374
+ const se = evs[i++];
375
+ seps.push(s.slice(ss.pos, se.pos));
376
+ items.push(build(node.part));
377
+ }
378
+ }
379
+ const l = evs[i++]; // LEAVE
380
+ if (spans !== undefined && node.name !== undefined)
381
+ spans.set(node.name, [e.pos, l.pos]);
382
+ return { items, seps };
383
+ }
384
+ }
385
+ };
386
+ return { val: build(root) };
387
+ }
388
+ /** Does the program match the whole of `s`? Recognition only (no allocation). */
389
+ export function recognize(prog, s) {
390
+ return run(prog.code, s, false) !== null;
391
+ }
@@ -0,0 +1,7 @@
1
+ import { type Re } from "./engine.js";
2
+ /** Thrown when a pattern uses a construct outside the regular subset. */
3
+ export declare class RegError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ /** Compile a `RegExp` to an engine `Re`, or throw `RegError`. */
7
+ export declare function compileRegex(re: RegExp): Re;