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