@turing-machine-js/machine 7.0.0-alpha.5 → 7.0.0-alpha.7
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/CHANGELOG.md +42 -0
- package/README.md +151 -61
- package/dist/classes/DebugSession.d.ts +119 -0
- package/dist/classes/State.d.ts +50 -4
- package/dist/classes/TuringMachine.d.ts +86 -71
- package/dist/index.cjs +721 -307
- package/dist/index.d.ts +3 -2
- package/dist/index.mjs +720 -308
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -13,13 +13,13 @@ function id(object) {
|
|
|
13
13
|
id[idKey] = 0;
|
|
14
14
|
id[idWeakMapKey] = new WeakMap();
|
|
15
15
|
|
|
16
|
-
var __classPrivateFieldSet$
|
|
16
|
+
var __classPrivateFieldSet$9 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
17
17
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
18
18
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
19
19
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
20
20
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
21
21
|
};
|
|
22
|
-
var __classPrivateFieldGet$
|
|
22
|
+
var __classPrivateFieldGet$9 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
23
23
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
24
24
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
25
25
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -39,36 +39,36 @@ class Alphabet {
|
|
|
39
39
|
if (!isSymbolsValid) {
|
|
40
40
|
throw new Error('symbols contains invalid symbol');
|
|
41
41
|
}
|
|
42
|
-
__classPrivateFieldSet$
|
|
42
|
+
__classPrivateFieldSet$9(this, _Alphabet_symbols, Array.from(uniqueSymbols), "f");
|
|
43
43
|
}
|
|
44
44
|
get symbols() {
|
|
45
|
-
return Array.from(__classPrivateFieldGet$
|
|
45
|
+
return Array.from(__classPrivateFieldGet$9(this, _Alphabet_symbols, "f"));
|
|
46
46
|
}
|
|
47
47
|
get blankSymbol() {
|
|
48
|
-
return __classPrivateFieldGet$
|
|
48
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f")[0];
|
|
49
49
|
}
|
|
50
50
|
has(symbol) {
|
|
51
|
-
return __classPrivateFieldGet$
|
|
51
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").indexOf(symbol) >= 0;
|
|
52
52
|
}
|
|
53
53
|
get(index) {
|
|
54
|
-
if (index < 0 || index >= __classPrivateFieldGet$
|
|
54
|
+
if (index < 0 || index >= __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").length) {
|
|
55
55
|
throw new Error('Invalid index');
|
|
56
56
|
}
|
|
57
|
-
return __classPrivateFieldGet$
|
|
57
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f")[index];
|
|
58
58
|
}
|
|
59
59
|
index(symbol) {
|
|
60
|
-
return __classPrivateFieldGet$
|
|
60
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").indexOf(symbol);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
_Alphabet_symbols = new WeakMap();
|
|
64
64
|
|
|
65
|
-
var __classPrivateFieldSet$
|
|
65
|
+
var __classPrivateFieldSet$8 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
66
66
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
67
67
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
68
68
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
69
69
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
70
70
|
};
|
|
71
|
-
var __classPrivateFieldGet$
|
|
71
|
+
var __classPrivateFieldGet$8 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
72
72
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
73
73
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
74
74
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -91,30 +91,30 @@ class TapeCommand {
|
|
|
91
91
|
if (!isValidMovement) {
|
|
92
92
|
throw new Error('invalid movement');
|
|
93
93
|
}
|
|
94
|
-
__classPrivateFieldSet$
|
|
94
|
+
__classPrivateFieldSet$8(this, _TapeCommand_movement, movement, "f");
|
|
95
95
|
const isValidSymbol = ((typeof symbol === 'string' && symbol.length === 1)
|
|
96
96
|
|| [symbolCommands.keep, symbolCommands.erase].includes(symbol));
|
|
97
97
|
if (!isValidSymbol) {
|
|
98
98
|
throw new Error('invalid symbol');
|
|
99
99
|
}
|
|
100
|
-
__classPrivateFieldSet$
|
|
100
|
+
__classPrivateFieldSet$8(this, _TapeCommand_symbol, symbol, "f");
|
|
101
101
|
}
|
|
102
102
|
get symbol() {
|
|
103
|
-
return __classPrivateFieldGet$
|
|
103
|
+
return __classPrivateFieldGet$8(this, _TapeCommand_symbol, "f");
|
|
104
104
|
}
|
|
105
105
|
get movement() {
|
|
106
|
-
return __classPrivateFieldGet$
|
|
106
|
+
return __classPrivateFieldGet$8(this, _TapeCommand_movement, "f");
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
_TapeCommand_movement = new WeakMap(), _TapeCommand_symbol = new WeakMap();
|
|
110
110
|
|
|
111
|
-
var __classPrivateFieldSet$
|
|
111
|
+
var __classPrivateFieldSet$7 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
112
112
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
113
113
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
114
114
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
115
115
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
116
116
|
};
|
|
117
|
-
var __classPrivateFieldGet$
|
|
117
|
+
var __classPrivateFieldGet$7 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
118
118
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
119
119
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
120
120
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -127,7 +127,7 @@ class Command {
|
|
|
127
127
|
throw new Error('invalid parameter');
|
|
128
128
|
}
|
|
129
129
|
try {
|
|
130
|
-
__classPrivateFieldSet$
|
|
130
|
+
__classPrivateFieldSet$7(this, _Command_tapesCommands, tapesCommands.map((tapeCommand) => {
|
|
131
131
|
if (tapeCommand instanceof TapeCommand) {
|
|
132
132
|
return tapeCommand;
|
|
133
133
|
}
|
|
@@ -139,17 +139,17 @@ class Command {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
get tapesCommands() {
|
|
142
|
-
return [...__classPrivateFieldGet$
|
|
142
|
+
return [...__classPrivateFieldGet$7(this, _Command_tapesCommands, "f")];
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
_Command_tapesCommands = new WeakMap();
|
|
146
146
|
|
|
147
|
-
var __classPrivateFieldGet$
|
|
147
|
+
var __classPrivateFieldGet$6 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
148
148
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
149
149
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
150
150
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
151
151
|
};
|
|
152
|
-
var __classPrivateFieldSet$
|
|
152
|
+
var __classPrivateFieldSet$6 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
153
153
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
154
154
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
155
155
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
@@ -161,16 +161,16 @@ class Reference {
|
|
|
161
161
|
_Reference_referenceBinding.set(this, null);
|
|
162
162
|
}
|
|
163
163
|
get ref() {
|
|
164
|
-
if (!__classPrivateFieldGet$
|
|
164
|
+
if (!__classPrivateFieldGet$6(this, _Reference_referenceBinding, "f")) {
|
|
165
165
|
throw new Error('unbounded reference');
|
|
166
166
|
}
|
|
167
|
-
return __classPrivateFieldGet$
|
|
167
|
+
return __classPrivateFieldGet$6(this, _Reference_referenceBinding, "f");
|
|
168
168
|
}
|
|
169
169
|
bind(state) {
|
|
170
|
-
if (__classPrivateFieldGet$
|
|
171
|
-
__classPrivateFieldSet$
|
|
170
|
+
if (__classPrivateFieldGet$6(this, _Reference_referenceBinding, "f") == null) {
|
|
171
|
+
__classPrivateFieldSet$6(this, _Reference_referenceBinding, state, "f");
|
|
172
172
|
}
|
|
173
|
-
return __classPrivateFieldGet$
|
|
173
|
+
return __classPrivateFieldGet$6(this, _Reference_referenceBinding, "f");
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
_Reference_referenceBinding = new WeakMap();
|
|
@@ -322,13 +322,13 @@ function decodeWriteSymbol(symbol) {
|
|
|
322
322
|
}
|
|
323
323
|
// Format converters (toMermaid / fromMermaid) live in ./graphFormats.
|
|
324
324
|
|
|
325
|
-
var __classPrivateFieldSet$
|
|
325
|
+
var __classPrivateFieldSet$5 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
326
326
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
327
327
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
328
328
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
329
329
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
330
330
|
};
|
|
331
|
-
var __classPrivateFieldGet$
|
|
331
|
+
var __classPrivateFieldGet$5 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
332
332
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
333
333
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
334
334
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -349,65 +349,65 @@ class Tape {
|
|
|
349
349
|
if (!isSymbolsValid) {
|
|
350
350
|
throw new Error('symbolList contains invalid symbol');
|
|
351
351
|
}
|
|
352
|
-
__classPrivateFieldSet$
|
|
353
|
-
__classPrivateFieldSet$
|
|
354
|
-
__classPrivateFieldSet$
|
|
355
|
-
const initialSymbols = symbols.length === 0 ? [__classPrivateFieldGet$
|
|
352
|
+
__classPrivateFieldSet$5(this, _Tape_alphabet, new Alphabet(alphabet), "f");
|
|
353
|
+
__classPrivateFieldSet$5(this, _Tape_position, position, "f");
|
|
354
|
+
__classPrivateFieldSet$5(this, _Tape_viewportWidth, 1, "f");
|
|
355
|
+
const initialSymbols = symbols.length === 0 ? [__classPrivateFieldGet$5(this, _Tape_alphabet, "f").blankSymbol] : symbols;
|
|
356
356
|
for (const symbol of initialSymbols) {
|
|
357
|
-
__classPrivateFieldGet$
|
|
357
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f").push(__classPrivateFieldGet$5(this, _Tape_alphabet, "f").index(symbol));
|
|
358
358
|
}
|
|
359
359
|
this.viewportWidth = viewportWidth;
|
|
360
360
|
}
|
|
361
361
|
get alphabet() {
|
|
362
|
-
return __classPrivateFieldGet$
|
|
362
|
+
return __classPrivateFieldGet$5(this, _Tape_alphabet, "f");
|
|
363
363
|
}
|
|
364
364
|
get extraCellsCount() {
|
|
365
|
-
return (__classPrivateFieldGet$
|
|
365
|
+
return (__classPrivateFieldGet$5(this, _Tape_viewportWidth, "f") - 1) / 2;
|
|
366
366
|
}
|
|
367
367
|
get position() {
|
|
368
368
|
// Public contract: index of the head in the `symbols` array. With the
|
|
369
369
|
// two-array deque, `#position` is the head's logical position; adding
|
|
370
370
|
// `#left.length` shifts it back into "index from the leftmost backed cell".
|
|
371
|
-
return __classPrivateFieldGet$
|
|
371
|
+
return __classPrivateFieldGet$5(this, _Tape_position, "f") + __classPrivateFieldGet$5(this, _Tape_left, "f").length;
|
|
372
372
|
}
|
|
373
373
|
get symbol() {
|
|
374
|
-
return __classPrivateFieldGet$
|
|
374
|
+
return __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_instances, "m", _Tape_cellAt).call(this, __classPrivateFieldGet$5(this, _Tape_position, "f")));
|
|
375
375
|
}
|
|
376
376
|
set symbol(symbol) {
|
|
377
|
-
if (!__classPrivateFieldGet$
|
|
377
|
+
if (!__classPrivateFieldGet$5(this, _Tape_alphabet, "f").has(symbol)) {
|
|
378
378
|
throw new Error('Invalid symbol');
|
|
379
379
|
}
|
|
380
|
-
const index = __classPrivateFieldGet$
|
|
381
|
-
if (__classPrivateFieldGet$
|
|
382
|
-
__classPrivateFieldGet$
|
|
380
|
+
const index = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").index(symbol);
|
|
381
|
+
if (__classPrivateFieldGet$5(this, _Tape_position, "f") >= 0) {
|
|
382
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f")[__classPrivateFieldGet$5(this, _Tape_position, "f")] = index;
|
|
383
383
|
}
|
|
384
384
|
else {
|
|
385
|
-
__classPrivateFieldGet$
|
|
385
|
+
__classPrivateFieldGet$5(this, _Tape_left, "f")[-__classPrivateFieldGet$5(this, _Tape_position, "f") - 1] = index;
|
|
386
386
|
}
|
|
387
|
-
__classPrivateFieldSet$
|
|
387
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
388
388
|
}
|
|
389
389
|
get symbols() {
|
|
390
|
-
const result = new Array(__classPrivateFieldGet$
|
|
391
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
392
|
-
result[i] = __classPrivateFieldGet$
|
|
390
|
+
const result = new Array(__classPrivateFieldGet$5(this, _Tape_left, "f").length + __classPrivateFieldGet$5(this, _Tape_right, "f").length);
|
|
391
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_left, "f").length; i += 1) {
|
|
392
|
+
result[i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_left, "f")[__classPrivateFieldGet$5(this, _Tape_left, "f").length - 1 - i]);
|
|
393
393
|
}
|
|
394
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
395
|
-
result[__classPrivateFieldGet$
|
|
394
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_right, "f").length; i += 1) {
|
|
395
|
+
result[__classPrivateFieldGet$5(this, _Tape_left, "f").length + i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_right, "f")[i]);
|
|
396
396
|
}
|
|
397
397
|
return result;
|
|
398
398
|
}
|
|
399
399
|
get viewport() {
|
|
400
|
-
if (__classPrivateFieldGet$
|
|
401
|
-
const start = __classPrivateFieldGet$
|
|
402
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
403
|
-
__classPrivateFieldGet$
|
|
400
|
+
if (__classPrivateFieldGet$5(this, _Tape_viewportDirty, "f")) {
|
|
401
|
+
const start = __classPrivateFieldGet$5(this, _Tape_position, "f") - this.extraCellsCount;
|
|
402
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_viewportWidth, "f"); i += 1) {
|
|
403
|
+
__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f")[i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_instances, "m", _Tape_cellAt).call(this, start + i));
|
|
404
404
|
}
|
|
405
|
-
__classPrivateFieldSet$
|
|
405
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, false, "f");
|
|
406
406
|
}
|
|
407
|
-
return [...__classPrivateFieldGet$
|
|
407
|
+
return [...__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f")];
|
|
408
408
|
}
|
|
409
409
|
get viewportWidth() {
|
|
410
|
-
return __classPrivateFieldGet$
|
|
410
|
+
return __classPrivateFieldGet$5(this, _Tape_viewportWidth, "f");
|
|
411
411
|
}
|
|
412
412
|
set viewportWidth(width) {
|
|
413
413
|
let finalWidth = width;
|
|
@@ -417,46 +417,46 @@ class Tape {
|
|
|
417
417
|
if (finalWidth % 2 === 0) {
|
|
418
418
|
finalWidth += 1;
|
|
419
419
|
}
|
|
420
|
-
__classPrivateFieldSet$
|
|
421
|
-
__classPrivateFieldGet$
|
|
422
|
-
__classPrivateFieldSet$
|
|
420
|
+
__classPrivateFieldSet$5(this, _Tape_viewportWidth, finalWidth, "f");
|
|
421
|
+
__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f").length = finalWidth;
|
|
422
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
423
423
|
this.normalise();
|
|
424
424
|
}
|
|
425
425
|
left() {
|
|
426
|
-
__classPrivateFieldSet$
|
|
426
|
+
__classPrivateFieldSet$5(this, _Tape_position, __classPrivateFieldGet$5(this, _Tape_position, "f") - 1, "f");
|
|
427
427
|
this.normalise();
|
|
428
|
-
__classPrivateFieldSet$
|
|
428
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
429
429
|
}
|
|
430
430
|
normalise() {
|
|
431
|
-
const minLogical = __classPrivateFieldGet$
|
|
432
|
-
const maxLogical = __classPrivateFieldGet$
|
|
433
|
-
while (-__classPrivateFieldGet$
|
|
434
|
-
__classPrivateFieldGet$
|
|
431
|
+
const minLogical = __classPrivateFieldGet$5(this, _Tape_position, "f") - this.extraCellsCount;
|
|
432
|
+
const maxLogical = __classPrivateFieldGet$5(this, _Tape_position, "f") + this.extraCellsCount;
|
|
433
|
+
while (-__classPrivateFieldGet$5(this, _Tape_left, "f").length > minLogical) {
|
|
434
|
+
__classPrivateFieldGet$5(this, _Tape_left, "f").push(BLANK_INDEX);
|
|
435
435
|
}
|
|
436
|
-
while (__classPrivateFieldGet$
|
|
437
|
-
__classPrivateFieldGet$
|
|
436
|
+
while (__classPrivateFieldGet$5(this, _Tape_right, "f").length - 1 < maxLogical) {
|
|
437
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f").push(BLANK_INDEX);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
right() {
|
|
441
|
-
__classPrivateFieldSet$
|
|
441
|
+
__classPrivateFieldSet$5(this, _Tape_position, __classPrivateFieldGet$5(this, _Tape_position, "f") + 1, "f");
|
|
442
442
|
this.normalise();
|
|
443
|
-
__classPrivateFieldSet$
|
|
443
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
446
|
_Tape_alphabet = new WeakMap(), _Tape_right = new WeakMap(), _Tape_left = new WeakMap(), _Tape_position = new WeakMap(), _Tape_viewportWidth = new WeakMap(), _Tape_viewportBuffer = new WeakMap(), _Tape_viewportDirty = new WeakMap(), _Tape_instances = new WeakSet(), _Tape_cellAt = function _Tape_cellAt(logical) {
|
|
447
447
|
if (logical >= 0) {
|
|
448
|
-
return logical < __classPrivateFieldGet$
|
|
448
|
+
return logical < __classPrivateFieldGet$5(this, _Tape_right, "f").length ? __classPrivateFieldGet$5(this, _Tape_right, "f")[logical] : BLANK_INDEX;
|
|
449
449
|
}
|
|
450
450
|
const ix = -logical - 1;
|
|
451
|
-
return ix < __classPrivateFieldGet$
|
|
451
|
+
return ix < __classPrivateFieldGet$5(this, _Tape_left, "f").length ? __classPrivateFieldGet$5(this, _Tape_left, "f")[ix] : BLANK_INDEX;
|
|
452
452
|
};
|
|
453
453
|
|
|
454
|
-
var __classPrivateFieldGet$
|
|
454
|
+
var __classPrivateFieldGet$4 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
455
455
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
456
456
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
457
457
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
458
458
|
};
|
|
459
|
-
var __classPrivateFieldSet$
|
|
459
|
+
var __classPrivateFieldSet$4 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
460
460
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
461
461
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
462
462
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
@@ -468,30 +468,30 @@ class Lock {
|
|
|
468
468
|
_Lock_lockSymbol.set(this, null);
|
|
469
469
|
}
|
|
470
470
|
lock(symbol) {
|
|
471
|
-
if (__classPrivateFieldGet$
|
|
472
|
-
__classPrivateFieldSet$
|
|
471
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") === null) {
|
|
472
|
+
__classPrivateFieldSet$4(this, _Lock_lockSymbol, symbol, "f");
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
unlock(symbol) {
|
|
476
|
-
if (__classPrivateFieldGet$
|
|
477
|
-
__classPrivateFieldSet$
|
|
476
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") === symbol) {
|
|
477
|
+
__classPrivateFieldSet$4(this, _Lock_lockSymbol, null, "f");
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
check(symbol) {
|
|
481
|
-
if (__classPrivateFieldGet$
|
|
481
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") && __classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") !== symbol) {
|
|
482
482
|
throw new Error('Lock check failed');
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
_Lock_lockSymbol = new WeakMap();
|
|
487
487
|
|
|
488
|
-
var __classPrivateFieldSet$
|
|
488
|
+
var __classPrivateFieldSet$3 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
489
489
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
490
490
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
491
491
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
492
492
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
493
493
|
};
|
|
494
|
-
var __classPrivateFieldGet$
|
|
494
|
+
var __classPrivateFieldGet$3 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
495
495
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
496
496
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
497
497
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -505,7 +505,7 @@ class TapeBlock {
|
|
|
505
505
|
_TapeBlock_lock.set(this, new Lock());
|
|
506
506
|
_TapeBlock_tapes.set(this, void 0);
|
|
507
507
|
_TapeBlock_buildPatternList.set(this, (symbolList) => symbolList.reduce((result, symbol, ix) => {
|
|
508
|
-
const row = Math.floor(ix / __classPrivateFieldGet$
|
|
508
|
+
const row = Math.floor(ix / __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length);
|
|
509
509
|
if (!Array.isArray(result[row])) {
|
|
510
510
|
result[row] = [];
|
|
511
511
|
}
|
|
@@ -521,7 +521,7 @@ class TapeBlock {
|
|
|
521
521
|
if (patternList.some((pattern) => pattern.every((symbol) => symbol === ifOtherSymbol))) {
|
|
522
522
|
return ifOtherSymbol;
|
|
523
523
|
}
|
|
524
|
-
const [storedPatternListSymbol] = [...__classPrivateFieldGet$
|
|
524
|
+
const [storedPatternListSymbol] = [...__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").entries()]
|
|
525
525
|
.find(([, storedPatternList]) => {
|
|
526
526
|
if (storedPatternList.length !== patternList.length) {
|
|
527
527
|
return false;
|
|
@@ -535,8 +535,8 @@ class TapeBlock {
|
|
|
535
535
|
symbol = storedPatternListSymbol;
|
|
536
536
|
}
|
|
537
537
|
else {
|
|
538
|
-
symbol = Symbol(__classPrivateFieldGet$
|
|
539
|
-
__classPrivateFieldGet$
|
|
538
|
+
symbol = Symbol(__classPrivateFieldGet$3(_a$1, _a$1, "f", _TapeBlock_generateSymbolHint).call(_a$1, patternList));
|
|
539
|
+
__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").set(symbol, patternList);
|
|
540
540
|
}
|
|
541
541
|
return symbol;
|
|
542
542
|
});
|
|
@@ -551,60 +551,60 @@ class TapeBlock {
|
|
|
551
551
|
else if (Array.isArray(symbols)) {
|
|
552
552
|
localSymbols = [...symbols];
|
|
553
553
|
}
|
|
554
|
-
if (localSymbols.length === 0 || localSymbols.length % __classPrivateFieldGet$
|
|
554
|
+
if (localSymbols.length === 0 || localSymbols.length % __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length > 0) {
|
|
555
555
|
throw new Error('invalid symbol parameter');
|
|
556
556
|
}
|
|
557
557
|
const invalidSymbolIndex = localSymbols.findIndex((symbol, ix) => (symbol !== ifOtherSymbol
|
|
558
|
-
&& !__classPrivateFieldGet$
|
|
558
|
+
&& !__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[ix % __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length].alphabet.has(symbol)));
|
|
559
559
|
if (invalidSymbolIndex >= 0) {
|
|
560
560
|
throw new Error('invalid symbol parameter');
|
|
561
561
|
}
|
|
562
562
|
if (localSymbols.every((symbol) => symbol === ifOtherSymbol)) {
|
|
563
563
|
return ifOtherSymbol;
|
|
564
564
|
}
|
|
565
|
-
return __classPrivateFieldGet$
|
|
565
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_getSymbolForPatternList, "f").call(this, __classPrivateFieldGet$3(this, _TapeBlock_buildPatternList, "f").call(this, localSymbols));
|
|
566
566
|
});
|
|
567
|
-
__classPrivateFieldSet$
|
|
567
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, [], "f");
|
|
568
568
|
if ('alphabets' in argument) {
|
|
569
569
|
const { alphabets } = argument;
|
|
570
570
|
if (alphabets.length === 0) {
|
|
571
571
|
throw new Error('empty alphabet list');
|
|
572
572
|
}
|
|
573
|
-
__classPrivateFieldSet$
|
|
573
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, alphabets.map((alphabet) => new Tape({
|
|
574
574
|
alphabet,
|
|
575
575
|
})), "f");
|
|
576
576
|
}
|
|
577
577
|
else if ('tapes' in argument) {
|
|
578
|
-
__classPrivateFieldSet$
|
|
578
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, argument.tapes, "f");
|
|
579
579
|
}
|
|
580
|
-
if (__classPrivateFieldGet$
|
|
580
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length === 0) {
|
|
581
581
|
throw new Error('empty tape list');
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
get alphabets() {
|
|
585
|
-
return [...__classPrivateFieldGet$
|
|
585
|
+
return [...__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").map((tape) => tape.alphabet)];
|
|
586
586
|
}
|
|
587
587
|
get currentSymbols() {
|
|
588
|
-
return __classPrivateFieldGet$
|
|
588
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").map((tape) => tape.symbol);
|
|
589
589
|
}
|
|
590
590
|
get [(_TapeBlock_symbolToPatternListMap = new WeakMap(), _TapeBlock_lock = new WeakMap(), _TapeBlock_tapes = new WeakMap(), _TapeBlock_buildPatternList = new WeakMap(), _TapeBlock_getSymbolForPatternList = new WeakMap(), _TapeBlock_symbol = new WeakMap(), lockSymbol)]() {
|
|
591
|
-
return __classPrivateFieldGet$
|
|
591
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_lock, "f");
|
|
592
592
|
}
|
|
593
593
|
get symbol() {
|
|
594
|
-
return __classPrivateFieldGet$
|
|
594
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_symbol, "f").bind(this);
|
|
595
595
|
}
|
|
596
596
|
get tapes() {
|
|
597
|
-
return [...__classPrivateFieldGet$
|
|
597
|
+
return [...__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")];
|
|
598
598
|
}
|
|
599
599
|
set [symbolToPatternListMapSymbol](symbolToPatternListMap) {
|
|
600
|
-
__classPrivateFieldSet$
|
|
600
|
+
__classPrivateFieldSet$3(this, _TapeBlock_symbolToPatternListMap, new Map(symbolToPatternListMap), "f");
|
|
601
601
|
}
|
|
602
602
|
applyCommand(command, executionSymbol = null) {
|
|
603
|
-
__classPrivateFieldGet$
|
|
604
|
-
if (__classPrivateFieldGet$
|
|
603
|
+
__classPrivateFieldGet$3(this, _TapeBlock_lock, "f").check(executionSymbol);
|
|
604
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length !== command.tapesCommands.length) {
|
|
605
605
|
throw new Error('invalid command');
|
|
606
606
|
}
|
|
607
|
-
__classPrivateFieldGet$
|
|
607
|
+
__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").forEach((tape, ix) => {
|
|
608
608
|
const { movement, symbol } = command.tapesCommands[ix];
|
|
609
609
|
if (typeof symbol === 'string') {
|
|
610
610
|
tape.symbol = symbol;
|
|
@@ -640,17 +640,17 @@ class TapeBlock {
|
|
|
640
640
|
else {
|
|
641
641
|
tapeBlock = _a$1.fromAlphabets(this.alphabets);
|
|
642
642
|
}
|
|
643
|
-
tapeBlock[symbolToPatternListMapSymbol] = __classPrivateFieldGet$
|
|
643
|
+
tapeBlock[symbolToPatternListMapSymbol] = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f");
|
|
644
644
|
return tapeBlock;
|
|
645
645
|
}
|
|
646
646
|
isMatched({ currentSymbols = this.currentSymbols, symbol }) {
|
|
647
647
|
if (symbol === ifOtherSymbol) {
|
|
648
648
|
return true;
|
|
649
649
|
}
|
|
650
|
-
if (!__classPrivateFieldGet$
|
|
650
|
+
if (!__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").has(symbol)) {
|
|
651
651
|
throw new Error('invalid symbol');
|
|
652
652
|
}
|
|
653
|
-
const patternList = __classPrivateFieldGet$
|
|
653
|
+
const patternList = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").get(symbol);
|
|
654
654
|
return patternList?.some((pattern) => (pattern
|
|
655
655
|
.every((everySymbol, ix) => (everySymbol === ifOtherSymbol
|
|
656
656
|
|| everySymbol === currentSymbols[ix])))) ?? false;
|
|
@@ -680,11 +680,11 @@ class TapeBlock {
|
|
|
680
680
|
* the State's normal matching): fall back to all `'literal'`.
|
|
681
681
|
*/
|
|
682
682
|
patternKinds(symbol, currentSymbols = this.currentSymbols) {
|
|
683
|
-
const tapeCount = __classPrivateFieldGet$
|
|
683
|
+
const tapeCount = __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length;
|
|
684
684
|
if (symbol === ifOtherSymbol) {
|
|
685
685
|
return Array.from({ length: tapeCount }, () => 'wildcard');
|
|
686
686
|
}
|
|
687
|
-
const patternList = __classPrivateFieldGet$
|
|
687
|
+
const patternList = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").get(symbol);
|
|
688
688
|
if (patternList === undefined) {
|
|
689
689
|
return Array.from({ length: tapeCount }, () => 'literal');
|
|
690
690
|
}
|
|
@@ -696,11 +696,11 @@ class TapeBlock {
|
|
|
696
696
|
return winning.map((everySymbol) => (everySymbol === ifOtherSymbol ? 'wildcard' : 'literal'));
|
|
697
697
|
}
|
|
698
698
|
replaceTape(tape, tapeIx = 0) {
|
|
699
|
-
if (__classPrivateFieldGet$
|
|
699
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx] == null) {
|
|
700
700
|
throw new Error('invalid tapeIx');
|
|
701
701
|
}
|
|
702
|
-
if (tape.alphabet.symbols.join('') === __classPrivateFieldGet$
|
|
703
|
-
__classPrivateFieldGet$
|
|
702
|
+
if (tape.alphabet.symbols.join('') === __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx].alphabet.symbols.join('')) {
|
|
703
|
+
__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx] = tape;
|
|
704
704
|
}
|
|
705
705
|
else {
|
|
706
706
|
throw new Error('invalid tape');
|
|
@@ -718,16 +718,11 @@ _TapeBlock_generateSymbolHint = { value: (patternList) => JSON.stringify(pattern
|
|
|
718
718
|
.map((pattern) => pattern
|
|
719
719
|
.map((symbol) => (symbol === ifOtherSymbol ? null : symbol)))) };
|
|
720
720
|
|
|
721
|
-
// Graph serialization/reconstruction for State graphs.
|
|
722
|
-
//
|
|
723
|
-
// machinery (transitions, debug, halt-stack composition). Sibling-module
|
|
724
|
-
// private access to State's internals goes through the `STATE_INTERNAL`
|
|
721
|
+
// Graph serialization/reconstruction + state collection for State graphs.
|
|
722
|
+
// Sibling-module access to State's internals uses the `STATE_INTERNAL`
|
|
725
723
|
// Symbol re-exported from State.ts — see the @internal JSDoc there.
|
|
726
|
-
//
|
|
727
|
-
//
|
|
728
|
-
// methods continue to exist as thin delegates to the functions in this
|
|
729
|
-
// module. New consumers (e.g. #195's planned `collectStates`) will live
|
|
730
|
-
// here too and share the BFS-walk shape with `toGraph`.
|
|
724
|
+
// `State.toGraph` / `.fromGraph` / `.collectStates` static methods on
|
|
725
|
+
// State are thin delegates to functions in this module.
|
|
731
726
|
/**
|
|
732
727
|
* Walks the reachable graph from `initialState` and returns a serializable
|
|
733
728
|
* `Graph`. The walk is a BFS that visits each State exactly once (keyed by
|
|
@@ -829,13 +824,11 @@ function toGraph(initialState, tapeBlock) {
|
|
|
829
824
|
movement: decodeMovement(tc.movement.description),
|
|
830
825
|
})),
|
|
831
826
|
nextStateId: targetInternal.id,
|
|
832
|
-
//
|
|
833
|
-
//
|
|
834
|
-
// matchedTransition.id` so consumers can do
|
|
827
|
+
// `${stateId}.${transitionIx}` — matches
|
|
828
|
+
// `MachineState.matchedTransition.id` so consumers can do
|
|
835
829
|
// `graph.nodes[stateId].transitions.find(t => t.id === id)`.
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
// marker ids in adjacent contexts.
|
|
830
|
+
// `.` separator (vs `-`) avoids collision with negative
|
|
831
|
+
// halt-marker ids.
|
|
839
832
|
id: `${stateInternal.id}.${patternIx}`,
|
|
840
833
|
});
|
|
841
834
|
queue.push(target);
|
|
@@ -860,33 +853,70 @@ function toGraph(initialState, tapeBlock) {
|
|
|
860
853
|
};
|
|
861
854
|
}
|
|
862
855
|
// Pass 2: For each bare, compute its forward-reachable set (following
|
|
863
|
-
// transitions; stopping at halt
|
|
864
|
-
//
|
|
856
|
+
// transitions; stopping at halt; including wrappers AND tunneling through
|
|
857
|
+
// them to their `overriddenHaltStateId` continuation).
|
|
858
|
+
//
|
|
859
|
+
// Wrappers are call-site markers — semantically owned by the CALLER (the
|
|
860
|
+
// bare whose body invokes the sub-call). Both the wrapper itself and its
|
|
861
|
+
// continuation (its `--> override` arrow in the rendered diagram, sourced
|
|
862
|
+
// from `overriddenHaltStateId`) belong to the caller's frame: the wrapper
|
|
863
|
+
// visually anchors the call site inside the caller's subgraph; the
|
|
864
|
+
// continuation is the state the caller's body resumes at AFTER the inner
|
|
865
|
+
// sub-call returns. So when reach traversal hits a wrapper, we PUSH the
|
|
866
|
+
// wrapper (joining the caller's reach-set) AND tunnel through to its
|
|
867
|
+
// continuation (also joining). Wrappers carry no `transitions` of their
|
|
868
|
+
// own (Pass 1 emits `transitions: []` on wrapper nodes), so the main loop
|
|
869
|
+
// pops them and adds them to `reach` without further traversal — but the
|
|
870
|
+
// continuation already entered via the wrapper-tunnel chain in
|
|
871
|
+
// `resolveAndPush`.
|
|
872
|
+
//
|
|
873
|
+
// Halt-bound retargeting + union-find then "just work": continuation
|
|
874
|
+
// states' halt-bound transitions get retargeted to the caller's halt
|
|
875
|
+
// marker (so an in-subroutine halt returns to the caller, not the
|
|
876
|
+
// program's terminal halt); when two bares both reach the same
|
|
877
|
+
// continuation through different wrapper chains, union-find merges their
|
|
878
|
+
// frames as it already does for non-wrapper overlap.
|
|
879
|
+
//
|
|
880
|
+
// Wrapper chains (continuation IS another wrapper, e.g., nested
|
|
881
|
+
// compositions) are walked transitively by the inner while-loop in
|
|
882
|
+
// `resolveAndPush` — each tunnel hop pushes the intermediate wrapper.
|
|
865
883
|
const computeReach = (startId) => {
|
|
866
884
|
const reach = new Set();
|
|
867
|
-
const stack = [
|
|
885
|
+
const stack = [];
|
|
886
|
+
const resolveAndPush = (id) => {
|
|
887
|
+
let current = id;
|
|
888
|
+
while (true) {
|
|
889
|
+
const target = nodes[current];
|
|
890
|
+
if (!target || target.isHalt) {
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
if (!target.isWrapper) {
|
|
894
|
+
stack.push(current);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
// Wrapper: push it (so it joins the caller's frame) AND tunnel to
|
|
898
|
+
// its continuation. Both belong to the caller's frame.
|
|
899
|
+
stack.push(current);
|
|
900
|
+
/* c8 ignore next 3 — every wrapper emitted by Pass 1 has a
|
|
901
|
+
non-null overriddenHaltStateId (lines 76-101); this branch
|
|
902
|
+
only guards against future wrapper variants that might not. */
|
|
903
|
+
if (target.overriddenHaltStateId === null) {
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
current = target.overriddenHaltStateId;
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
resolveAndPush(startId);
|
|
868
910
|
while (stack.length > 0) {
|
|
869
911
|
const id = stack.pop();
|
|
870
912
|
if (reach.has(id)) {
|
|
871
913
|
continue;
|
|
872
914
|
}
|
|
873
|
-
const node = nodes[id];
|
|
874
|
-
// `nodes[id]` is always populated for `id` that the BFS reached, so
|
|
875
|
-
// a defensive `!node` check would be dead. `isHalt` / `isWrapper`
|
|
876
|
-
// are real boundaries — both stop reach-set expansion.
|
|
877
|
-
/* c8 ignore next 3 — defensive: the push site below already filters
|
|
878
|
-
halt/wrapper targets, and the initial push is always a bare, so
|
|
879
|
-
this branch is unreachable in practice. */
|
|
880
|
-
if (node.isHalt || node.isWrapper) {
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
915
|
reach.add(id);
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
}
|
|
889
|
-
stack.push(t.nextStateId);
|
|
916
|
+
// Wrappers have empty transitions arrays — the for-loop runs zero
|
|
917
|
+
// iterations and we proceed to the next stack entry.
|
|
918
|
+
for (const t of nodes[id].transitions) {
|
|
919
|
+
resolveAndPush(t.nextStateId);
|
|
890
920
|
}
|
|
891
921
|
}
|
|
892
922
|
return reach;
|
|
@@ -1236,18 +1266,18 @@ function collectStates(initialState, tapeBlock) {
|
|
|
1236
1266
|
// source module finishes evaluating. All references here live inside
|
|
1237
1267
|
// function bodies, so the cycle is safe.
|
|
1238
1268
|
|
|
1239
|
-
var __classPrivateFieldSet$
|
|
1269
|
+
var __classPrivateFieldSet$2 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1240
1270
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1241
1271
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1242
1272
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
1243
1273
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1244
1274
|
};
|
|
1245
|
-
var __classPrivateFieldGet$
|
|
1275
|
+
var __classPrivateFieldGet$2 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1246
1276
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1247
1277
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
1248
1278
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1249
1279
|
};
|
|
1250
|
-
var _DebugConfig_ownerState, _DebugConfig_before, _DebugConfig_after, _State_instances, _a, _State_wrapperCache, _State_id, _State_name,
|
|
1280
|
+
var _DebugConfig_ownerState, _DebugConfig_before, _DebugConfig_after, _State_instances, _a, _State_wrapperCache, _State_id, _State_name, _State_symbolToDataMap, _State_debugRef, _State_haltDebug, _State_tags, _State_getEntry, _CallFrame_bare, _CallFrame_override;
|
|
1251
1281
|
const ifOtherSymbol = Symbol('other symbol');
|
|
1252
1282
|
// Module-private symbol used by DebugConfig setters to call State's validator
|
|
1253
1283
|
// without exposing the validator on the public surface.
|
|
@@ -1279,7 +1309,7 @@ class DebugConfig {
|
|
|
1279
1309
|
_DebugConfig_ownerState.set(this, void 0);
|
|
1280
1310
|
_DebugConfig_before.set(this, void 0);
|
|
1281
1311
|
_DebugConfig_after.set(this, void 0);
|
|
1282
|
-
__classPrivateFieldSet$
|
|
1312
|
+
__classPrivateFieldSet$2(this, _DebugConfig_ownerState, ownerState, "f");
|
|
1283
1313
|
if (initial) {
|
|
1284
1314
|
if (initial.before !== undefined) {
|
|
1285
1315
|
this.before = initial.before;
|
|
@@ -1296,18 +1326,18 @@ class DebugConfig {
|
|
|
1296
1326
|
Object.seal(this);
|
|
1297
1327
|
}
|
|
1298
1328
|
get before() {
|
|
1299
|
-
return __classPrivateFieldGet$
|
|
1329
|
+
return __classPrivateFieldGet$2(this, _DebugConfig_before, "f");
|
|
1300
1330
|
}
|
|
1301
1331
|
set before(v) {
|
|
1302
|
-
__classPrivateFieldGet$
|
|
1303
|
-
__classPrivateFieldSet$
|
|
1332
|
+
__classPrivateFieldGet$2(this, _DebugConfig_ownerState, "f")[validateDebugFilter]('before', v);
|
|
1333
|
+
__classPrivateFieldSet$2(this, _DebugConfig_before, Array.isArray(v) ? Object.freeze([...v]) : v, "f");
|
|
1304
1334
|
}
|
|
1305
1335
|
get after() {
|
|
1306
|
-
return __classPrivateFieldGet$
|
|
1336
|
+
return __classPrivateFieldGet$2(this, _DebugConfig_after, "f");
|
|
1307
1337
|
}
|
|
1308
1338
|
set after(v) {
|
|
1309
|
-
__classPrivateFieldGet$
|
|
1310
|
-
__classPrivateFieldSet$
|
|
1339
|
+
__classPrivateFieldGet$2(this, _DebugConfig_ownerState, "f")[validateDebugFilter]('after', v);
|
|
1340
|
+
__classPrivateFieldSet$2(this, _DebugConfig_after, Array.isArray(v) ? Object.freeze([...v]) : v, "f");
|
|
1311
1341
|
}
|
|
1312
1342
|
}
|
|
1313
1343
|
_DebugConfig_ownerState = new WeakMap(), _DebugConfig_before = new WeakMap(), _DebugConfig_after = new WeakMap();
|
|
@@ -1319,12 +1349,6 @@ class State {
|
|
|
1319
1349
|
// composed name on a no-arg `new State()` to bypass the constructor's
|
|
1320
1350
|
// user-facing name validation (composite names contain `(` and `)`).
|
|
1321
1351
|
_State_name.set(this, void 0);
|
|
1322
|
-
_State_overriddenHaltState.set(this, null);
|
|
1323
|
-
// For wrapper states (produced by `withOverriddenHaltState`), points at the
|
|
1324
|
-
// State whose transition map was wrapped. `null` on bare/atomic states.
|
|
1325
|
-
// Used by `toGraph` to collapse the wrapper-and-its-bare pair into a single
|
|
1326
|
-
// "wrapped bare" graph node — see the v7 emit redesign for #138.
|
|
1327
|
-
_State_bareState.set(this, null);
|
|
1328
1352
|
_State_symbolToDataMap.set(this, new Map());
|
|
1329
1353
|
// Shared mutable cell — withOverriddenHaltState wrappers reference the same
|
|
1330
1354
|
// object so that `state.debug = ...` (and nullings) propagate across them.
|
|
@@ -1350,11 +1374,11 @@ class State {
|
|
|
1350
1374
|
if (stateDefinition) {
|
|
1351
1375
|
const keys = Object.getOwnPropertyNames(stateDefinition);
|
|
1352
1376
|
if (keys.length) {
|
|
1353
|
-
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$
|
|
1377
|
+
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$2(this, _State_id, "f")}`);
|
|
1354
1378
|
}
|
|
1355
1379
|
const symbols = Object.getOwnPropertySymbols(stateDefinition);
|
|
1356
1380
|
if (symbols.length === 0) {
|
|
1357
|
-
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$
|
|
1381
|
+
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$2(this, _State_id, "f")}`);
|
|
1358
1382
|
}
|
|
1359
1383
|
symbols.forEach((symbol) => {
|
|
1360
1384
|
const { nextState } = stateDefinition[symbol];
|
|
@@ -1382,7 +1406,7 @@ class State {
|
|
|
1382
1406
|
if (!(commandLocal instanceof Command)) {
|
|
1383
1407
|
throw new Error('invalid command');
|
|
1384
1408
|
}
|
|
1385
|
-
__classPrivateFieldGet$
|
|
1409
|
+
__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").set(symbol, {
|
|
1386
1410
|
command: commandLocal,
|
|
1387
1411
|
nextState: nextStateLocal,
|
|
1388
1412
|
});
|
|
@@ -1391,19 +1415,21 @@ class State {
|
|
|
1391
1415
|
if (name !== undefined && /[()]/.test(name)) {
|
|
1392
1416
|
throw new Error(`invalid state name "${name}": must not contain '(' or ')' (reserved as wrapper-composition delimiters in withOverriddenHaltState)`);
|
|
1393
1417
|
}
|
|
1394
|
-
__classPrivateFieldSet$
|
|
1418
|
+
__classPrivateFieldSet$2(this, _State_name, name ?? `id:${__classPrivateFieldGet$2(this, _State_id, "f")}`, "f");
|
|
1395
1419
|
}
|
|
1396
1420
|
get id() {
|
|
1397
|
-
return __classPrivateFieldGet$
|
|
1421
|
+
return __classPrivateFieldGet$2(this, _State_id, "f");
|
|
1398
1422
|
}
|
|
1399
1423
|
get name() {
|
|
1400
|
-
return __classPrivateFieldGet$
|
|
1424
|
+
return __classPrivateFieldGet$2(this, _State_name, "f");
|
|
1401
1425
|
}
|
|
1402
1426
|
get isHalt() {
|
|
1403
|
-
return __classPrivateFieldGet$
|
|
1427
|
+
return __classPrivateFieldGet$2(this, _State_id, "f") === 0;
|
|
1404
1428
|
}
|
|
1429
|
+
// Plain States never override the halt state — only a `CallFrame` (produced
|
|
1430
|
+
// by `withOverriddenHaltState`) carries an override, via its own getter.
|
|
1405
1431
|
get overriddenHaltState() {
|
|
1406
|
-
return
|
|
1432
|
+
return null;
|
|
1407
1433
|
}
|
|
1408
1434
|
get ref() {
|
|
1409
1435
|
return this;
|
|
@@ -1418,17 +1444,17 @@ class State {
|
|
|
1418
1444
|
// declared `DebugConfig` for any rare caller that holds a State
|
|
1419
1445
|
// reference happening to be haltState.
|
|
1420
1446
|
if (this.isHalt) {
|
|
1421
|
-
return __classPrivateFieldGet$
|
|
1447
|
+
return __classPrivateFieldGet$2(this, _State_haltDebug, "f");
|
|
1422
1448
|
}
|
|
1423
1449
|
// Lazy-init: `state.debug` is never null at read time, so chained writes
|
|
1424
1450
|
// like `state.debug.before = true` work on a fresh state without a prior
|
|
1425
1451
|
// whole-object assignment. The setter still accepts `null` to reset the
|
|
1426
1452
|
// filters; the next read recreates a fresh empty `DebugConfig` on demand.
|
|
1427
1453
|
// See #150.
|
|
1428
|
-
if (__classPrivateFieldGet$
|
|
1429
|
-
__classPrivateFieldGet$
|
|
1454
|
+
if (__classPrivateFieldGet$2(this, _State_debugRef, "f").current === null) {
|
|
1455
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = new DebugConfig(this);
|
|
1430
1456
|
}
|
|
1431
|
-
return __classPrivateFieldGet$
|
|
1457
|
+
return __classPrivateFieldGet$2(this, _State_debugRef, "f").current;
|
|
1432
1458
|
}
|
|
1433
1459
|
// TS signature: non-halt callers (generic `State` reference) get the
|
|
1434
1460
|
// `DebugConfig | object | null` surface; boolean is rejected statically.
|
|
@@ -1447,7 +1473,7 @@ class State {
|
|
|
1447
1473
|
// (no own iter to anchor on; halt is terminal).
|
|
1448
1474
|
if (this.isHalt) {
|
|
1449
1475
|
if (v === null || typeof v === 'boolean') {
|
|
1450
|
-
__classPrivateFieldSet$
|
|
1476
|
+
__classPrivateFieldSet$2(this, _State_haltDebug, v === true, "f");
|
|
1451
1477
|
return;
|
|
1452
1478
|
}
|
|
1453
1479
|
throw new Error('haltState.debug only accepts boolean (or null to reset). Use '
|
|
@@ -1463,14 +1489,14 @@ class State {
|
|
|
1463
1489
|
+ '(or null to reset). Boolean assignment is reserved for `haltState`.');
|
|
1464
1490
|
}
|
|
1465
1491
|
if (v === null) {
|
|
1466
|
-
__classPrivateFieldGet$
|
|
1492
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = null;
|
|
1467
1493
|
return;
|
|
1468
1494
|
}
|
|
1469
1495
|
if (v instanceof DebugConfig) {
|
|
1470
|
-
__classPrivateFieldGet$
|
|
1496
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = v;
|
|
1471
1497
|
return;
|
|
1472
1498
|
}
|
|
1473
|
-
__classPrivateFieldGet$
|
|
1499
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = new DebugConfig(this, v);
|
|
1474
1500
|
}
|
|
1475
1501
|
/**
|
|
1476
1502
|
* Add one or more tags to this State (#186). Tags are out-of-band metadata
|
|
@@ -1480,7 +1506,7 @@ class State {
|
|
|
1480
1506
|
*/
|
|
1481
1507
|
tag(...tags) {
|
|
1482
1508
|
for (const t of tags) {
|
|
1483
|
-
__classPrivateFieldGet$
|
|
1509
|
+
__classPrivateFieldGet$2(this, _State_tags, "f").add(t);
|
|
1484
1510
|
}
|
|
1485
1511
|
return this;
|
|
1486
1512
|
}
|
|
@@ -1490,7 +1516,7 @@ class State {
|
|
|
1490
1516
|
*/
|
|
1491
1517
|
untag(...tags) {
|
|
1492
1518
|
for (const t of tags) {
|
|
1493
|
-
__classPrivateFieldGet$
|
|
1519
|
+
__classPrivateFieldGet$2(this, _State_tags, "f").delete(t);
|
|
1494
1520
|
}
|
|
1495
1521
|
return this;
|
|
1496
1522
|
}
|
|
@@ -1500,27 +1526,26 @@ class State {
|
|
|
1500
1526
|
* code uses). Order matches insertion order of the underlying Set.
|
|
1501
1527
|
*/
|
|
1502
1528
|
get tags() {
|
|
1503
|
-
return Object.freeze([...__classPrivateFieldGet$
|
|
1529
|
+
return Object.freeze([...__classPrivateFieldGet$2(this, _State_tags, "f")]);
|
|
1504
1530
|
}
|
|
1505
1531
|
/** @internal — invoked by DebugConfig setters via module-private symbol.
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
1508
|
-
|
|
1509
|
-
[(_State_id = new WeakMap(), _State_name = new WeakMap(), _State_overriddenHaltState = new WeakMap(), _State_bareState = new WeakMap(), _State_symbolToDataMap = new WeakMap(), _State_debugRef = new WeakMap(), _State_haltDebug = new WeakMap(), _State_tags = new WeakMap(), _State_instances = new WeakSet(), validateDebugFilter)](fieldName, filter) {
|
|
1532
|
+
* haltState's `debug` setter rejects object writes before reaching
|
|
1533
|
+
* DebugConfig, so this validator only sees non-halt states. */
|
|
1534
|
+
[(_State_id = new WeakMap(), _State_name = new WeakMap(), _State_symbolToDataMap = new WeakMap(), _State_debugRef = new WeakMap(), _State_haltDebug = new WeakMap(), _State_tags = new WeakMap(), _State_instances = new WeakSet(), validateDebugFilter)](fieldName, filter) {
|
|
1510
1535
|
if (filter === undefined)
|
|
1511
1536
|
return;
|
|
1512
1537
|
if (filter === true)
|
|
1513
1538
|
return;
|
|
1514
1539
|
for (const sym of filter) {
|
|
1515
|
-
if (sym !== ifOtherSymbol && !__classPrivateFieldGet$
|
|
1540
|
+
if (sym !== ifOtherSymbol && !__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").has(sym)) {
|
|
1516
1541
|
throw new Error(`State.debug.${fieldName}: symbol is not a transition key of this state `
|
|
1517
|
-
+ `(state name: ${__classPrivateFieldGet$
|
|
1542
|
+
+ `(state name: ${__classPrivateFieldGet$2(this, _State_name, "f")}). Common cause: symbol comes from a `
|
|
1518
1543
|
+ 'different tape block, or doesn\'t match any of this state\'s transitions.');
|
|
1519
1544
|
}
|
|
1520
1545
|
}
|
|
1521
1546
|
}
|
|
1522
1547
|
getSymbol(tapeBlock) {
|
|
1523
|
-
const symbol = [...__classPrivateFieldGet$
|
|
1548
|
+
const symbol = [...__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").keys()].find((currentSymbol) => tapeBlock.isMatched({
|
|
1524
1549
|
symbol: currentSymbol,
|
|
1525
1550
|
}));
|
|
1526
1551
|
if (symbol) {
|
|
@@ -1529,10 +1554,10 @@ class State {
|
|
|
1529
1554
|
return ifOtherSymbol;
|
|
1530
1555
|
}
|
|
1531
1556
|
getCommand(symbol) {
|
|
1532
|
-
return __classPrivateFieldGet$
|
|
1557
|
+
return __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol).command;
|
|
1533
1558
|
}
|
|
1534
1559
|
getNextState(symbol) {
|
|
1535
|
-
return __classPrivateFieldGet$
|
|
1560
|
+
return __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol).nextState;
|
|
1536
1561
|
}
|
|
1537
1562
|
/**
|
|
1538
1563
|
* Like `getNextState`, but also returns the matched Symbol and its index
|
|
@@ -1551,13 +1576,13 @@ class State {
|
|
|
1551
1576
|
* bare's transition iteration order — they're the same map.
|
|
1552
1577
|
*/
|
|
1553
1578
|
getMatchedTransition(symbol) {
|
|
1554
|
-
const entry = __classPrivateFieldGet$
|
|
1579
|
+
const entry = __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol);
|
|
1555
1580
|
// Iteration order on a Map is insertion order; index lookup is O(N),
|
|
1556
1581
|
// acceptable since this fires at most once per iter and N (transitions
|
|
1557
1582
|
// per state) is typically tiny. If hot-path measurement ever flags it,
|
|
1558
1583
|
// cache as `#symbolToIxMap` mirror.
|
|
1559
1584
|
let ix = 0;
|
|
1560
|
-
for (const key of __classPrivateFieldGet$
|
|
1585
|
+
for (const key of __classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").keys()) {
|
|
1561
1586
|
if (key === symbol)
|
|
1562
1587
|
break;
|
|
1563
1588
|
ix += 1;
|
|
@@ -1565,17 +1590,17 @@ class State {
|
|
|
1565
1590
|
return { nextState: entry.nextState, matchedSymbol: symbol, ix };
|
|
1566
1591
|
}
|
|
1567
1592
|
withOverriddenHaltState(overriddenHaltState) {
|
|
1568
|
-
// Unwrap `this` if it's itself a
|
|
1593
|
+
// Unwrap `this` if it's itself a CallFrame — the chain's inner overrides
|
|
1569
1594
|
// are dead at runtime anyway (only the outermost `.wohs()`'s override is
|
|
1570
1595
|
// pushed onto the halt-stack on entry; verified empirically). Composite
|
|
1571
1596
|
// name reflects runtime behavior, not construction history. See #176.
|
|
1572
|
-
const bare =
|
|
1597
|
+
const bare = this instanceof CallFrame ? this.bare : this;
|
|
1573
1598
|
// Memoize by (bare, override) so identical args return the same instance
|
|
1574
|
-
// (#175). The cache uses WeakMaps + WeakRefs so cached
|
|
1599
|
+
// (#175). The cache uses WeakMaps + WeakRefs so cached frames can be
|
|
1575
1600
|
// GC'd when nothing else holds them. Compounds with the chain-collapse
|
|
1576
1601
|
// above: `A.wohs(t1).wohs(t2)` keys as (A, t2) after the unwrap, hitting
|
|
1577
1602
|
// the same cache slot as a direct `A.wohs(t2)`.
|
|
1578
|
-
let innerCache = __classPrivateFieldGet$
|
|
1603
|
+
let innerCache = __classPrivateFieldGet$2(_a, _a, "f", _State_wrapperCache).get(bare);
|
|
1579
1604
|
if (innerCache !== undefined) {
|
|
1580
1605
|
const ref = innerCache.get(overriddenHaltState);
|
|
1581
1606
|
if (ref !== undefined) {
|
|
@@ -1587,19 +1612,11 @@ class State {
|
|
|
1587
1612
|
}
|
|
1588
1613
|
else {
|
|
1589
1614
|
innerCache = new WeakMap();
|
|
1590
|
-
__classPrivateFieldGet$
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
const state = new _a();
|
|
1596
|
-
__classPrivateFieldSet$1(state, _State_name, `${bare.name}(${overriddenHaltState.name})`, "f");
|
|
1597
|
-
__classPrivateFieldSet$1(state, _State_symbolToDataMap, __classPrivateFieldGet$1(bare, _State_symbolToDataMap, "f"), "f");
|
|
1598
|
-
__classPrivateFieldSet$1(state, _State_overriddenHaltState, overriddenHaltState, "f");
|
|
1599
|
-
__classPrivateFieldSet$1(state, _State_debugRef, __classPrivateFieldGet$1(bare, _State_debugRef, "f"), "f");
|
|
1600
|
-
__classPrivateFieldSet$1(state, _State_bareState, bare, "f");
|
|
1601
|
-
innerCache.set(overriddenHaltState, new WeakRef(state));
|
|
1602
|
-
return state;
|
|
1615
|
+
__classPrivateFieldGet$2(_a, _a, "f", _State_wrapperCache).set(bare, innerCache);
|
|
1616
|
+
}
|
|
1617
|
+
const frame = new CallFrame(bare, overriddenHaltState);
|
|
1618
|
+
innerCache.set(overriddenHaltState, new WeakRef(frame));
|
|
1619
|
+
return frame;
|
|
1603
1620
|
}
|
|
1604
1621
|
/**
|
|
1605
1622
|
* @internal
|
|
@@ -1626,9 +1643,9 @@ class State {
|
|
|
1626
1643
|
* each adds to the implicit contract sibling modules can rely on.
|
|
1627
1644
|
*/
|
|
1628
1645
|
[(_State_getEntry = function _State_getEntry(symbol) {
|
|
1629
|
-
const entry = __classPrivateFieldGet$
|
|
1646
|
+
const entry = __classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").get(symbol);
|
|
1630
1647
|
if (entry === undefined) {
|
|
1631
|
-
throw new Error(`No transition for symbol at state named ${__classPrivateFieldGet$
|
|
1648
|
+
throw new Error(`No transition for symbol at state named ${__classPrivateFieldGet$2(this, _State_name, "f")}`);
|
|
1632
1649
|
}
|
|
1633
1650
|
return entry;
|
|
1634
1651
|
}, STATE_INTERNAL)]() {
|
|
@@ -1639,13 +1656,13 @@ class State {
|
|
|
1639
1656
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1640
1657
|
const self = this;
|
|
1641
1658
|
return {
|
|
1642
|
-
get id() { return __classPrivateFieldGet$
|
|
1643
|
-
get name() { return __classPrivateFieldGet$
|
|
1644
|
-
set name(v) { __classPrivateFieldSet$
|
|
1645
|
-
get bareState() { return
|
|
1646
|
-
get overriddenHaltState() { return
|
|
1647
|
-
get symbolToDataMap() { return __classPrivateFieldGet$
|
|
1648
|
-
get tags() { return __classPrivateFieldGet$
|
|
1659
|
+
get id() { return __classPrivateFieldGet$2(self, _State_id, "f"); },
|
|
1660
|
+
get name() { return __classPrivateFieldGet$2(self, _State_name, "f"); },
|
|
1661
|
+
set name(v) { __classPrivateFieldSet$2(self, _State_name, v, "f"); },
|
|
1662
|
+
get bareState() { return null; },
|
|
1663
|
+
get overriddenHaltState() { return null; },
|
|
1664
|
+
get symbolToDataMap() { return __classPrivateFieldGet$2(self, _State_symbolToDataMap, "f"); },
|
|
1665
|
+
get tags() { return __classPrivateFieldGet$2(self, _State_tags, "f"); },
|
|
1649
1666
|
};
|
|
1650
1667
|
}
|
|
1651
1668
|
// Single-state introspection — no traversal, no tapeBlock required.
|
|
@@ -1654,8 +1671,13 @@ class State {
|
|
|
1654
1671
|
// Symbol patterns are returned as the raw description string from the
|
|
1655
1672
|
// interned JS Symbol (decode via decodePatternDescription if needed).
|
|
1656
1673
|
static inspect(state) {
|
|
1674
|
+
// Route through the STATE_INTERNAL view so a CallFrame reports its bare's
|
|
1675
|
+
// transitions and its own override — the view delegates those to the bare
|
|
1676
|
+
// / the frame's #override, whereas the raw private fields on a CallFrame
|
|
1677
|
+
// are empty/null.
|
|
1678
|
+
const internal = state[STATE_INTERNAL]();
|
|
1657
1679
|
const transitions = [];
|
|
1658
|
-
for (const [sym, { command, nextState }] of
|
|
1680
|
+
for (const [sym, { command, nextState }] of internal.symbolToDataMap) {
|
|
1659
1681
|
let target = null;
|
|
1660
1682
|
try {
|
|
1661
1683
|
target = nextState instanceof _a ? nextState : nextState.ref;
|
|
@@ -1672,12 +1694,13 @@ class State {
|
|
|
1672
1694
|
nextState: target ? { id: target.id, name: target.name } : null,
|
|
1673
1695
|
});
|
|
1674
1696
|
}
|
|
1697
|
+
const override = internal.overriddenHaltState;
|
|
1675
1698
|
return {
|
|
1676
|
-
id:
|
|
1677
|
-
name:
|
|
1699
|
+
id: internal.id,
|
|
1700
|
+
name: internal.name,
|
|
1678
1701
|
isHalt: state.isHalt,
|
|
1679
|
-
overriddenHaltState:
|
|
1680
|
-
? { id:
|
|
1702
|
+
overriddenHaltState: override
|
|
1703
|
+
? { id: override.id, name: override.name }
|
|
1681
1704
|
: null,
|
|
1682
1705
|
transitions,
|
|
1683
1706
|
};
|
|
@@ -1722,21 +1745,111 @@ _a = State;
|
|
|
1722
1745
|
// them, with cache misses simply reconstructing fresh wrappers.
|
|
1723
1746
|
_State_wrapperCache = { value: new WeakMap() };
|
|
1724
1747
|
const haltState = new State(null);
|
|
1748
|
+
/**
|
|
1749
|
+
* A first-class call frame produced by `State.withOverriddenHaltState`
|
|
1750
|
+
* (#213). A `CallFrame` is a `State` — `instanceof State` holds, so it flows
|
|
1751
|
+
* anywhere a `State` does (as a `nextState`, through `toGraph`/`fromGraph`,
|
|
1752
|
+
* etc.) — but it carries its own `bare` (the wrapped State) and `override`
|
|
1753
|
+
* (the continuation pushed onto the run-stack on entry). `instanceof
|
|
1754
|
+
* CallFrame` is the explicit wrapper discriminator.
|
|
1755
|
+
*
|
|
1756
|
+
* It owns no transitions of its own: lookups (`getSymbol`/`getCommand`/
|
|
1757
|
+
* `getNextState`/`getMatchedTransition`) and `debug` DELEGATE to the bare,
|
|
1758
|
+
* replacing the v6 field-aliasing (where a wrapper was a plain `State` whose
|
|
1759
|
+
* private `#symbolToDataMap`/`#debugRef` were physically shared with the
|
|
1760
|
+
* bare). `id`, `name` (composite `bare(override)`), and `tags` are its own
|
|
1761
|
+
* (inherited State fields) — so memoized frames sharing a bare keep
|
|
1762
|
+
* independent tags (#186), and the frame is never the halt singleton
|
|
1763
|
+
* (fresh nonzero `#id` → `isHalt === false`).
|
|
1764
|
+
*/
|
|
1765
|
+
class CallFrame extends State {
|
|
1766
|
+
constructor(bare, override) {
|
|
1767
|
+
super(null);
|
|
1768
|
+
_CallFrame_bare.set(this, void 0);
|
|
1769
|
+
_CallFrame_override.set(this, void 0);
|
|
1770
|
+
__classPrivateFieldSet$2(this, _CallFrame_bare, bare, "f");
|
|
1771
|
+
__classPrivateFieldSet$2(this, _CallFrame_override, override, "f");
|
|
1772
|
+
// Composite name contains `(` / `)`, which the constructor's user-facing
|
|
1773
|
+
// name validator rejects; the STATE_INTERNAL name setter bypasses it
|
|
1774
|
+
// (writes the inherited #name). `super[...]` reaches State's own view so
|
|
1775
|
+
// we don't recurse through this subclass's override below.
|
|
1776
|
+
super[STATE_INTERNAL]().name = `${bare.name}(${override.name})`;
|
|
1777
|
+
}
|
|
1778
|
+
get bare() {
|
|
1779
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f");
|
|
1780
|
+
}
|
|
1781
|
+
get overriddenHaltState() {
|
|
1782
|
+
return __classPrivateFieldGet$2(this, _CallFrame_override, "f");
|
|
1783
|
+
}
|
|
1784
|
+
getSymbol(tapeBlock) {
|
|
1785
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f").getSymbol(tapeBlock);
|
|
1786
|
+
}
|
|
1787
|
+
getCommand(symbol) {
|
|
1788
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f").getCommand(symbol);
|
|
1789
|
+
}
|
|
1790
|
+
getNextState(symbol) {
|
|
1791
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f").getNextState(symbol);
|
|
1792
|
+
}
|
|
1793
|
+
getMatchedTransition(symbol) {
|
|
1794
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f").getMatchedTransition(symbol);
|
|
1795
|
+
}
|
|
1796
|
+
get debug() {
|
|
1797
|
+
return __classPrivateFieldGet$2(this, _CallFrame_bare, "f").debug;
|
|
1798
|
+
}
|
|
1799
|
+
set debug(value) {
|
|
1800
|
+
__classPrivateFieldGet$2(this, _CallFrame_bare, "f").debug = value;
|
|
1801
|
+
}
|
|
1802
|
+
[(_CallFrame_bare = new WeakMap(), _CallFrame_override = new WeakMap(), STATE_INTERNAL)]() {
|
|
1803
|
+
// Own id / name / tags come from the inherited State fields (via super's
|
|
1804
|
+
// view); bareState / overriddenHaltState / the transition map delegate to
|
|
1805
|
+
// #bare / #override so sibling modules (stateGraph, inspect) see the
|
|
1806
|
+
// frame's true shape.
|
|
1807
|
+
const own = super[STATE_INTERNAL]();
|
|
1808
|
+
const bare = __classPrivateFieldGet$2(this, _CallFrame_bare, "f");
|
|
1809
|
+
const override = __classPrivateFieldGet$2(this, _CallFrame_override, "f");
|
|
1810
|
+
return {
|
|
1811
|
+
get id() { return own.id; },
|
|
1812
|
+
get name() { return own.name; },
|
|
1813
|
+
set name(v) { own.name = v; },
|
|
1814
|
+
get bareState() { return bare; },
|
|
1815
|
+
get overriddenHaltState() { return override; },
|
|
1816
|
+
get symbolToDataMap() { return bare[STATE_INTERNAL]().symbolToDataMap; },
|
|
1817
|
+
get tags() { return own.tags; },
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1725
1821
|
|
|
1726
|
-
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1822
|
+
var __classPrivateFieldSet$1 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1727
1823
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1728
1824
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1729
1825
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
1730
1826
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1731
1827
|
};
|
|
1732
|
-
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1828
|
+
var __classPrivateFieldGet$1 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1733
1829
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1734
1830
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
1735
1831
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1736
1832
|
};
|
|
1737
1833
|
var _TuringMachine_tapeBlock;
|
|
1738
|
-
|
|
1739
|
-
|
|
1834
|
+
/**
|
|
1835
|
+
* @internal — package-private accessor key for `MachineState` instances yielded
|
|
1836
|
+
* by `runStepByStep`. Calling `machineState[MACHINE_STATE_INTERNAL]()` returns a
|
|
1837
|
+
* frozen snapshot of the engine's halt-stack at yield time (BEFORE this iter's
|
|
1838
|
+
* applyCommand / pop / push). Consumed by `DebugSession` for step-over /
|
|
1839
|
+
* step-out endpoint detection without exposing the stack to public API.
|
|
1840
|
+
*
|
|
1841
|
+
* Re-exported from this module so the sibling `DebugSession` module can import
|
|
1842
|
+
* it; intentionally NOT re-exported from the package's public `index.ts` —
|
|
1843
|
+
* downstream consumers shouldn't reach for the stack. Same pattern as
|
|
1844
|
+
* `STATE_INTERNAL` (#180).
|
|
1845
|
+
*/
|
|
1846
|
+
const MACHINE_STATE_INTERNAL = Symbol('MachineState.internal');
|
|
1847
|
+
/**
|
|
1848
|
+
* @internal — true iff `filter` matches `symbol` per the DebugConfig semantics.
|
|
1849
|
+
* undefined / [] -> never; true -> always; symbol[] -> exact membership.
|
|
1850
|
+
* Exported for sibling-module use in `DebugSession` (which now owns breakpoint
|
|
1851
|
+
* detection); NOT re-exported from the package's public `index.ts`.
|
|
1852
|
+
*/
|
|
1740
1853
|
function matchFilter(filter, symbol) {
|
|
1741
1854
|
if (filter === undefined)
|
|
1742
1855
|
return false;
|
|
@@ -1750,43 +1863,42 @@ class TuringMachine {
|
|
|
1750
1863
|
if (!tapeBlock) {
|
|
1751
1864
|
throw new Error('invalid tapeBlock');
|
|
1752
1865
|
}
|
|
1753
|
-
__classPrivateFieldSet(this, _TuringMachine_tapeBlock, tapeBlock, "f");
|
|
1866
|
+
__classPrivateFieldSet$1(this, _TuringMachine_tapeBlock, tapeBlock, "f");
|
|
1754
1867
|
}
|
|
1755
1868
|
get tapeBlock() {
|
|
1756
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f");
|
|
1757
|
-
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1869
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f");
|
|
1870
|
+
}
|
|
1871
|
+
/**
|
|
1872
|
+
* Run the machine to halt. Pure execution — synchronous, no observation
|
|
1873
|
+
* callbacks, no debug overhead. For breakpoint-driven interactive debugging
|
|
1874
|
+
* use `DebugSession`; for per-iter tracing use `runStepByStep`'s generator
|
|
1875
|
+
* directly.
|
|
1876
|
+
*
|
|
1877
|
+
* Breakpoint metadata (`state.debug` / `haltState.debug` matches) is still
|
|
1878
|
+
* resolved and attached to each yielded MachineState by the underlying
|
|
1879
|
+
* generator — `run()` simply doesn't dispatch on it. A consumer that wants
|
|
1880
|
+
* to dispatch on it constructs a `DebugSession` instead.
|
|
1881
|
+
*
|
|
1882
|
+
* Symmetric reversal of v4's `run` → `async run` change: v4 made the method
|
|
1883
|
+
* async to support awaited `onPause`; with callbacks moved to `DebugSession`
|
|
1884
|
+
* there's no async work left, so the method returns `void` again.
|
|
1885
|
+
*/
|
|
1886
|
+
run({ initialState, stepsLimit = 1e5 }) {
|
|
1887
|
+
// Drain the generator. We don't care about the yielded values — the
|
|
1888
|
+
// generator's job is to advance the tape; only side effects matter here.
|
|
1889
|
+
// Casting to unknown so eslint doesn't flag the unused `_` variable.
|
|
1890
|
+
for (const machineState of this.runStepByStep({ initialState, stepsLimit })) {
|
|
1776
1891
|
}
|
|
1777
1892
|
}
|
|
1778
1893
|
*runStepByStep({ initialState, stepsLimit = 1e5 }) {
|
|
1779
1894
|
const executionSymbol = Symbol('execution');
|
|
1780
1895
|
try {
|
|
1781
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].check(executionSymbol);
|
|
1782
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].lock(executionSymbol);
|
|
1783
|
-
// Halt-stack is run-scoped, not machine-scoped (#196)
|
|
1784
|
-
//
|
|
1785
|
-
//
|
|
1786
|
-
//
|
|
1787
|
-
// halt-bound transition. Before this change `#stack` was an instance
|
|
1788
|
-
// field and accumulated one extra push per call when the same machine
|
|
1789
|
-
// was reused.
|
|
1896
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].check(executionSymbol);
|
|
1897
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].lock(executionSymbol);
|
|
1898
|
+
// Halt-stack is run-scoped, not machine-scoped (#196) — local
|
|
1899
|
+
// declaration prevents leftover entries from a previous
|
|
1900
|
+
// `runStepByStep` call (e.g. a build-time peek that never drained
|
|
1901
|
+
// the generator) from leaking into a subsequent halt-bound transition.
|
|
1790
1902
|
const stack = [];
|
|
1791
1903
|
let state = initialState;
|
|
1792
1904
|
if (state.overriddenHaltState) {
|
|
@@ -1798,59 +1910,37 @@ class TuringMachine {
|
|
|
1798
1910
|
throw new Error('Long execution');
|
|
1799
1911
|
}
|
|
1800
1912
|
i += 1;
|
|
1801
|
-
const symbol = state.getSymbol(__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f"));
|
|
1913
|
+
const symbol = state.getSymbol(__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f"));
|
|
1802
1914
|
const command = state.getCommand(symbol);
|
|
1803
1915
|
const matched = state.getMatchedTransition(symbol);
|
|
1804
1916
|
let nextState = matched.nextState.ref;
|
|
1805
|
-
// For wrapper-entry iters,
|
|
1806
|
-
// are empty (
|
|
1807
|
-
//
|
|
1808
|
-
|
|
1809
|
-
// is a wrapper produced by `withOverriddenHaltState`. Accessed
|
|
1810
|
-
// via the STATE_INTERNAL package-private view (same pattern
|
|
1811
|
-
// `utilities/stateGraph.ts` uses) to avoid widening the public
|
|
1812
|
-
// State API for this internal need.
|
|
1813
|
-
const stateInternal = state[STATE_INTERNAL]();
|
|
1814
|
-
const resolvableStateId = stateInternal.bareState?.id ?? state.id;
|
|
1917
|
+
// For wrapper-entry iters, a CallFrame's own transitions in `toGraph`
|
|
1918
|
+
// are empty (it delegates lookups to its bare); the resolvable
|
|
1919
|
+
// transition id lives under the bare's stateId.
|
|
1920
|
+
const resolvableStateId = state instanceof CallFrame ? state.bare.id : state.id;
|
|
1815
1921
|
const matchedTransition = {
|
|
1816
1922
|
id: `${resolvableStateId}.${matched.ix}`,
|
|
1817
|
-
matchKinds: __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").patternKinds(matched.matchedSymbol),
|
|
1923
|
+
matchKinds: __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").patternKinds(matched.matchedSymbol),
|
|
1818
1924
|
};
|
|
1819
1925
|
try {
|
|
1820
|
-
//
|
|
1821
|
-
//
|
|
1822
|
-
//
|
|
1823
|
-
//
|
|
1824
|
-
// #207: `haltState.debug` is now a boolean, and pauses on the
|
|
1825
|
-
// halt-triggering iter's AFTER side (not before). The previous
|
|
1826
|
-
// before-side check (`nextState.debug?.before === true`) was
|
|
1827
|
-
// "early-warning" timing — the user paused before the halt-bound
|
|
1828
|
-
// transition fired, then had to mentally re-derive what would
|
|
1829
|
-
// happen. Now the pause anchors post-step (after the iter's own
|
|
1830
|
-
// after-pause if armed), so consumers see the just-fired halt-
|
|
1831
|
-
// bound transition + diagram cursor still on the triggering state.
|
|
1832
|
-
//
|
|
1833
|
-
// `state` here is always non-halt (halt is terminal — the run
|
|
1834
|
-
// loop never iterates with state === haltState), so `state.debug`
|
|
1835
|
-
// is always `DebugConfig` at runtime. The public getter's return
|
|
1836
|
-
// type matches that.
|
|
1837
|
-
const beforeMatch = matchFilter(state.debug?.before, symbol);
|
|
1838
|
-
const afterMatch = matchFilter(state.debug?.after, symbol)
|
|
1839
|
-
|| (nextState === haltState && haltState.debug);
|
|
1926
|
+
// `runStepByStep` is the minimal execution primitive: it advances the
|
|
1927
|
+
// machine and reports state. It does NO breakpoint detection — that's
|
|
1928
|
+
// a debug concern that lives entirely in `DebugSession`. The yielded
|
|
1929
|
+
// `MachineState` has no `pause` / `debugBreak` field.
|
|
1840
1930
|
const nextStateForYield = nextState.isHalt && stack.length
|
|
1841
1931
|
? stack.slice(-1)[0]
|
|
1842
1932
|
: nextState;
|
|
1843
1933
|
const yielded = {
|
|
1844
1934
|
step: i,
|
|
1845
1935
|
state,
|
|
1846
|
-
currentSymbols: __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").currentSymbols,
|
|
1936
|
+
currentSymbols: __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").currentSymbols,
|
|
1847
1937
|
nextSymbols: command.tapesCommands.map((tapeCommand, ix) => {
|
|
1848
1938
|
if (typeof tapeCommand.symbol === 'symbol') {
|
|
1849
1939
|
switch (tapeCommand.symbol) {
|
|
1850
1940
|
case symbolCommands.erase:
|
|
1851
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].alphabet.blankSymbol;
|
|
1941
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").tapes[ix].alphabet.blankSymbol;
|
|
1852
1942
|
case symbolCommands.keep:
|
|
1853
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].symbol;
|
|
1943
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").tapes[ix].symbol;
|
|
1854
1944
|
default:
|
|
1855
1945
|
throw new Error('invalid symbol command');
|
|
1856
1946
|
}
|
|
@@ -1861,16 +1951,24 @@ class TuringMachine {
|
|
|
1861
1951
|
nextState: nextStateForYield,
|
|
1862
1952
|
matchedTransition,
|
|
1863
1953
|
};
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1954
|
+
// #102: expose the pre-iter halt-stack + the matched symbol to
|
|
1955
|
+
// DebugSession via a Symbol-keyed accessor (non-enumerable, so it
|
|
1956
|
+
// doesn't leak into serialization / spread / toEqual). The stack
|
|
1957
|
+
// snapshot is frozen so a consumer holding a reference can't mutate
|
|
1958
|
+
// the engine's stack. DebugSession reads `matchedSymbol` to evaluate
|
|
1959
|
+
// `state.debug` filters — keeping breakpoint detection out of this
|
|
1960
|
+
// primitive.
|
|
1961
|
+
const stackSnapshot = Object.freeze(stack.slice());
|
|
1962
|
+
// Snapshot halt-imminence on the RAW nextState NOW, before the
|
|
1963
|
+
// post-yield pop reassigns `nextState` — so the closure can't capture
|
|
1964
|
+
// the mutated value.
|
|
1965
|
+
const haltImminent = nextState === haltState;
|
|
1966
|
+
Object.defineProperty(yielded, MACHINE_STATE_INTERNAL, {
|
|
1967
|
+
value: () => ({ stack: stackSnapshot, matchedSymbol: symbol, haltImminent }),
|
|
1968
|
+
enumerable: false,
|
|
1969
|
+
});
|
|
1872
1970
|
yield yielded;
|
|
1873
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").applyCommand(command, executionSymbol);
|
|
1971
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").applyCommand(command, executionSymbol);
|
|
1874
1972
|
if (nextState.isHalt && stack.length) {
|
|
1875
1973
|
nextState = stack.pop();
|
|
1876
1974
|
}
|
|
@@ -1888,12 +1986,312 @@ class TuringMachine {
|
|
|
1888
1986
|
}
|
|
1889
1987
|
}
|
|
1890
1988
|
finally {
|
|
1891
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].unlock(executionSymbol);
|
|
1989
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].unlock(executionSymbol);
|
|
1892
1990
|
}
|
|
1893
1991
|
}
|
|
1894
1992
|
}
|
|
1895
1993
|
_TuringMachine_tapeBlock = new WeakMap();
|
|
1896
1994
|
|
|
1995
|
+
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1996
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1997
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1998
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
1999
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
2000
|
+
};
|
|
2001
|
+
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2002
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
2003
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
2004
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
2005
|
+
};
|
|
2006
|
+
var _DebugSession_instances, _DebugSession_machine, _DebugSession_parameter, _DebugSession_listeners, _DebugSession_started, _DebugSession_stopped, _DebugSession_iterating, _DebugSession_pauseResolver, _DebugSession_activeStepMode, _DebugSession_capturedDepth, _DebugSession_clickTimeDepth, _DebugSession_runIntervalMs, _DebugSession_pauseRequested, _DebugSession_releasePause, _DebugSession_dispatchPause, _DebugSession_readInternal, _DebugSession_readStack, _DebugSession_drive;
|
|
2007
|
+
/**
|
|
2008
|
+
* Interactive debugger session for `TuringMachine`. Owns the coordination
|
|
2009
|
+
* layer that every UI debugger / IDE extension / educational demo would
|
|
2010
|
+
* otherwise reimplement: breakpoint dispatch, step-in / step-over / step-out,
|
|
2011
|
+
* click-pause from outside, per-iter throttle, pause/resume promise plumbing.
|
|
2012
|
+
*
|
|
2013
|
+
* Construction is direct — the engine class stays minimal and doesn't expose a
|
|
2014
|
+
* `debugRun()` factory; consumers import both classes and write
|
|
2015
|
+
* `new DebugSession(machine, {initialState})`.
|
|
2016
|
+
*
|
|
2017
|
+
* Lifecycle:
|
|
2018
|
+
* const session = new DebugSession(machine, {initialState});
|
|
2019
|
+
* session.on('pause', (m) => { ...; session.continue(); });
|
|
2020
|
+
* session.on('halt', () => { ... });
|
|
2021
|
+
* await session.start(); // resolves on natural halt or stop()
|
|
2022
|
+
*
|
|
2023
|
+
* Each session is single-use: `start()` may only be called once. Construct a
|
|
2024
|
+
* fresh session to re-run.
|
|
2025
|
+
*/
|
|
2026
|
+
class DebugSession {
|
|
2027
|
+
constructor(machine, parameter) {
|
|
2028
|
+
_DebugSession_instances.add(this);
|
|
2029
|
+
_DebugSession_machine.set(this, void 0);
|
|
2030
|
+
_DebugSession_parameter.set(this, void 0);
|
|
2031
|
+
_DebugSession_listeners.set(this, {
|
|
2032
|
+
pause: [],
|
|
2033
|
+
step: [],
|
|
2034
|
+
iter: [],
|
|
2035
|
+
halt: [],
|
|
2036
|
+
});
|
|
2037
|
+
_DebugSession_started.set(this, false);
|
|
2038
|
+
_DebugSession_stopped.set(this, false);
|
|
2039
|
+
_DebugSession_iterating.set(this, false);
|
|
2040
|
+
_DebugSession_pauseResolver.set(this, null);
|
|
2041
|
+
_DebugSession_activeStepMode.set(this, null);
|
|
2042
|
+
/**
|
|
2043
|
+
* Halt-stack DEPTH snapshotted at the most recent pause dispatch (= number
|
|
2044
|
+
* of frames on the stack). DevTools-style step granularity is depth-based:
|
|
2045
|
+
* stepOver pauses at the next iter with `depth <= clickTimeDepth` (skip
|
|
2046
|
+
* frames the stepped-over iter pushes, pause back at the start level);
|
|
2047
|
+
* stepOut at `depth < clickTimeDepth` (the current frame itself exited).
|
|
2048
|
+
* Captured on EVERY pause so a step* call from the listener can freeze it.
|
|
2049
|
+
*/
|
|
2050
|
+
_DebugSession_capturedDepth.set(this, 0);
|
|
2051
|
+
/** The click-time depth frozen when a stepOver / stepOut directive is issued. */
|
|
2052
|
+
_DebugSession_clickTimeDepth.set(this, 0);
|
|
2053
|
+
_DebugSession_runIntervalMs.set(this, 0);
|
|
2054
|
+
_DebugSession_pauseRequested.set(this, false);
|
|
2055
|
+
__classPrivateFieldSet(this, _DebugSession_machine, machine, "f");
|
|
2056
|
+
__classPrivateFieldSet(this, _DebugSession_parameter, parameter, "f");
|
|
2057
|
+
}
|
|
2058
|
+
on(event, listener) {
|
|
2059
|
+
__classPrivateFieldGet(this, _DebugSession_listeners, "f")[event].push(listener);
|
|
2060
|
+
return this;
|
|
2061
|
+
}
|
|
2062
|
+
off(event, listener) {
|
|
2063
|
+
const arr = __classPrivateFieldGet(this, _DebugSession_listeners, "f")[event];
|
|
2064
|
+
const ix = arr.indexOf(listener);
|
|
2065
|
+
if (ix >= 0)
|
|
2066
|
+
arr.splice(ix, 1);
|
|
2067
|
+
return this;
|
|
2068
|
+
}
|
|
2069
|
+
stop() {
|
|
2070
|
+
__classPrivateFieldSet(this, _DebugSession_stopped, true, "f");
|
|
2071
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Request a pause from outside the run loop. The pause fires on the next
|
|
2075
|
+
* iter's before-side with `cause: 'manual'`. If a breakpoint matches that
|
|
2076
|
+
* same iter, the breakpoint takes precedence and the request is consumed
|
|
2077
|
+
* silently (one pause, cause: 'breakpoint').
|
|
2078
|
+
*
|
|
2079
|
+
* No-op if the session is already paused — the next `continue` / step call
|
|
2080
|
+
* resumes normal execution, then the flag fires on the iter AFTER that.
|
|
2081
|
+
* Equivalent to a debouncing one-shot.
|
|
2082
|
+
*/
|
|
2083
|
+
pause() {
|
|
2084
|
+
__classPrivateFieldSet(this, _DebugSession_pauseRequested, true, "f");
|
|
2085
|
+
}
|
|
2086
|
+
/**
|
|
2087
|
+
* Set the per-iter throttle delay in milliseconds. After each iter (including
|
|
2088
|
+
* any pause + step + iter listeners on that iter), the loop awaits
|
|
2089
|
+
* `setTimeout(ms)` before proceeding to the next iter. `0` disables the
|
|
2090
|
+
* throttle.
|
|
2091
|
+
*
|
|
2092
|
+
* Useful for visualization UIs that want to animate execution at a fixed
|
|
2093
|
+
* pace. Updates take effect on the next iter.
|
|
2094
|
+
*/
|
|
2095
|
+
setRunInterval(ms) {
|
|
2096
|
+
if (!Number.isFinite(ms) || ms < 0) {
|
|
2097
|
+
throw new Error(`DebugSession.setRunInterval(${ms}): expected a non-negative finite number.`);
|
|
2098
|
+
}
|
|
2099
|
+
__classPrivateFieldSet(this, _DebugSession_runIntervalMs, ms, "f");
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Resume from the current pause, returning to normal execution until the
|
|
2103
|
+
* next breakpoint or natural halt. No-op when called outside of a paused
|
|
2104
|
+
* state.
|
|
2105
|
+
*/
|
|
2106
|
+
continue() {
|
|
2107
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, null, "f");
|
|
2108
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* Resume and force a pause on the next iter regardless of whether that
|
|
2112
|
+
* iter's `state.debug` filter matches. Step-mode is one-shot: any
|
|
2113
|
+
* subsequent pause dispatch (this step-in's endpoint, an inner
|
|
2114
|
+
* breakpoint, or a manual pause) drops it. To keep stepping, call
|
|
2115
|
+
* stepIn() again from the new pause.
|
|
2116
|
+
*/
|
|
2117
|
+
stepIn() {
|
|
2118
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-in', "f");
|
|
2119
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2120
|
+
}
|
|
2121
|
+
/**
|
|
2122
|
+
* Resume and pause at the next iter back at (or above) the click-time depth
|
|
2123
|
+
* — i.e. `depth <= clickTimeDepth`. Frames the stepped-over iter pushes are
|
|
2124
|
+
* run to completion without pausing inside (the engine's continuation-passing
|
|
2125
|
+
* `withOverriddenHaltState` "calls"). Mirrors DevTools Step Over.
|
|
2126
|
+
*
|
|
2127
|
+
* For a plain iter (no frame push) this coincides with stepIn (next iter is
|
|
2128
|
+
* already at the same depth). The Over-vs-In / Over-vs-Out distinction only
|
|
2129
|
+
* appears under genuine nesting (a bare that itself enters a wrapper).
|
|
2130
|
+
*
|
|
2131
|
+
* One-shot: an inner breakpoint or any other pause drops the step-over
|
|
2132
|
+
* intent. The endpoint pause carries `cause: 'step'`.
|
|
2133
|
+
*/
|
|
2134
|
+
stepOver() {
|
|
2135
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-over', "f");
|
|
2136
|
+
__classPrivateFieldSet(this, _DebugSession_clickTimeDepth, __classPrivateFieldGet(this, _DebugSession_capturedDepth, "f"), "f");
|
|
2137
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2138
|
+
}
|
|
2139
|
+
/**
|
|
2140
|
+
* Resume and pause at the next iter STRICTLY shallower than the click-time
|
|
2141
|
+
* depth — `depth < clickTimeDepth` — i.e. once the current frame itself has
|
|
2142
|
+
* been popped. Mirrors DevTools Step Out.
|
|
2143
|
+
*
|
|
2144
|
+
* Throws when the click-time depth is 0: there's no enclosing frame to exit
|
|
2145
|
+
* (IDE convention — "step out of nothing" is a programming error, not a
|
|
2146
|
+
* silent no-op).
|
|
2147
|
+
*/
|
|
2148
|
+
stepOut() {
|
|
2149
|
+
if (__classPrivateFieldGet(this, _DebugSession_capturedDepth, "f") === 0) {
|
|
2150
|
+
throw new Error('DebugSession.stepOut() called with an empty click-time halt-stack — there is no enclosing frame to exit.');
|
|
2151
|
+
}
|
|
2152
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-out', "f");
|
|
2153
|
+
__classPrivateFieldSet(this, _DebugSession_clickTimeDepth, __classPrivateFieldGet(this, _DebugSession_capturedDepth, "f"), "f");
|
|
2154
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2155
|
+
}
|
|
2156
|
+
async start() {
|
|
2157
|
+
if (__classPrivateFieldGet(this, _DebugSession_started, "f")) {
|
|
2158
|
+
throw new Error('DebugSession.start() has already been called; construct a fresh session to re-run.');
|
|
2159
|
+
}
|
|
2160
|
+
__classPrivateFieldSet(this, _DebugSession_started, true, "f");
|
|
2161
|
+
try {
|
|
2162
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_drive).call(this);
|
|
2163
|
+
}
|
|
2164
|
+
catch (error) {
|
|
2165
|
+
// `runStepByStep` acquires the TapeBlock lock at its first advance. If
|
|
2166
|
+
// another DebugSession (or a bare `run()`) is already active on this
|
|
2167
|
+
// machine, that acquisition throws the low-level 'Lock check failed'.
|
|
2168
|
+
// Remap it to a message that names the real cause. The `#iterating`
|
|
2169
|
+
// guard scopes the remap to the startup acquisition only — once we hold
|
|
2170
|
+
// the lock and are iterating, a same-named error can't originate here.
|
|
2171
|
+
if (!__classPrivateFieldGet(this, _DebugSession_iterating, "f") && error instanceof Error && error.message === 'Lock check failed') {
|
|
2172
|
+
throw new Error('Cannot start this DebugSession: a run is already in progress on this machine. '
|
|
2173
|
+
+ 'Only one DebugSession or run() may be active on a TuringMachine at a time — '
|
|
2174
|
+
+ 'stop the active session (or let it halt) before starting another.');
|
|
2175
|
+
}
|
|
2176
|
+
throw error;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
_DebugSession_machine = new WeakMap(), _DebugSession_parameter = new WeakMap(), _DebugSession_listeners = new WeakMap(), _DebugSession_started = new WeakMap(), _DebugSession_stopped = new WeakMap(), _DebugSession_iterating = new WeakMap(), _DebugSession_pauseResolver = new WeakMap(), _DebugSession_activeStepMode = new WeakMap(), _DebugSession_capturedDepth = new WeakMap(), _DebugSession_clickTimeDepth = new WeakMap(), _DebugSession_runIntervalMs = new WeakMap(), _DebugSession_pauseRequested = new WeakMap(), _DebugSession_instances = new WeakSet(), _DebugSession_releasePause = function _DebugSession_releasePause() {
|
|
2181
|
+
const resolver = __classPrivateFieldGet(this, _DebugSession_pauseResolver, "f");
|
|
2182
|
+
if (resolver) {
|
|
2183
|
+
__classPrivateFieldSet(this, _DebugSession_pauseResolver, null, "f");
|
|
2184
|
+
resolver();
|
|
2185
|
+
}
|
|
2186
|
+
}, _DebugSession_dispatchPause =
|
|
2187
|
+
/**
|
|
2188
|
+
* Emit a `pause` event with the synthesized pause descriptor and await the
|
|
2189
|
+
* consumer's resume signal. Resolver is installed BEFORE listeners fire so a listener
|
|
2190
|
+
* that synchronously calls `session.continue()` (or any other resume method)
|
|
2191
|
+
* sees a live resolver to drop.
|
|
2192
|
+
*
|
|
2193
|
+
* One-shot rule: any pause dispatch (step-mode endpoint, inner breakpoint,
|
|
2194
|
+
* manual pause) drops the active step-mode BEFORE listeners fire. Listeners
|
|
2195
|
+
* that want to keep stepping must call stepIn/Over/Out from the new pause.
|
|
2196
|
+
*
|
|
2197
|
+
* The pre-iter halt-stack DEPTH is snapshotted into `#capturedDepth` so a
|
|
2198
|
+
* `stepOver` / `stepOut` issued from inside the listener can freeze it as
|
|
2199
|
+
* the click-time depth.
|
|
2200
|
+
*/
|
|
2201
|
+
async function _DebugSession_dispatchPause(machineState, pause) {
|
|
2202
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, null, "f");
|
|
2203
|
+
__classPrivateFieldSet(this, _DebugSession_capturedDepth, __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readStack).call(this, machineState).length, "f");
|
|
2204
|
+
// Note: the spread drops the non-enumerable MACHINE_STATE_INTERNAL Symbol
|
|
2205
|
+
// accessor — that's intentional. Pause listeners are public API; the
|
|
2206
|
+
// Symbol accessor is package-private and only consumed by the session's
|
|
2207
|
+
// OWN detection (which reads the original `machineState` via #readInternal).
|
|
2208
|
+
const paused = { ...machineState, pause };
|
|
2209
|
+
const pausePromise = new Promise((resolve) => {
|
|
2210
|
+
__classPrivateFieldSet(this, _DebugSession_pauseResolver, resolve, "f");
|
|
2211
|
+
});
|
|
2212
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").pause) {
|
|
2213
|
+
void fn(paused);
|
|
2214
|
+
}
|
|
2215
|
+
await pausePromise;
|
|
2216
|
+
}, _DebugSession_readInternal = function _DebugSession_readInternal(machineState) {
|
|
2217
|
+
const fn = machineState[MACHINE_STATE_INTERNAL];
|
|
2218
|
+
return typeof fn === 'function' ? fn() : null;
|
|
2219
|
+
}, _DebugSession_readStack = function _DebugSession_readStack(machineState) {
|
|
2220
|
+
return __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readInternal).call(this, machineState)?.stack ?? [];
|
|
2221
|
+
}, _DebugSession_drive = async function _DebugSession_drive() {
|
|
2222
|
+
for (const machineState of __classPrivateFieldGet(this, _DebugSession_machine, "f").runStepByStep(__classPrivateFieldGet(this, _DebugSession_parameter, "f"))) {
|
|
2223
|
+
__classPrivateFieldSet(this, _DebugSession_iterating, true, "f");
|
|
2224
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2225
|
+
return;
|
|
2226
|
+
// Breakpoint detection lives HERE (not in the generator). Evaluate the
|
|
2227
|
+
// current state's debug filters against the matched symbol the generator
|
|
2228
|
+
// stashed in the internal accessor. `machineState.state` is always
|
|
2229
|
+
// non-halt (halt is terminal), so `.debug` is a DebugConfig at runtime.
|
|
2230
|
+
// The after side also fires on halt-imminent (`haltState.debug`, #207) —
|
|
2231
|
+
// read via the internal flag, since the yielded `nextState` shows the
|
|
2232
|
+
// post-pop continuation on subroutine-return iters, not haltState.
|
|
2233
|
+
const internal = __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readInternal).call(this, machineState);
|
|
2234
|
+
const matchedSymbol = internal?.matchedSymbol;
|
|
2235
|
+
const hasBeforeBreakpoint = matchedSymbol !== undefined
|
|
2236
|
+
&& matchFilter(machineState.state.debug?.before, matchedSymbol);
|
|
2237
|
+
const hasAfterBreakpoint = (matchedSymbol !== undefined
|
|
2238
|
+
&& matchFilter(machineState.state.debug?.after, matchedSymbol))
|
|
2239
|
+
|| (internal?.haltImminent === true && haltState.debug === true);
|
|
2240
|
+
const stepInForcesPause = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-in';
|
|
2241
|
+
// Depth-based endpoints (DevTools semantics). currentDepth = pre-iter
|
|
2242
|
+
// halt-stack length. stepOver: back at/above click-time depth (skip
|
|
2243
|
+
// pushed frames). stepOut: strictly shallower (current frame exited).
|
|
2244
|
+
const currentDepth = __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readStack).call(this, machineState).length;
|
|
2245
|
+
const stepOverEndpointReached = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-over' && currentDepth <= __classPrivateFieldGet(this, _DebugSession_clickTimeDepth, "f");
|
|
2246
|
+
const stepOutEndpointReached = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-out' && currentDepth < __classPrivateFieldGet(this, _DebugSession_clickTimeDepth, "f");
|
|
2247
|
+
// Consume the manual-pause flag at iter start. If a breakpoint also
|
|
2248
|
+
// matches this iter, the request is silently consumed by the
|
|
2249
|
+
// breakpoint dispatch (one pause, cause: 'breakpoint').
|
|
2250
|
+
const manualPauseFires = __classPrivateFieldGet(this, _DebugSession_pauseRequested, "f");
|
|
2251
|
+
if (manualPauseFires)
|
|
2252
|
+
__classPrivateFieldSet(this, _DebugSession_pauseRequested, false, "f");
|
|
2253
|
+
// Before-side pause: fires if any of breakpoint / step-mode endpoint /
|
|
2254
|
+
// manual request is true. Precedence: breakpoint > step > manual.
|
|
2255
|
+
const fireBeforePause = hasBeforeBreakpoint || stepInForcesPause || stepOverEndpointReached || stepOutEndpointReached || manualPauseFires;
|
|
2256
|
+
if (fireBeforePause) {
|
|
2257
|
+
const cause = hasBeforeBreakpoint ? 'breakpoint'
|
|
2258
|
+
: (stepInForcesPause || stepOverEndpointReached || stepOutEndpointReached) ? 'step'
|
|
2259
|
+
: 'manual';
|
|
2260
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_dispatchPause).call(this, machineState, { side: 'before', cause });
|
|
2261
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2262
|
+
return;
|
|
2263
|
+
}
|
|
2264
|
+
// step: fires once per iter, after any before-pause and before any after-pause.
|
|
2265
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").step) {
|
|
2266
|
+
void fn(machineState);
|
|
2267
|
+
}
|
|
2268
|
+
if (hasAfterBreakpoint) {
|
|
2269
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_dispatchPause).call(this, machineState, { side: 'after', cause: 'breakpoint' });
|
|
2270
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
// iter: end-of-iter, after both before- and after-pause have fired.
|
|
2274
|
+
// Listeners are AWAITED (sequenced, blocking the engine) — matches the
|
|
2275
|
+
// v6 `onIter` contract that downstream consumers rely on for
|
|
2276
|
+
// throttle / per-iter coordination / step-boundary synthesis.
|
|
2277
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").iter) {
|
|
2278
|
+
await fn(machineState);
|
|
2279
|
+
}
|
|
2280
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2281
|
+
return;
|
|
2282
|
+
if (__classPrivateFieldGet(this, _DebugSession_runIntervalMs, "f") > 0) {
|
|
2283
|
+
await new Promise((resolve) => setTimeout(resolve, __classPrivateFieldGet(this, _DebugSession_runIntervalMs, "f")));
|
|
2284
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2285
|
+
return;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
if (!__classPrivateFieldGet(this, _DebugSession_stopped, "f")) {
|
|
2289
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").halt) {
|
|
2290
|
+
void fn();
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
};
|
|
2294
|
+
|
|
1897
2295
|
// Format converters between a Graph (the data model produced by State.toGraph
|
|
1898
2296
|
// and consumed by State.fromGraph) and external string representations.
|
|
1899
2297
|
//
|
|
@@ -2021,14 +2419,20 @@ function toMermaid(graph) {
|
|
|
2021
2419
|
const nodes = Object.values(graph.nodes).slice().sort((a, b) => a.id - b.id);
|
|
2022
2420
|
// Bucket nodes for emit order.
|
|
2023
2421
|
const topLevelNodes = nodes.filter((n) => n.frameId === null && !n.isWrapper);
|
|
2422
|
+
// All wrappers — needed by the call / return / wrapper-to-override
|
|
2423
|
+
// arrow emit passes below regardless of where the wrapper renders.
|
|
2024
2424
|
const wrapperNodes = nodes.filter((n) => n.isWrapper);
|
|
2025
|
-
//
|
|
2425
|
+
// Top-level wrappers: wrappers whose caller has no frame (the caller is
|
|
2426
|
+
// the top-level program). Framed wrappers (whose caller IS a subroutine
|
|
2427
|
+
// with its own frame) render INSIDE that frame's subgraph below.
|
|
2428
|
+
const topLevelWrapperNodes = wrapperNodes.filter((w) => w.frameId === null);
|
|
2429
|
+
// Bares-bodies-and-framed-wrappers inside frames, grouped by frameId.
|
|
2026
2430
|
const nodesByFrame = new Map();
|
|
2027
2431
|
// Halt-marker per frame (kept separate so it always emits LAST inside the
|
|
2028
2432
|
// subgraph for deterministic shape).
|
|
2029
2433
|
const haltMarkerByFrame = new Map();
|
|
2030
2434
|
for (const node of nodes) {
|
|
2031
|
-
if (node.frameId === null
|
|
2435
|
+
if (node.frameId === null)
|
|
2032
2436
|
continue;
|
|
2033
2437
|
if (node.isHaltMarker) {
|
|
2034
2438
|
haltMarkerByFrame.set(node.frameId, node);
|
|
@@ -2071,8 +2475,9 @@ function toMermaid(graph) {
|
|
|
2071
2475
|
lines.push(` ${mid}["${labelOf(node)}"]`);
|
|
2072
2476
|
}
|
|
2073
2477
|
}
|
|
2074
|
-
// 2. Emit wrappers
|
|
2075
|
-
|
|
2478
|
+
// 2. Emit top-level wrappers (wrappers owned by the top-level program;
|
|
2479
|
+
// wrappers owned by a subroutine emit inside that subroutine's subgraph).
|
|
2480
|
+
for (const wrapper of topLevelWrapperNodes) {
|
|
2076
2481
|
lines.push(` ${mermaidIdFor(wrapper.id)}[["${labelOf(wrapper)}"]]`);
|
|
2077
2482
|
}
|
|
2078
2483
|
// 3. `idle` sentinel.
|
|
@@ -2089,9 +2494,16 @@ function toMermaid(graph) {
|
|
|
2089
2494
|
? `callable scope: ${frameBareNames.join(' ∪ ')}`
|
|
2090
2495
|
: `callable subtree of ${frameBareNames[0] ?? frameId}`;
|
|
2091
2496
|
lines.push(` subgraph ${frameSubgraphId(frameId)}["${label}"]`);
|
|
2092
|
-
// Inner nodes — sort by id for determinism.
|
|
2497
|
+
// Inner nodes — sort by id for determinism. Framed wrappers (call sites
|
|
2498
|
+
// owned by this frame) render with the `[[name]]` wrapper shape; bares
|
|
2499
|
+
// and body states render with the regular `["name"]` shape.
|
|
2093
2500
|
for (const node of (nodesByFrame.get(frameId) ?? []).slice().sort((a, b) => a.id - b.id)) {
|
|
2094
|
-
|
|
2501
|
+
if (node.isWrapper) {
|
|
2502
|
+
lines.push(` ${mermaidIdFor(node.id)}[["${labelOf(node)}"]]`);
|
|
2503
|
+
}
|
|
2504
|
+
else {
|
|
2505
|
+
lines.push(` ${mermaidIdFor(node.id)}["${labelOf(node)}"]`);
|
|
2506
|
+
}
|
|
2095
2507
|
}
|
|
2096
2508
|
// Every frame has a halt marker — `State.toGraph`'s frame-emit pass
|
|
2097
2509
|
// creates one for each frame. Non-null assertion is safe; a defensive
|
|
@@ -2609,10 +3021,10 @@ function summarizeGraph(graph) {
|
|
|
2609
3021
|
}
|
|
2610
3022
|
let hasCycles = false;
|
|
2611
3023
|
const visit = (id) => {
|
|
2612
|
-
// No `if (hasCycles) return` guard at function entry: the
|
|
2613
|
-
//
|
|
2614
|
-
//
|
|
2615
|
-
//
|
|
3024
|
+
// No `if (hasCycles) return` guard at function entry: the call pattern
|
|
3025
|
+
// (outer for-loop checks before calling, inner loop checks after each
|
|
3026
|
+
// recursive call) ensures visit() is never invoked when hasCycles is
|
|
3027
|
+
// already true.
|
|
2616
3028
|
if (color.get(id) === GREY) {
|
|
2617
3029
|
hasCycles = true;
|
|
2618
3030
|
return;
|
|
@@ -2729,8 +3141,10 @@ function runOnce(runnable, input, stepsLimit) {
|
|
|
2729
3141
|
}
|
|
2730
3142
|
|
|
2731
3143
|
exports.Alphabet = Alphabet;
|
|
3144
|
+
exports.CallFrame = CallFrame;
|
|
2732
3145
|
exports.Command = Command;
|
|
2733
3146
|
exports.DebugConfig = DebugConfig;
|
|
3147
|
+
exports.DebugSession = DebugSession;
|
|
2734
3148
|
exports.Reference = Reference;
|
|
2735
3149
|
exports.State = State;
|
|
2736
3150
|
exports.Tape = Tape;
|