@turing-machine-js/machine 7.0.0-alpha.4 → 7.0.0-alpha.6
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 +60 -0
- package/README.md +172 -50
- package/dist/classes/DebugSession.d.ts +119 -0
- package/dist/classes/State.d.ts +46 -2
- package/dist/classes/TapeBlock.d.ts +25 -0
- package/dist/classes/TuringMachine.d.ts +105 -67
- package/dist/index.cjs +710 -255
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +710 -256
- package/dist/utilities/stateGraph.d.ts +3 -2
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -13,13 +13,13 @@ function id(object) {
|
|
|
13
13
|
id[idKey] = 0;
|
|
14
14
|
id[idWeakMapKey] = new WeakMap();
|
|
15
15
|
|
|
16
|
-
var __classPrivateFieldSet$
|
|
16
|
+
var __classPrivateFieldSet$9 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
17
17
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
18
18
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
19
19
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
20
20
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
21
21
|
};
|
|
22
|
-
var __classPrivateFieldGet$
|
|
22
|
+
var __classPrivateFieldGet$9 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
23
23
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
24
24
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
25
25
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -39,36 +39,36 @@ class Alphabet {
|
|
|
39
39
|
if (!isSymbolsValid) {
|
|
40
40
|
throw new Error('symbols contains invalid symbol');
|
|
41
41
|
}
|
|
42
|
-
__classPrivateFieldSet$
|
|
42
|
+
__classPrivateFieldSet$9(this, _Alphabet_symbols, Array.from(uniqueSymbols), "f");
|
|
43
43
|
}
|
|
44
44
|
get symbols() {
|
|
45
|
-
return Array.from(__classPrivateFieldGet$
|
|
45
|
+
return Array.from(__classPrivateFieldGet$9(this, _Alphabet_symbols, "f"));
|
|
46
46
|
}
|
|
47
47
|
get blankSymbol() {
|
|
48
|
-
return __classPrivateFieldGet$
|
|
48
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f")[0];
|
|
49
49
|
}
|
|
50
50
|
has(symbol) {
|
|
51
|
-
return __classPrivateFieldGet$
|
|
51
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").indexOf(symbol) >= 0;
|
|
52
52
|
}
|
|
53
53
|
get(index) {
|
|
54
|
-
if (index < 0 || index >= __classPrivateFieldGet$
|
|
54
|
+
if (index < 0 || index >= __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").length) {
|
|
55
55
|
throw new Error('Invalid index');
|
|
56
56
|
}
|
|
57
|
-
return __classPrivateFieldGet$
|
|
57
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f")[index];
|
|
58
58
|
}
|
|
59
59
|
index(symbol) {
|
|
60
|
-
return __classPrivateFieldGet$
|
|
60
|
+
return __classPrivateFieldGet$9(this, _Alphabet_symbols, "f").indexOf(symbol);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
_Alphabet_symbols = new WeakMap();
|
|
64
64
|
|
|
65
|
-
var __classPrivateFieldSet$
|
|
65
|
+
var __classPrivateFieldSet$8 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
66
66
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
67
67
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
68
68
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
69
69
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
70
70
|
};
|
|
71
|
-
var __classPrivateFieldGet$
|
|
71
|
+
var __classPrivateFieldGet$8 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
72
72
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
73
73
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
74
74
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -91,30 +91,30 @@ class TapeCommand {
|
|
|
91
91
|
if (!isValidMovement) {
|
|
92
92
|
throw new Error('invalid movement');
|
|
93
93
|
}
|
|
94
|
-
__classPrivateFieldSet$
|
|
94
|
+
__classPrivateFieldSet$8(this, _TapeCommand_movement, movement, "f");
|
|
95
95
|
const isValidSymbol = ((typeof symbol === 'string' && symbol.length === 1)
|
|
96
96
|
|| [symbolCommands.keep, symbolCommands.erase].includes(symbol));
|
|
97
97
|
if (!isValidSymbol) {
|
|
98
98
|
throw new Error('invalid symbol');
|
|
99
99
|
}
|
|
100
|
-
__classPrivateFieldSet$
|
|
100
|
+
__classPrivateFieldSet$8(this, _TapeCommand_symbol, symbol, "f");
|
|
101
101
|
}
|
|
102
102
|
get symbol() {
|
|
103
|
-
return __classPrivateFieldGet$
|
|
103
|
+
return __classPrivateFieldGet$8(this, _TapeCommand_symbol, "f");
|
|
104
104
|
}
|
|
105
105
|
get movement() {
|
|
106
|
-
return __classPrivateFieldGet$
|
|
106
|
+
return __classPrivateFieldGet$8(this, _TapeCommand_movement, "f");
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
_TapeCommand_movement = new WeakMap(), _TapeCommand_symbol = new WeakMap();
|
|
110
110
|
|
|
111
|
-
var __classPrivateFieldSet$
|
|
111
|
+
var __classPrivateFieldSet$7 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
112
112
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
113
113
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
114
114
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
115
115
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
116
116
|
};
|
|
117
|
-
var __classPrivateFieldGet$
|
|
117
|
+
var __classPrivateFieldGet$7 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
118
118
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
119
119
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
120
120
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -127,7 +127,7 @@ class Command {
|
|
|
127
127
|
throw new Error('invalid parameter');
|
|
128
128
|
}
|
|
129
129
|
try {
|
|
130
|
-
__classPrivateFieldSet$
|
|
130
|
+
__classPrivateFieldSet$7(this, _Command_tapesCommands, tapesCommands.map((tapeCommand) => {
|
|
131
131
|
if (tapeCommand instanceof TapeCommand) {
|
|
132
132
|
return tapeCommand;
|
|
133
133
|
}
|
|
@@ -139,17 +139,17 @@ class Command {
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
get tapesCommands() {
|
|
142
|
-
return [...__classPrivateFieldGet$
|
|
142
|
+
return [...__classPrivateFieldGet$7(this, _Command_tapesCommands, "f")];
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
_Command_tapesCommands = new WeakMap();
|
|
146
146
|
|
|
147
|
-
var __classPrivateFieldGet$
|
|
147
|
+
var __classPrivateFieldGet$6 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
148
148
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
149
149
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
150
150
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
151
151
|
};
|
|
152
|
-
var __classPrivateFieldSet$
|
|
152
|
+
var __classPrivateFieldSet$6 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
153
153
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
154
154
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
155
155
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
@@ -161,16 +161,16 @@ class Reference {
|
|
|
161
161
|
_Reference_referenceBinding.set(this, null);
|
|
162
162
|
}
|
|
163
163
|
get ref() {
|
|
164
|
-
if (!__classPrivateFieldGet$
|
|
164
|
+
if (!__classPrivateFieldGet$6(this, _Reference_referenceBinding, "f")) {
|
|
165
165
|
throw new Error('unbounded reference');
|
|
166
166
|
}
|
|
167
|
-
return __classPrivateFieldGet$
|
|
167
|
+
return __classPrivateFieldGet$6(this, _Reference_referenceBinding, "f");
|
|
168
168
|
}
|
|
169
169
|
bind(state) {
|
|
170
|
-
if (__classPrivateFieldGet$
|
|
171
|
-
__classPrivateFieldSet$
|
|
170
|
+
if (__classPrivateFieldGet$6(this, _Reference_referenceBinding, "f") == null) {
|
|
171
|
+
__classPrivateFieldSet$6(this, _Reference_referenceBinding, state, "f");
|
|
172
172
|
}
|
|
173
|
-
return __classPrivateFieldGet$
|
|
173
|
+
return __classPrivateFieldGet$6(this, _Reference_referenceBinding, "f");
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
_Reference_referenceBinding = new WeakMap();
|
|
@@ -322,13 +322,13 @@ function decodeWriteSymbol(symbol) {
|
|
|
322
322
|
}
|
|
323
323
|
// Format converters (toMermaid / fromMermaid) live in ./graphFormats.
|
|
324
324
|
|
|
325
|
-
var __classPrivateFieldSet$
|
|
325
|
+
var __classPrivateFieldSet$5 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
326
326
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
327
327
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
328
328
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
329
329
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
330
330
|
};
|
|
331
|
-
var __classPrivateFieldGet$
|
|
331
|
+
var __classPrivateFieldGet$5 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
332
332
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
333
333
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
334
334
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -349,65 +349,65 @@ class Tape {
|
|
|
349
349
|
if (!isSymbolsValid) {
|
|
350
350
|
throw new Error('symbolList contains invalid symbol');
|
|
351
351
|
}
|
|
352
|
-
__classPrivateFieldSet$
|
|
353
|
-
__classPrivateFieldSet$
|
|
354
|
-
__classPrivateFieldSet$
|
|
355
|
-
const initialSymbols = symbols.length === 0 ? [__classPrivateFieldGet$
|
|
352
|
+
__classPrivateFieldSet$5(this, _Tape_alphabet, new Alphabet(alphabet), "f");
|
|
353
|
+
__classPrivateFieldSet$5(this, _Tape_position, position, "f");
|
|
354
|
+
__classPrivateFieldSet$5(this, _Tape_viewportWidth, 1, "f");
|
|
355
|
+
const initialSymbols = symbols.length === 0 ? [__classPrivateFieldGet$5(this, _Tape_alphabet, "f").blankSymbol] : symbols;
|
|
356
356
|
for (const symbol of initialSymbols) {
|
|
357
|
-
__classPrivateFieldGet$
|
|
357
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f").push(__classPrivateFieldGet$5(this, _Tape_alphabet, "f").index(symbol));
|
|
358
358
|
}
|
|
359
359
|
this.viewportWidth = viewportWidth;
|
|
360
360
|
}
|
|
361
361
|
get alphabet() {
|
|
362
|
-
return __classPrivateFieldGet$
|
|
362
|
+
return __classPrivateFieldGet$5(this, _Tape_alphabet, "f");
|
|
363
363
|
}
|
|
364
364
|
get extraCellsCount() {
|
|
365
|
-
return (__classPrivateFieldGet$
|
|
365
|
+
return (__classPrivateFieldGet$5(this, _Tape_viewportWidth, "f") - 1) / 2;
|
|
366
366
|
}
|
|
367
367
|
get position() {
|
|
368
368
|
// Public contract: index of the head in the `symbols` array. With the
|
|
369
369
|
// two-array deque, `#position` is the head's logical position; adding
|
|
370
370
|
// `#left.length` shifts it back into "index from the leftmost backed cell".
|
|
371
|
-
return __classPrivateFieldGet$
|
|
371
|
+
return __classPrivateFieldGet$5(this, _Tape_position, "f") + __classPrivateFieldGet$5(this, _Tape_left, "f").length;
|
|
372
372
|
}
|
|
373
373
|
get symbol() {
|
|
374
|
-
return __classPrivateFieldGet$
|
|
374
|
+
return __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_instances, "m", _Tape_cellAt).call(this, __classPrivateFieldGet$5(this, _Tape_position, "f")));
|
|
375
375
|
}
|
|
376
376
|
set symbol(symbol) {
|
|
377
|
-
if (!__classPrivateFieldGet$
|
|
377
|
+
if (!__classPrivateFieldGet$5(this, _Tape_alphabet, "f").has(symbol)) {
|
|
378
378
|
throw new Error('Invalid symbol');
|
|
379
379
|
}
|
|
380
|
-
const index = __classPrivateFieldGet$
|
|
381
|
-
if (__classPrivateFieldGet$
|
|
382
|
-
__classPrivateFieldGet$
|
|
380
|
+
const index = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").index(symbol);
|
|
381
|
+
if (__classPrivateFieldGet$5(this, _Tape_position, "f") >= 0) {
|
|
382
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f")[__classPrivateFieldGet$5(this, _Tape_position, "f")] = index;
|
|
383
383
|
}
|
|
384
384
|
else {
|
|
385
|
-
__classPrivateFieldGet$
|
|
385
|
+
__classPrivateFieldGet$5(this, _Tape_left, "f")[-__classPrivateFieldGet$5(this, _Tape_position, "f") - 1] = index;
|
|
386
386
|
}
|
|
387
|
-
__classPrivateFieldSet$
|
|
387
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
388
388
|
}
|
|
389
389
|
get symbols() {
|
|
390
|
-
const result = new Array(__classPrivateFieldGet$
|
|
391
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
392
|
-
result[i] = __classPrivateFieldGet$
|
|
390
|
+
const result = new Array(__classPrivateFieldGet$5(this, _Tape_left, "f").length + __classPrivateFieldGet$5(this, _Tape_right, "f").length);
|
|
391
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_left, "f").length; i += 1) {
|
|
392
|
+
result[i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_left, "f")[__classPrivateFieldGet$5(this, _Tape_left, "f").length - 1 - i]);
|
|
393
393
|
}
|
|
394
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
395
|
-
result[__classPrivateFieldGet$
|
|
394
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_right, "f").length; i += 1) {
|
|
395
|
+
result[__classPrivateFieldGet$5(this, _Tape_left, "f").length + i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_right, "f")[i]);
|
|
396
396
|
}
|
|
397
397
|
return result;
|
|
398
398
|
}
|
|
399
399
|
get viewport() {
|
|
400
|
-
if (__classPrivateFieldGet$
|
|
401
|
-
const start = __classPrivateFieldGet$
|
|
402
|
-
for (let i = 0; i < __classPrivateFieldGet$
|
|
403
|
-
__classPrivateFieldGet$
|
|
400
|
+
if (__classPrivateFieldGet$5(this, _Tape_viewportDirty, "f")) {
|
|
401
|
+
const start = __classPrivateFieldGet$5(this, _Tape_position, "f") - this.extraCellsCount;
|
|
402
|
+
for (let i = 0; i < __classPrivateFieldGet$5(this, _Tape_viewportWidth, "f"); i += 1) {
|
|
403
|
+
__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f")[i] = __classPrivateFieldGet$5(this, _Tape_alphabet, "f").get(__classPrivateFieldGet$5(this, _Tape_instances, "m", _Tape_cellAt).call(this, start + i));
|
|
404
404
|
}
|
|
405
|
-
__classPrivateFieldSet$
|
|
405
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, false, "f");
|
|
406
406
|
}
|
|
407
|
-
return [...__classPrivateFieldGet$
|
|
407
|
+
return [...__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f")];
|
|
408
408
|
}
|
|
409
409
|
get viewportWidth() {
|
|
410
|
-
return __classPrivateFieldGet$
|
|
410
|
+
return __classPrivateFieldGet$5(this, _Tape_viewportWidth, "f");
|
|
411
411
|
}
|
|
412
412
|
set viewportWidth(width) {
|
|
413
413
|
let finalWidth = width;
|
|
@@ -417,46 +417,46 @@ class Tape {
|
|
|
417
417
|
if (finalWidth % 2 === 0) {
|
|
418
418
|
finalWidth += 1;
|
|
419
419
|
}
|
|
420
|
-
__classPrivateFieldSet$
|
|
421
|
-
__classPrivateFieldGet$
|
|
422
|
-
__classPrivateFieldSet$
|
|
420
|
+
__classPrivateFieldSet$5(this, _Tape_viewportWidth, finalWidth, "f");
|
|
421
|
+
__classPrivateFieldGet$5(this, _Tape_viewportBuffer, "f").length = finalWidth;
|
|
422
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
423
423
|
this.normalise();
|
|
424
424
|
}
|
|
425
425
|
left() {
|
|
426
|
-
__classPrivateFieldSet$
|
|
426
|
+
__classPrivateFieldSet$5(this, _Tape_position, __classPrivateFieldGet$5(this, _Tape_position, "f") - 1, "f");
|
|
427
427
|
this.normalise();
|
|
428
|
-
__classPrivateFieldSet$
|
|
428
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
429
429
|
}
|
|
430
430
|
normalise() {
|
|
431
|
-
const minLogical = __classPrivateFieldGet$
|
|
432
|
-
const maxLogical = __classPrivateFieldGet$
|
|
433
|
-
while (-__classPrivateFieldGet$
|
|
434
|
-
__classPrivateFieldGet$
|
|
431
|
+
const minLogical = __classPrivateFieldGet$5(this, _Tape_position, "f") - this.extraCellsCount;
|
|
432
|
+
const maxLogical = __classPrivateFieldGet$5(this, _Tape_position, "f") + this.extraCellsCount;
|
|
433
|
+
while (-__classPrivateFieldGet$5(this, _Tape_left, "f").length > minLogical) {
|
|
434
|
+
__classPrivateFieldGet$5(this, _Tape_left, "f").push(BLANK_INDEX);
|
|
435
435
|
}
|
|
436
|
-
while (__classPrivateFieldGet$
|
|
437
|
-
__classPrivateFieldGet$
|
|
436
|
+
while (__classPrivateFieldGet$5(this, _Tape_right, "f").length - 1 < maxLogical) {
|
|
437
|
+
__classPrivateFieldGet$5(this, _Tape_right, "f").push(BLANK_INDEX);
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
right() {
|
|
441
|
-
__classPrivateFieldSet$
|
|
441
|
+
__classPrivateFieldSet$5(this, _Tape_position, __classPrivateFieldGet$5(this, _Tape_position, "f") + 1, "f");
|
|
442
442
|
this.normalise();
|
|
443
|
-
__classPrivateFieldSet$
|
|
443
|
+
__classPrivateFieldSet$5(this, _Tape_viewportDirty, true, "f");
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
446
|
_Tape_alphabet = new WeakMap(), _Tape_right = new WeakMap(), _Tape_left = new WeakMap(), _Tape_position = new WeakMap(), _Tape_viewportWidth = new WeakMap(), _Tape_viewportBuffer = new WeakMap(), _Tape_viewportDirty = new WeakMap(), _Tape_instances = new WeakSet(), _Tape_cellAt = function _Tape_cellAt(logical) {
|
|
447
447
|
if (logical >= 0) {
|
|
448
|
-
return logical < __classPrivateFieldGet$
|
|
448
|
+
return logical < __classPrivateFieldGet$5(this, _Tape_right, "f").length ? __classPrivateFieldGet$5(this, _Tape_right, "f")[logical] : BLANK_INDEX;
|
|
449
449
|
}
|
|
450
450
|
const ix = -logical - 1;
|
|
451
|
-
return ix < __classPrivateFieldGet$
|
|
451
|
+
return ix < __classPrivateFieldGet$5(this, _Tape_left, "f").length ? __classPrivateFieldGet$5(this, _Tape_left, "f")[ix] : BLANK_INDEX;
|
|
452
452
|
};
|
|
453
453
|
|
|
454
|
-
var __classPrivateFieldGet$
|
|
454
|
+
var __classPrivateFieldGet$4 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
455
455
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
456
456
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
457
457
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
458
458
|
};
|
|
459
|
-
var __classPrivateFieldSet$
|
|
459
|
+
var __classPrivateFieldSet$4 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
460
460
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
461
461
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
462
462
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
@@ -468,30 +468,30 @@ class Lock {
|
|
|
468
468
|
_Lock_lockSymbol.set(this, null);
|
|
469
469
|
}
|
|
470
470
|
lock(symbol) {
|
|
471
|
-
if (__classPrivateFieldGet$
|
|
472
|
-
__classPrivateFieldSet$
|
|
471
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") === null) {
|
|
472
|
+
__classPrivateFieldSet$4(this, _Lock_lockSymbol, symbol, "f");
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
unlock(symbol) {
|
|
476
|
-
if (__classPrivateFieldGet$
|
|
477
|
-
__classPrivateFieldSet$
|
|
476
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") === symbol) {
|
|
477
|
+
__classPrivateFieldSet$4(this, _Lock_lockSymbol, null, "f");
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
check(symbol) {
|
|
481
|
-
if (__classPrivateFieldGet$
|
|
481
|
+
if (__classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") && __classPrivateFieldGet$4(this, _Lock_lockSymbol, "f") !== symbol) {
|
|
482
482
|
throw new Error('Lock check failed');
|
|
483
483
|
}
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
_Lock_lockSymbol = new WeakMap();
|
|
487
487
|
|
|
488
|
-
var __classPrivateFieldSet$
|
|
488
|
+
var __classPrivateFieldSet$3 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
489
489
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
490
490
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
491
491
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
492
492
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
493
493
|
};
|
|
494
|
-
var __classPrivateFieldGet$
|
|
494
|
+
var __classPrivateFieldGet$3 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
495
495
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
496
496
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
497
497
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
@@ -505,7 +505,7 @@ class TapeBlock {
|
|
|
505
505
|
_TapeBlock_lock.set(this, new Lock());
|
|
506
506
|
_TapeBlock_tapes.set(this, void 0);
|
|
507
507
|
_TapeBlock_buildPatternList.set(this, (symbolList) => symbolList.reduce((result, symbol, ix) => {
|
|
508
|
-
const row = Math.floor(ix / __classPrivateFieldGet$
|
|
508
|
+
const row = Math.floor(ix / __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length);
|
|
509
509
|
if (!Array.isArray(result[row])) {
|
|
510
510
|
result[row] = [];
|
|
511
511
|
}
|
|
@@ -521,7 +521,7 @@ class TapeBlock {
|
|
|
521
521
|
if (patternList.some((pattern) => pattern.every((symbol) => symbol === ifOtherSymbol))) {
|
|
522
522
|
return ifOtherSymbol;
|
|
523
523
|
}
|
|
524
|
-
const [storedPatternListSymbol] = [...__classPrivateFieldGet$
|
|
524
|
+
const [storedPatternListSymbol] = [...__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").entries()]
|
|
525
525
|
.find(([, storedPatternList]) => {
|
|
526
526
|
if (storedPatternList.length !== patternList.length) {
|
|
527
527
|
return false;
|
|
@@ -535,8 +535,8 @@ class TapeBlock {
|
|
|
535
535
|
symbol = storedPatternListSymbol;
|
|
536
536
|
}
|
|
537
537
|
else {
|
|
538
|
-
symbol = Symbol(__classPrivateFieldGet$
|
|
539
|
-
__classPrivateFieldGet$
|
|
538
|
+
symbol = Symbol(__classPrivateFieldGet$3(_a$1, _a$1, "f", _TapeBlock_generateSymbolHint).call(_a$1, patternList));
|
|
539
|
+
__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").set(symbol, patternList);
|
|
540
540
|
}
|
|
541
541
|
return symbol;
|
|
542
542
|
});
|
|
@@ -551,60 +551,60 @@ class TapeBlock {
|
|
|
551
551
|
else if (Array.isArray(symbols)) {
|
|
552
552
|
localSymbols = [...symbols];
|
|
553
553
|
}
|
|
554
|
-
if (localSymbols.length === 0 || localSymbols.length % __classPrivateFieldGet$
|
|
554
|
+
if (localSymbols.length === 0 || localSymbols.length % __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length > 0) {
|
|
555
555
|
throw new Error('invalid symbol parameter');
|
|
556
556
|
}
|
|
557
557
|
const invalidSymbolIndex = localSymbols.findIndex((symbol, ix) => (symbol !== ifOtherSymbol
|
|
558
|
-
&& !__classPrivateFieldGet$
|
|
558
|
+
&& !__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[ix % __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length].alphabet.has(symbol)));
|
|
559
559
|
if (invalidSymbolIndex >= 0) {
|
|
560
560
|
throw new Error('invalid symbol parameter');
|
|
561
561
|
}
|
|
562
562
|
if (localSymbols.every((symbol) => symbol === ifOtherSymbol)) {
|
|
563
563
|
return ifOtherSymbol;
|
|
564
564
|
}
|
|
565
|
-
return __classPrivateFieldGet$
|
|
565
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_getSymbolForPatternList, "f").call(this, __classPrivateFieldGet$3(this, _TapeBlock_buildPatternList, "f").call(this, localSymbols));
|
|
566
566
|
});
|
|
567
|
-
__classPrivateFieldSet$
|
|
567
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, [], "f");
|
|
568
568
|
if ('alphabets' in argument) {
|
|
569
569
|
const { alphabets } = argument;
|
|
570
570
|
if (alphabets.length === 0) {
|
|
571
571
|
throw new Error('empty alphabet list');
|
|
572
572
|
}
|
|
573
|
-
__classPrivateFieldSet$
|
|
573
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, alphabets.map((alphabet) => new Tape({
|
|
574
574
|
alphabet,
|
|
575
575
|
})), "f");
|
|
576
576
|
}
|
|
577
577
|
else if ('tapes' in argument) {
|
|
578
|
-
__classPrivateFieldSet$
|
|
578
|
+
__classPrivateFieldSet$3(this, _TapeBlock_tapes, argument.tapes, "f");
|
|
579
579
|
}
|
|
580
|
-
if (__classPrivateFieldGet$
|
|
580
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length === 0) {
|
|
581
581
|
throw new Error('empty tape list');
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
get alphabets() {
|
|
585
|
-
return [...__classPrivateFieldGet$
|
|
585
|
+
return [...__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").map((tape) => tape.alphabet)];
|
|
586
586
|
}
|
|
587
587
|
get currentSymbols() {
|
|
588
|
-
return __classPrivateFieldGet$
|
|
588
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").map((tape) => tape.symbol);
|
|
589
589
|
}
|
|
590
590
|
get [(_TapeBlock_symbolToPatternListMap = new WeakMap(), _TapeBlock_lock = new WeakMap(), _TapeBlock_tapes = new WeakMap(), _TapeBlock_buildPatternList = new WeakMap(), _TapeBlock_getSymbolForPatternList = new WeakMap(), _TapeBlock_symbol = new WeakMap(), lockSymbol)]() {
|
|
591
|
-
return __classPrivateFieldGet$
|
|
591
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_lock, "f");
|
|
592
592
|
}
|
|
593
593
|
get symbol() {
|
|
594
|
-
return __classPrivateFieldGet$
|
|
594
|
+
return __classPrivateFieldGet$3(this, _TapeBlock_symbol, "f").bind(this);
|
|
595
595
|
}
|
|
596
596
|
get tapes() {
|
|
597
|
-
return [...__classPrivateFieldGet$
|
|
597
|
+
return [...__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")];
|
|
598
598
|
}
|
|
599
599
|
set [symbolToPatternListMapSymbol](symbolToPatternListMap) {
|
|
600
|
-
__classPrivateFieldSet$
|
|
600
|
+
__classPrivateFieldSet$3(this, _TapeBlock_symbolToPatternListMap, new Map(symbolToPatternListMap), "f");
|
|
601
601
|
}
|
|
602
602
|
applyCommand(command, executionSymbol = null) {
|
|
603
|
-
__classPrivateFieldGet$
|
|
604
|
-
if (__classPrivateFieldGet$
|
|
603
|
+
__classPrivateFieldGet$3(this, _TapeBlock_lock, "f").check(executionSymbol);
|
|
604
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length !== command.tapesCommands.length) {
|
|
605
605
|
throw new Error('invalid command');
|
|
606
606
|
}
|
|
607
|
-
__classPrivateFieldGet$
|
|
607
|
+
__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").forEach((tape, ix) => {
|
|
608
608
|
const { movement, symbol } = command.tapesCommands[ix];
|
|
609
609
|
if (typeof symbol === 'string') {
|
|
610
610
|
tape.symbol = symbol;
|
|
@@ -640,27 +640,67 @@ class TapeBlock {
|
|
|
640
640
|
else {
|
|
641
641
|
tapeBlock = _a$1.fromAlphabets(this.alphabets);
|
|
642
642
|
}
|
|
643
|
-
tapeBlock[symbolToPatternListMapSymbol] = __classPrivateFieldGet$
|
|
643
|
+
tapeBlock[symbolToPatternListMapSymbol] = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f");
|
|
644
644
|
return tapeBlock;
|
|
645
645
|
}
|
|
646
646
|
isMatched({ currentSymbols = this.currentSymbols, symbol }) {
|
|
647
647
|
if (symbol === ifOtherSymbol) {
|
|
648
648
|
return true;
|
|
649
649
|
}
|
|
650
|
-
if (!__classPrivateFieldGet$
|
|
650
|
+
if (!__classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").has(symbol)) {
|
|
651
651
|
throw new Error('invalid symbol');
|
|
652
652
|
}
|
|
653
|
-
const patternList = __classPrivateFieldGet$
|
|
653
|
+
const patternList = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").get(symbol);
|
|
654
654
|
return patternList?.some((pattern) => (pattern
|
|
655
655
|
.every((everySymbol, ix) => (everySymbol === ifOtherSymbol
|
|
656
656
|
|| everySymbol === currentSymbols[ix])))) ?? false;
|
|
657
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* For a Symbol returned by `this.symbol([...])` (or the catch-all
|
|
660
|
+
* `ifOtherSymbol`), returns the per-tape match kind for the
|
|
661
|
+
* **alternative that actually matched** given `currentSymbols`:
|
|
662
|
+
* `'wildcard'` if that tape position was `ifOtherSymbol` in the winning
|
|
663
|
+
* alternative, `'literal'` otherwise. Length always equals the tape
|
|
664
|
+
* count.
|
|
665
|
+
*
|
|
666
|
+
* Used by `TuringMachine.runStepByStep` to populate
|
|
667
|
+
* `MachineState.matchedTransition.matchKinds` for #205. The "winning
|
|
668
|
+
* alternative" disambiguation matters for alternations like
|
|
669
|
+
* `[[ifOtherSymbol, 'c'], ['a', 'b']]` — different alternatives can
|
|
670
|
+
* have different per-tape kinds, and only the alternative that matched
|
|
671
|
+
* the current head symbols is meaningful.
|
|
672
|
+
*
|
|
673
|
+
* - `ifOtherSymbol` (the State's catch-all transition fired): all
|
|
674
|
+
* positions are `'wildcard'`.
|
|
675
|
+
* - Symbol with patternList: find the first alternative that matches
|
|
676
|
+
* `currentSymbols` (same predicate as `isMatched`), return its
|
|
677
|
+
* per-position kinds.
|
|
678
|
+
* - Symbol with no winning alternative under the given `currentSymbols`
|
|
679
|
+
* (defensive — shouldn't happen if the caller resolved the Symbol via
|
|
680
|
+
* the State's normal matching): fall back to all `'literal'`.
|
|
681
|
+
*/
|
|
682
|
+
patternKinds(symbol, currentSymbols = this.currentSymbols) {
|
|
683
|
+
const tapeCount = __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f").length;
|
|
684
|
+
if (symbol === ifOtherSymbol) {
|
|
685
|
+
return Array.from({ length: tapeCount }, () => 'wildcard');
|
|
686
|
+
}
|
|
687
|
+
const patternList = __classPrivateFieldGet$3(this, _TapeBlock_symbolToPatternListMap, "f").get(symbol);
|
|
688
|
+
if (patternList === undefined) {
|
|
689
|
+
return Array.from({ length: tapeCount }, () => 'literal');
|
|
690
|
+
}
|
|
691
|
+
const winning = patternList.find((pattern) => (pattern.every((everySymbol, ix) => (everySymbol === ifOtherSymbol
|
|
692
|
+
|| everySymbol === currentSymbols[ix]))));
|
|
693
|
+
if (winning === undefined) {
|
|
694
|
+
return Array.from({ length: tapeCount }, () => 'literal');
|
|
695
|
+
}
|
|
696
|
+
return winning.map((everySymbol) => (everySymbol === ifOtherSymbol ? 'wildcard' : 'literal'));
|
|
697
|
+
}
|
|
658
698
|
replaceTape(tape, tapeIx = 0) {
|
|
659
|
-
if (__classPrivateFieldGet$
|
|
699
|
+
if (__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx] == null) {
|
|
660
700
|
throw new Error('invalid tapeIx');
|
|
661
701
|
}
|
|
662
|
-
if (tape.alphabet.symbols.join('') === __classPrivateFieldGet$
|
|
663
|
-
__classPrivateFieldGet$
|
|
702
|
+
if (tape.alphabet.symbols.join('') === __classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx].alphabet.symbols.join('')) {
|
|
703
|
+
__classPrivateFieldGet$3(this, _TapeBlock_tapes, "f")[tapeIx] = tape;
|
|
664
704
|
}
|
|
665
705
|
else {
|
|
666
706
|
throw new Error('invalid tape');
|
|
@@ -678,16 +718,11 @@ _TapeBlock_generateSymbolHint = { value: (patternList) => JSON.stringify(pattern
|
|
|
678
718
|
.map((pattern) => pattern
|
|
679
719
|
.map((symbol) => (symbol === ifOtherSymbol ? null : symbol)))) };
|
|
680
720
|
|
|
681
|
-
// Graph serialization/reconstruction for State graphs.
|
|
682
|
-
//
|
|
683
|
-
// machinery (transitions, debug, halt-stack composition). Sibling-module
|
|
684
|
-
// private access to State's internals goes through the `STATE_INTERNAL`
|
|
721
|
+
// Graph serialization/reconstruction + state collection for State graphs.
|
|
722
|
+
// Sibling-module access to State's internals uses the `STATE_INTERNAL`
|
|
685
723
|
// Symbol re-exported from State.ts — see the @internal JSDoc there.
|
|
686
|
-
//
|
|
687
|
-
//
|
|
688
|
-
// methods continue to exist as thin delegates to the functions in this
|
|
689
|
-
// module. New consumers (e.g. #195's planned `collectStates`) will live
|
|
690
|
-
// here too and share the BFS-walk shape with `toGraph`.
|
|
724
|
+
// `State.toGraph` / `.fromGraph` / `.collectStates` static methods on
|
|
725
|
+
// State are thin delegates to functions in this module.
|
|
691
726
|
/**
|
|
692
727
|
* Walks the reachable graph from `initialState` and returns a serializable
|
|
693
728
|
* `Graph`. The walk is a BFS that visits each State exactly once (keyed by
|
|
@@ -789,7 +824,12 @@ function toGraph(initialState, tapeBlock) {
|
|
|
789
824
|
movement: decodeMovement(tc.movement.description),
|
|
790
825
|
})),
|
|
791
826
|
nextStateId: targetInternal.id,
|
|
792
|
-
|
|
827
|
+
// `${stateId}.${transitionIx}` — matches
|
|
828
|
+
// `MachineState.matchedTransition.id` so consumers can do
|
|
829
|
+
// `graph.nodes[stateId].transitions.find(t => t.id === id)`.
|
|
830
|
+
// `.` separator (vs `-`) avoids collision with negative
|
|
831
|
+
// halt-marker ids.
|
|
832
|
+
id: `${stateInternal.id}.${patternIx}`,
|
|
793
833
|
});
|
|
794
834
|
queue.push(target);
|
|
795
835
|
patternIx += 1;
|
|
@@ -827,6 +867,9 @@ function toGraph(initialState, tapeBlock) {
|
|
|
827
867
|
// `nodes[id]` is always populated for `id` that the BFS reached, so
|
|
828
868
|
// a defensive `!node` check would be dead. `isHalt` / `isWrapper`
|
|
829
869
|
// are real boundaries — both stop reach-set expansion.
|
|
870
|
+
/* c8 ignore next 3 — defensive: the push site below already filters
|
|
871
|
+
halt/wrapper targets, and the initial push is always a bare, so
|
|
872
|
+
this branch is unreachable in practice. */
|
|
830
873
|
if (node.isHalt || node.isWrapper) {
|
|
831
874
|
continue;
|
|
832
875
|
}
|
|
@@ -1071,7 +1114,8 @@ function fromGraph(graph) {
|
|
|
1071
1114
|
* instance + per-pattern Symbol references for breakpoint setup (#195).
|
|
1072
1115
|
*
|
|
1073
1116
|
* **Positional alignment contract.** For any `GraphTransition` whose id
|
|
1074
|
-
* is `${N}
|
|
1117
|
+
* is `${N}.${K}` (#205 changed the separator from `-` to `.`),
|
|
1118
|
+
* `result.get(N)!.transitionSymbols[K]` is the Symbol
|
|
1075
1119
|
* the transition fires on (reference equality, not structural). The K-th
|
|
1076
1120
|
* entry is the K-th key from the source State's `#symbolToDataMap` in
|
|
1077
1121
|
* insertion order, including `ifOtherSymbol` when the user wrote one.
|
|
@@ -1082,7 +1126,7 @@ function fromGraph(graph) {
|
|
|
1082
1126
|
* when a transition's `nextState` is an unresolved `Reference` (it
|
|
1083
1127
|
* `continue`s without pushing the GraphTransition). In that case
|
|
1084
1128
|
* `transitionSymbols[K]` is still set to the K-th Map key, but no
|
|
1085
|
-
* `Graph.nodes[N].transitions` entry exists with id `${N}
|
|
1129
|
+
* `Graph.nodes[N].transitions` entry exists with id `${N}.${K}`. Sparse
|
|
1086
1130
|
* on the Graph side, dense on the `transitionSymbols` side — same
|
|
1087
1131
|
* indexing.
|
|
1088
1132
|
*
|
|
@@ -1170,7 +1214,7 @@ function collectStates(initialState, tapeBlock) {
|
|
|
1170
1214
|
}
|
|
1171
1215
|
// Regular or bare State — enumerate `#symbolToDataMap.keys()` for
|
|
1172
1216
|
// the patternIx alignment. The K-th key is the Symbol that
|
|
1173
|
-
// `${id}
|
|
1217
|
+
// `${id}.${K}` GraphTransition fires on (positional contract).
|
|
1174
1218
|
const state = stateById.get(id);
|
|
1175
1219
|
const transitionSymbols = [...state[STATE_INTERNAL]().symbolToDataMap.keys()];
|
|
1176
1220
|
result.set(id, { state, transitionSymbols });
|
|
@@ -1185,18 +1229,18 @@ function collectStates(initialState, tapeBlock) {
|
|
|
1185
1229
|
// source module finishes evaluating. All references here live inside
|
|
1186
1230
|
// function bodies, so the cycle is safe.
|
|
1187
1231
|
|
|
1188
|
-
var __classPrivateFieldSet$
|
|
1232
|
+
var __classPrivateFieldSet$2 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1189
1233
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1190
1234
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1191
1235
|
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");
|
|
1192
1236
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1193
1237
|
};
|
|
1194
|
-
var __classPrivateFieldGet$
|
|
1238
|
+
var __classPrivateFieldGet$2 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1195
1239
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1196
1240
|
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");
|
|
1197
1241
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1198
1242
|
};
|
|
1199
|
-
var _DebugConfig_ownerState, _DebugConfig_before, _DebugConfig_after, _a, _State_wrapperCache, _State_id, _State_name, _State_overriddenHaltState, _State_bareState, _State_symbolToDataMap, _State_debugRef, _State_tags;
|
|
1243
|
+
var _DebugConfig_ownerState, _DebugConfig_before, _DebugConfig_after, _State_instances, _a, _State_wrapperCache, _State_id, _State_name, _State_overriddenHaltState, _State_bareState, _State_symbolToDataMap, _State_debugRef, _State_haltDebug, _State_tags, _State_getEntry;
|
|
1200
1244
|
const ifOtherSymbol = Symbol('other symbol');
|
|
1201
1245
|
// Module-private symbol used by DebugConfig setters to call State's validator
|
|
1202
1246
|
// without exposing the validator on the public surface.
|
|
@@ -1228,7 +1272,7 @@ class DebugConfig {
|
|
|
1228
1272
|
_DebugConfig_ownerState.set(this, void 0);
|
|
1229
1273
|
_DebugConfig_before.set(this, void 0);
|
|
1230
1274
|
_DebugConfig_after.set(this, void 0);
|
|
1231
|
-
__classPrivateFieldSet$
|
|
1275
|
+
__classPrivateFieldSet$2(this, _DebugConfig_ownerState, ownerState, "f");
|
|
1232
1276
|
if (initial) {
|
|
1233
1277
|
if (initial.before !== undefined) {
|
|
1234
1278
|
this.before = initial.before;
|
|
@@ -1245,23 +1289,24 @@ class DebugConfig {
|
|
|
1245
1289
|
Object.seal(this);
|
|
1246
1290
|
}
|
|
1247
1291
|
get before() {
|
|
1248
|
-
return __classPrivateFieldGet$
|
|
1292
|
+
return __classPrivateFieldGet$2(this, _DebugConfig_before, "f");
|
|
1249
1293
|
}
|
|
1250
1294
|
set before(v) {
|
|
1251
|
-
__classPrivateFieldGet$
|
|
1252
|
-
__classPrivateFieldSet$
|
|
1295
|
+
__classPrivateFieldGet$2(this, _DebugConfig_ownerState, "f")[validateDebugFilter]('before', v);
|
|
1296
|
+
__classPrivateFieldSet$2(this, _DebugConfig_before, Array.isArray(v) ? Object.freeze([...v]) : v, "f");
|
|
1253
1297
|
}
|
|
1254
1298
|
get after() {
|
|
1255
|
-
return __classPrivateFieldGet$
|
|
1299
|
+
return __classPrivateFieldGet$2(this, _DebugConfig_after, "f");
|
|
1256
1300
|
}
|
|
1257
1301
|
set after(v) {
|
|
1258
|
-
__classPrivateFieldGet$
|
|
1259
|
-
__classPrivateFieldSet$
|
|
1302
|
+
__classPrivateFieldGet$2(this, _DebugConfig_ownerState, "f")[validateDebugFilter]('after', v);
|
|
1303
|
+
__classPrivateFieldSet$2(this, _DebugConfig_after, Array.isArray(v) ? Object.freeze([...v]) : v, "f");
|
|
1260
1304
|
}
|
|
1261
1305
|
}
|
|
1262
1306
|
_DebugConfig_ownerState = new WeakMap(), _DebugConfig_before = new WeakMap(), _DebugConfig_after = new WeakMap();
|
|
1263
1307
|
class State {
|
|
1264
1308
|
constructor(stateDefinition = null, name) {
|
|
1309
|
+
_State_instances.add(this);
|
|
1265
1310
|
_State_id.set(this, id(this));
|
|
1266
1311
|
// Not `readonly` because `withOverriddenHaltState` and `fromGraph` set the
|
|
1267
1312
|
// composed name on a no-arg `new State()` to bypass the constructor's
|
|
@@ -1270,8 +1315,8 @@ class State {
|
|
|
1270
1315
|
_State_overriddenHaltState.set(this, null);
|
|
1271
1316
|
// For wrapper states (produced by `withOverriddenHaltState`), points at the
|
|
1272
1317
|
// State whose transition map was wrapped. `null` on bare/atomic states.
|
|
1273
|
-
//
|
|
1274
|
-
//
|
|
1318
|
+
// `toGraph` reads this to render wrapper and bare as separate nodes linked
|
|
1319
|
+
// by a `==> call` arrow.
|
|
1275
1320
|
_State_bareState.set(this, null);
|
|
1276
1321
|
_State_symbolToDataMap.set(this, new Map());
|
|
1277
1322
|
// Shared mutable cell — withOverriddenHaltState wrappers reference the same
|
|
@@ -1279,6 +1324,14 @@ class State {
|
|
|
1279
1324
|
// Note: toGraph / fromGraph deliberately do not serialize debug — debug is
|
|
1280
1325
|
// a runtime concern, not part of the structural graph.
|
|
1281
1326
|
_State_debugRef.set(this, { current: null });
|
|
1327
|
+
// Storage for `haltState.debug` (#207). haltState is a singleton terminal
|
|
1328
|
+
// state — it has no iter of its own, so the per-side `{ before, after }`
|
|
1329
|
+
// DebugConfig shape doesn't model anything meaningful for it. Instead the
|
|
1330
|
+
// halt breakpoint is a single boolean ("enabled / disabled"). The pause
|
|
1331
|
+
// anchors on the iter whose transition LEADS to halt, fired at end-of-iter
|
|
1332
|
+
// (after that iter's own after-pause if armed). Only used when `isHalt`;
|
|
1333
|
+
// ignored on every other State (whose `#debugRef` flow is unchanged).
|
|
1334
|
+
_State_haltDebug.set(this, false);
|
|
1282
1335
|
// Out-of-band tags applied to this State (#186). Tags are visualization
|
|
1283
1336
|
// and debugger-tooling metadata — they don't affect runtime transition
|
|
1284
1337
|
// lookup or `equivalentOn` comparisons. Stored as a Set for de-duplication;
|
|
@@ -1290,11 +1343,11 @@ class State {
|
|
|
1290
1343
|
if (stateDefinition) {
|
|
1291
1344
|
const keys = Object.getOwnPropertyNames(stateDefinition);
|
|
1292
1345
|
if (keys.length) {
|
|
1293
|
-
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$
|
|
1346
|
+
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$2(this, _State_id, "f")}`);
|
|
1294
1347
|
}
|
|
1295
1348
|
const symbols = Object.getOwnPropertySymbols(stateDefinition);
|
|
1296
1349
|
if (symbols.length === 0) {
|
|
1297
|
-
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$
|
|
1350
|
+
throw new Error(`invalid state definition while constructing state #${__classPrivateFieldGet$2(this, _State_id, "f")}`);
|
|
1298
1351
|
}
|
|
1299
1352
|
symbols.forEach((symbol) => {
|
|
1300
1353
|
const { nextState } = stateDefinition[symbol];
|
|
@@ -1322,7 +1375,7 @@ class State {
|
|
|
1322
1375
|
if (!(commandLocal instanceof Command)) {
|
|
1323
1376
|
throw new Error('invalid command');
|
|
1324
1377
|
}
|
|
1325
|
-
__classPrivateFieldGet$
|
|
1378
|
+
__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").set(symbol, {
|
|
1326
1379
|
command: commandLocal,
|
|
1327
1380
|
nextState: nextStateLocal,
|
|
1328
1381
|
});
|
|
@@ -1331,44 +1384,86 @@ class State {
|
|
|
1331
1384
|
if (name !== undefined && /[()]/.test(name)) {
|
|
1332
1385
|
throw new Error(`invalid state name "${name}": must not contain '(' or ')' (reserved as wrapper-composition delimiters in withOverriddenHaltState)`);
|
|
1333
1386
|
}
|
|
1334
|
-
__classPrivateFieldSet$
|
|
1387
|
+
__classPrivateFieldSet$2(this, _State_name, name ?? `id:${__classPrivateFieldGet$2(this, _State_id, "f")}`, "f");
|
|
1335
1388
|
}
|
|
1336
1389
|
get id() {
|
|
1337
|
-
return __classPrivateFieldGet$
|
|
1390
|
+
return __classPrivateFieldGet$2(this, _State_id, "f");
|
|
1338
1391
|
}
|
|
1339
1392
|
get name() {
|
|
1340
|
-
return __classPrivateFieldGet$
|
|
1393
|
+
return __classPrivateFieldGet$2(this, _State_name, "f");
|
|
1341
1394
|
}
|
|
1342
1395
|
get isHalt() {
|
|
1343
|
-
return __classPrivateFieldGet$
|
|
1396
|
+
return __classPrivateFieldGet$2(this, _State_id, "f") === 0;
|
|
1344
1397
|
}
|
|
1345
1398
|
get overriddenHaltState() {
|
|
1346
|
-
return __classPrivateFieldGet$
|
|
1399
|
+
return __classPrivateFieldGet$2(this, _State_overriddenHaltState, "f");
|
|
1347
1400
|
}
|
|
1348
1401
|
get ref() {
|
|
1349
1402
|
return this;
|
|
1350
1403
|
}
|
|
1351
1404
|
get debug() {
|
|
1405
|
+
// haltState (#207): the canonical access path is the `haltState` singleton
|
|
1406
|
+
// export, which is typed `HaltState` — its `debug` getter is narrowed to
|
|
1407
|
+
// `boolean`. Generic `State` references statically see `DebugConfig` and
|
|
1408
|
+
// (in practice) never refer to haltState — the run loop's `state` is
|
|
1409
|
+
// never haltState because halt is terminal and doesn't iterate. The cast
|
|
1410
|
+
// below makes the runtime boolean return type-compatible with the
|
|
1411
|
+
// declared `DebugConfig` for any rare caller that holds a State
|
|
1412
|
+
// reference happening to be haltState.
|
|
1413
|
+
if (this.isHalt) {
|
|
1414
|
+
return __classPrivateFieldGet$2(this, _State_haltDebug, "f");
|
|
1415
|
+
}
|
|
1352
1416
|
// Lazy-init: `state.debug` is never null at read time, so chained writes
|
|
1353
1417
|
// like `state.debug.before = true` work on a fresh state without a prior
|
|
1354
1418
|
// whole-object assignment. The setter still accepts `null` to reset the
|
|
1355
1419
|
// filters; the next read recreates a fresh empty `DebugConfig` on demand.
|
|
1356
1420
|
// See #150.
|
|
1357
|
-
if (__classPrivateFieldGet$
|
|
1358
|
-
__classPrivateFieldGet$
|
|
1421
|
+
if (__classPrivateFieldGet$2(this, _State_debugRef, "f").current === null) {
|
|
1422
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = new DebugConfig(this);
|
|
1359
1423
|
}
|
|
1360
|
-
return __classPrivateFieldGet$
|
|
1424
|
+
return __classPrivateFieldGet$2(this, _State_debugRef, "f").current;
|
|
1361
1425
|
}
|
|
1426
|
+
// TS signature: non-halt callers (generic `State` reference) get the
|
|
1427
|
+
// `DebugConfig | object | null` surface; boolean is rejected statically.
|
|
1428
|
+
// The `HaltState` typed alias on the singleton export overrides this to
|
|
1429
|
+
// `boolean | null` for the canonical halt access path. Runtime checks
|
|
1430
|
+
// below are defensive against type-bypass / mixed-source callers.
|
|
1362
1431
|
set debug(value) {
|
|
1363
|
-
|
|
1364
|
-
|
|
1432
|
+
// Defensive runtime cast: TS signature excludes boolean for the generic
|
|
1433
|
+
// State surface, but haltState (via the HaltState alias) DOES accept
|
|
1434
|
+
// boolean, and the runtime needs to handle it for the singleton path.
|
|
1435
|
+
const v = value;
|
|
1436
|
+
// haltState (#207): only `boolean | null` is accepted. `null` aliases
|
|
1437
|
+
// to `false` (reset). Any object-shaped write throws at write-time so
|
|
1438
|
+
// misuse surfaces immediately rather than silently no-op'ing — the
|
|
1439
|
+
// `{before, after}` shape doesn't model anything meaningful for halt
|
|
1440
|
+
// (no own iter to anchor on; halt is terminal).
|
|
1441
|
+
if (this.isHalt) {
|
|
1442
|
+
if (v === null || typeof v === 'boolean') {
|
|
1443
|
+
__classPrivateFieldSet$2(this, _State_haltDebug, v === true, "f");
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
throw new Error('haltState.debug only accepts boolean (or null to reset). Use '
|
|
1447
|
+
+ '`haltState.debug = true` to enable the halt breakpoint, false to '
|
|
1448
|
+
+ 'disable. The pause fires after the iter whose transition leads to '
|
|
1449
|
+
+ 'halt (post-iter, before halt processing).');
|
|
1450
|
+
}
|
|
1451
|
+
// Non-halt states: boolean writes are rejected — the per-side
|
|
1452
|
+
// `{before, after}` granularity is the contract. A boolean shortcut
|
|
1453
|
+
// would hide the asymmetry between before / after.
|
|
1454
|
+
if (typeof v === 'boolean') {
|
|
1455
|
+
throw new Error('state.debug only accepts a DebugConfig or `{ before, after }` object '
|
|
1456
|
+
+ '(or null to reset). Boolean assignment is reserved for `haltState`.');
|
|
1457
|
+
}
|
|
1458
|
+
if (v === null) {
|
|
1459
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = null;
|
|
1365
1460
|
return;
|
|
1366
1461
|
}
|
|
1367
|
-
if (
|
|
1368
|
-
__classPrivateFieldGet$
|
|
1462
|
+
if (v instanceof DebugConfig) {
|
|
1463
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = v;
|
|
1369
1464
|
return;
|
|
1370
1465
|
}
|
|
1371
|
-
__classPrivateFieldGet$
|
|
1466
|
+
__classPrivateFieldGet$2(this, _State_debugRef, "f").current = new DebugConfig(this, v);
|
|
1372
1467
|
}
|
|
1373
1468
|
/**
|
|
1374
1469
|
* Add one or more tags to this State (#186). Tags are out-of-band metadata
|
|
@@ -1378,7 +1473,7 @@ class State {
|
|
|
1378
1473
|
*/
|
|
1379
1474
|
tag(...tags) {
|
|
1380
1475
|
for (const t of tags) {
|
|
1381
|
-
__classPrivateFieldGet$
|
|
1476
|
+
__classPrivateFieldGet$2(this, _State_tags, "f").add(t);
|
|
1382
1477
|
}
|
|
1383
1478
|
return this;
|
|
1384
1479
|
}
|
|
@@ -1388,7 +1483,7 @@ class State {
|
|
|
1388
1483
|
*/
|
|
1389
1484
|
untag(...tags) {
|
|
1390
1485
|
for (const t of tags) {
|
|
1391
|
-
__classPrivateFieldGet$
|
|
1486
|
+
__classPrivateFieldGet$2(this, _State_tags, "f").delete(t);
|
|
1392
1487
|
}
|
|
1393
1488
|
return this;
|
|
1394
1489
|
}
|
|
@@ -1398,37 +1493,26 @@ class State {
|
|
|
1398
1493
|
* code uses). Order matches insertion order of the underlying Set.
|
|
1399
1494
|
*/
|
|
1400
1495
|
get tags() {
|
|
1401
|
-
return Object.freeze([...__classPrivateFieldGet$
|
|
1496
|
+
return Object.freeze([...__classPrivateFieldGet$2(this, _State_tags, "f")]);
|
|
1402
1497
|
}
|
|
1403
|
-
/** @internal — invoked by DebugConfig setters via module-private symbol.
|
|
1404
|
-
|
|
1498
|
+
/** @internal — invoked by DebugConfig setters via module-private symbol.
|
|
1499
|
+
* haltState's `debug` setter rejects object writes before reaching
|
|
1500
|
+
* DebugConfig, so this validator only sees non-halt states. */
|
|
1501
|
+
[(_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) {
|
|
1405
1502
|
if (filter === undefined)
|
|
1406
1503
|
return;
|
|
1407
|
-
// #108 part 2: `.after` on haltState has no semantic anchor — halt is
|
|
1408
|
-
// terminal, so there is no iteration-after-halt for an after-fire to
|
|
1409
|
-
// attach to. Reject any truthy assignment (true OR list) at write time
|
|
1410
|
-
// so misuse surfaces immediately rather than silently no-op'ing.
|
|
1411
|
-
if (this.isHalt && fieldName === 'after') {
|
|
1412
|
-
throw new Error('haltState.debug.after is not supported: halt is terminal, so there is '
|
|
1413
|
-
+ 'no iteration-after-halt for an after-fire to anchor on. Use '
|
|
1414
|
-
+ '{ before: true } to pause on halt entry.');
|
|
1415
|
-
}
|
|
1416
1504
|
if (filter === true)
|
|
1417
1505
|
return;
|
|
1418
|
-
// haltState has no own transitions; symbol-list filters on `before` are
|
|
1419
|
-
// silent no-ops at the engine level (spec §8.6), so accept any list shape.
|
|
1420
|
-
if (this.isHalt)
|
|
1421
|
-
return;
|
|
1422
1506
|
for (const sym of filter) {
|
|
1423
|
-
if (sym !== ifOtherSymbol && !__classPrivateFieldGet$
|
|
1507
|
+
if (sym !== ifOtherSymbol && !__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").has(sym)) {
|
|
1424
1508
|
throw new Error(`State.debug.${fieldName}: symbol is not a transition key of this state `
|
|
1425
|
-
+ `(state name: ${__classPrivateFieldGet$
|
|
1509
|
+
+ `(state name: ${__classPrivateFieldGet$2(this, _State_name, "f")}). Common cause: symbol comes from a `
|
|
1426
1510
|
+ 'different tape block, or doesn\'t match any of this state\'s transitions.');
|
|
1427
1511
|
}
|
|
1428
1512
|
}
|
|
1429
1513
|
}
|
|
1430
1514
|
getSymbol(tapeBlock) {
|
|
1431
|
-
const symbol = [...__classPrivateFieldGet$
|
|
1515
|
+
const symbol = [...__classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").keys()].find((currentSymbol) => tapeBlock.isMatched({
|
|
1432
1516
|
symbol: currentSymbol,
|
|
1433
1517
|
}));
|
|
1434
1518
|
if (symbol) {
|
|
@@ -1437,29 +1521,53 @@ class State {
|
|
|
1437
1521
|
return ifOtherSymbol;
|
|
1438
1522
|
}
|
|
1439
1523
|
getCommand(symbol) {
|
|
1440
|
-
|
|
1441
|
-
return __classPrivateFieldGet$1(this, _State_symbolToDataMap, "f").get(symbol).command;
|
|
1442
|
-
}
|
|
1443
|
-
throw new Error(`No command for symbol at state named ${__classPrivateFieldGet$1(this, _State_name, "f")}`);
|
|
1524
|
+
return __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol).command;
|
|
1444
1525
|
}
|
|
1445
1526
|
getNextState(symbol) {
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1527
|
+
return __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol).nextState;
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Like `getNextState`, but also returns the matched Symbol and its index
|
|
1531
|
+
* in this State's transition declaration order (= the `K` in `toGraph`'s
|
|
1532
|
+
* `${stateId}.${K}` transition ids). Used by `TuringMachine.runStepByStep`
|
|
1533
|
+
* to populate `MachineState.matchedTransition` for #205 — exposes which
|
|
1534
|
+
* transition fired so consumers (UIs, log tools, coverage maps) can
|
|
1535
|
+
* resolve the firing edge without re-deriving from `(source, nextState)`,
|
|
1536
|
+
* which is ambiguous when multiple transitions on the same source go to
|
|
1537
|
+
* the same destination.
|
|
1538
|
+
*
|
|
1539
|
+
* Throws (matching `getNextState` / `getCommand`) when no entry exists for
|
|
1540
|
+
* the symbol. For wrappers (states produced by `withOverriddenHaltState`):
|
|
1541
|
+
* the symbol-to-data map is shared with the bare via `bareState`, so the
|
|
1542
|
+
* returned `ix` is a valid position into BOTH the wrapper's and the
|
|
1543
|
+
* bare's transition iteration order — they're the same map.
|
|
1544
|
+
*/
|
|
1545
|
+
getMatchedTransition(symbol) {
|
|
1546
|
+
const entry = __classPrivateFieldGet$2(this, _State_instances, "m", _State_getEntry).call(this, symbol);
|
|
1547
|
+
// Iteration order on a Map is insertion order; index lookup is O(N),
|
|
1548
|
+
// acceptable since this fires at most once per iter and N (transitions
|
|
1549
|
+
// per state) is typically tiny. If hot-path measurement ever flags it,
|
|
1550
|
+
// cache as `#symbolToIxMap` mirror.
|
|
1551
|
+
let ix = 0;
|
|
1552
|
+
for (const key of __classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").keys()) {
|
|
1553
|
+
if (key === symbol)
|
|
1554
|
+
break;
|
|
1555
|
+
ix += 1;
|
|
1556
|
+
}
|
|
1557
|
+
return { nextState: entry.nextState, matchedSymbol: symbol, ix };
|
|
1450
1558
|
}
|
|
1451
1559
|
withOverriddenHaltState(overriddenHaltState) {
|
|
1452
1560
|
// Unwrap `this` if it's itself a wrapper — the chain's inner overrides
|
|
1453
1561
|
// are dead at runtime anyway (only the outermost `.wohs()`'s override is
|
|
1454
1562
|
// pushed onto the halt-stack on entry; verified empirically). Composite
|
|
1455
1563
|
// name reflects runtime behavior, not construction history. See #176.
|
|
1456
|
-
const bare = __classPrivateFieldGet$
|
|
1564
|
+
const bare = __classPrivateFieldGet$2(this, _State_bareState, "f") ?? this;
|
|
1457
1565
|
// Memoize by (bare, override) so identical args return the same instance
|
|
1458
1566
|
// (#175). The cache uses WeakMaps + WeakRefs so cached wrappers can be
|
|
1459
1567
|
// GC'd when nothing else holds them. Compounds with the chain-collapse
|
|
1460
1568
|
// above: `A.wohs(t1).wohs(t2)` keys as (A, t2) after the unwrap, hitting
|
|
1461
1569
|
// the same cache slot as a direct `A.wohs(t2)`.
|
|
1462
|
-
let innerCache = __classPrivateFieldGet$
|
|
1570
|
+
let innerCache = __classPrivateFieldGet$2(_a, _a, "f", _State_wrapperCache).get(bare);
|
|
1463
1571
|
if (innerCache !== undefined) {
|
|
1464
1572
|
const ref = innerCache.get(overriddenHaltState);
|
|
1465
1573
|
if (ref !== undefined) {
|
|
@@ -1471,17 +1579,17 @@ class State {
|
|
|
1471
1579
|
}
|
|
1472
1580
|
else {
|
|
1473
1581
|
innerCache = new WeakMap();
|
|
1474
|
-
__classPrivateFieldGet$
|
|
1582
|
+
__classPrivateFieldGet$2(_a, _a, "f", _State_wrapperCache).set(bare, innerCache);
|
|
1475
1583
|
}
|
|
1476
1584
|
// Cache miss — construct with no name, then overwrite #name directly
|
|
1477
1585
|
// (composed names contain `(` and `)` which the constructor's user-facing
|
|
1478
1586
|
// validation would reject; private-field access bypasses that).
|
|
1479
1587
|
const state = new _a();
|
|
1480
|
-
__classPrivateFieldSet$
|
|
1481
|
-
__classPrivateFieldSet$
|
|
1482
|
-
__classPrivateFieldSet$
|
|
1483
|
-
__classPrivateFieldSet$
|
|
1484
|
-
__classPrivateFieldSet$
|
|
1588
|
+
__classPrivateFieldSet$2(state, _State_name, `${bare.name}(${overriddenHaltState.name})`, "f");
|
|
1589
|
+
__classPrivateFieldSet$2(state, _State_symbolToDataMap, __classPrivateFieldGet$2(bare, _State_symbolToDataMap, "f"), "f");
|
|
1590
|
+
__classPrivateFieldSet$2(state, _State_overriddenHaltState, overriddenHaltState, "f");
|
|
1591
|
+
__classPrivateFieldSet$2(state, _State_debugRef, __classPrivateFieldGet$2(bare, _State_debugRef, "f"), "f");
|
|
1592
|
+
__classPrivateFieldSet$2(state, _State_bareState, bare, "f");
|
|
1485
1593
|
innerCache.set(overriddenHaltState, new WeakRef(state));
|
|
1486
1594
|
return state;
|
|
1487
1595
|
}
|
|
@@ -1509,7 +1617,13 @@ class State {
|
|
|
1509
1617
|
* read what they need. Adding fields here is a deliberate decision —
|
|
1510
1618
|
* each adds to the implicit contract sibling modules can rely on.
|
|
1511
1619
|
*/
|
|
1512
|
-
[
|
|
1620
|
+
[(_State_getEntry = function _State_getEntry(symbol) {
|
|
1621
|
+
const entry = __classPrivateFieldGet$2(this, _State_symbolToDataMap, "f").get(symbol);
|
|
1622
|
+
if (entry === undefined) {
|
|
1623
|
+
throw new Error(`No transition for symbol at state named ${__classPrivateFieldGet$2(this, _State_name, "f")}`);
|
|
1624
|
+
}
|
|
1625
|
+
return entry;
|
|
1626
|
+
}, STATE_INTERNAL)]() {
|
|
1513
1627
|
// Aliasing `this` so the nested object-literal getters/setters below
|
|
1514
1628
|
// can read/write the enclosing State's private fields — getters in an
|
|
1515
1629
|
// object literal can't be arrow functions, so the standard arrow-
|
|
@@ -1517,13 +1631,13 @@ class State {
|
|
|
1517
1631
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
1518
1632
|
const self = this;
|
|
1519
1633
|
return {
|
|
1520
|
-
get id() { return __classPrivateFieldGet$
|
|
1521
|
-
get name() { return __classPrivateFieldGet$
|
|
1522
|
-
set name(v) { __classPrivateFieldSet$
|
|
1523
|
-
get bareState() { return __classPrivateFieldGet$
|
|
1524
|
-
get overriddenHaltState() { return __classPrivateFieldGet$
|
|
1525
|
-
get symbolToDataMap() { return __classPrivateFieldGet$
|
|
1526
|
-
get tags() { return __classPrivateFieldGet$
|
|
1634
|
+
get id() { return __classPrivateFieldGet$2(self, _State_id, "f"); },
|
|
1635
|
+
get name() { return __classPrivateFieldGet$2(self, _State_name, "f"); },
|
|
1636
|
+
set name(v) { __classPrivateFieldSet$2(self, _State_name, v, "f"); },
|
|
1637
|
+
get bareState() { return __classPrivateFieldGet$2(self, _State_bareState, "f"); },
|
|
1638
|
+
get overriddenHaltState() { return __classPrivateFieldGet$2(self, _State_overriddenHaltState, "f"); },
|
|
1639
|
+
get symbolToDataMap() { return __classPrivateFieldGet$2(self, _State_symbolToDataMap, "f"); },
|
|
1640
|
+
get tags() { return __classPrivateFieldGet$2(self, _State_tags, "f"); },
|
|
1527
1641
|
};
|
|
1528
1642
|
}
|
|
1529
1643
|
// Single-state introspection — no traversal, no tapeBlock required.
|
|
@@ -1533,7 +1647,7 @@ class State {
|
|
|
1533
1647
|
// interned JS Symbol (decode via decodePatternDescription if needed).
|
|
1534
1648
|
static inspect(state) {
|
|
1535
1649
|
const transitions = [];
|
|
1536
|
-
for (const [sym, { command, nextState }] of __classPrivateFieldGet$
|
|
1650
|
+
for (const [sym, { command, nextState }] of __classPrivateFieldGet$2(state, _State_symbolToDataMap, "f")) {
|
|
1537
1651
|
let target = null;
|
|
1538
1652
|
try {
|
|
1539
1653
|
target = nextState instanceof _a ? nextState : nextState.ref;
|
|
@@ -1551,11 +1665,11 @@ class State {
|
|
|
1551
1665
|
});
|
|
1552
1666
|
}
|
|
1553
1667
|
return {
|
|
1554
|
-
id: __classPrivateFieldGet$
|
|
1555
|
-
name: __classPrivateFieldGet$
|
|
1668
|
+
id: __classPrivateFieldGet$2(state, _State_id, "f"),
|
|
1669
|
+
name: __classPrivateFieldGet$2(state, _State_name, "f"),
|
|
1556
1670
|
isHalt: state.isHalt,
|
|
1557
|
-
overriddenHaltState: __classPrivateFieldGet$
|
|
1558
|
-
? { id: __classPrivateFieldGet$
|
|
1671
|
+
overriddenHaltState: __classPrivateFieldGet$2(state, _State_overriddenHaltState, "f")
|
|
1672
|
+
? { id: __classPrivateFieldGet$2(state, _State_overriddenHaltState, "f").id, name: __classPrivateFieldGet$2(state, _State_overriddenHaltState, "f").name }
|
|
1559
1673
|
: null,
|
|
1560
1674
|
transitions,
|
|
1561
1675
|
};
|
|
@@ -1601,20 +1715,37 @@ _a = State;
|
|
|
1601
1715
|
_State_wrapperCache = { value: new WeakMap() };
|
|
1602
1716
|
const haltState = new State(null);
|
|
1603
1717
|
|
|
1604
|
-
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1718
|
+
var __classPrivateFieldSet$1 = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1605
1719
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1606
1720
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1607
1721
|
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");
|
|
1608
1722
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1609
1723
|
};
|
|
1610
|
-
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1724
|
+
var __classPrivateFieldGet$1 = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1611
1725
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1612
1726
|
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");
|
|
1613
1727
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1614
1728
|
};
|
|
1615
1729
|
var _TuringMachine_tapeBlock;
|
|
1616
|
-
|
|
1617
|
-
|
|
1730
|
+
/**
|
|
1731
|
+
* @internal — package-private accessor key for `MachineState` instances yielded
|
|
1732
|
+
* by `runStepByStep`. Calling `machineState[MACHINE_STATE_INTERNAL]()` returns a
|
|
1733
|
+
* frozen snapshot of the engine's halt-stack at yield time (BEFORE this iter's
|
|
1734
|
+
* applyCommand / pop / push). Consumed by `DebugSession` for step-over /
|
|
1735
|
+
* step-out endpoint detection without exposing the stack to public API.
|
|
1736
|
+
*
|
|
1737
|
+
* Re-exported from this module so the sibling `DebugSession` module can import
|
|
1738
|
+
* it; intentionally NOT re-exported from the package's public `index.ts` —
|
|
1739
|
+
* downstream consumers shouldn't reach for the stack. Same pattern as
|
|
1740
|
+
* `STATE_INTERNAL` (#180).
|
|
1741
|
+
*/
|
|
1742
|
+
const MACHINE_STATE_INTERNAL = Symbol('MachineState.internal');
|
|
1743
|
+
/**
|
|
1744
|
+
* @internal — true iff `filter` matches `symbol` per the DebugConfig semantics.
|
|
1745
|
+
* undefined / [] -> never; true -> always; symbol[] -> exact membership.
|
|
1746
|
+
* Exported for sibling-module use in `DebugSession` (which now owns breakpoint
|
|
1747
|
+
* detection); NOT re-exported from the package's public `index.ts`.
|
|
1748
|
+
*/
|
|
1618
1749
|
function matchFilter(filter, symbol) {
|
|
1619
1750
|
if (filter === undefined)
|
|
1620
1751
|
return false;
|
|
@@ -1628,43 +1759,42 @@ class TuringMachine {
|
|
|
1628
1759
|
if (!tapeBlock) {
|
|
1629
1760
|
throw new Error('invalid tapeBlock');
|
|
1630
1761
|
}
|
|
1631
|
-
__classPrivateFieldSet(this, _TuringMachine_tapeBlock, tapeBlock, "f");
|
|
1762
|
+
__classPrivateFieldSet$1(this, _TuringMachine_tapeBlock, tapeBlock, "f");
|
|
1632
1763
|
}
|
|
1633
1764
|
get tapeBlock() {
|
|
1634
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f");
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1765
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f");
|
|
1766
|
+
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Run the machine to halt. Pure execution — synchronous, no observation
|
|
1769
|
+
* callbacks, no debug overhead. For breakpoint-driven interactive debugging
|
|
1770
|
+
* use `DebugSession`; for per-iter tracing use `runStepByStep`'s generator
|
|
1771
|
+
* directly.
|
|
1772
|
+
*
|
|
1773
|
+
* Breakpoint metadata (`state.debug` / `haltState.debug` matches) is still
|
|
1774
|
+
* resolved and attached to each yielded MachineState by the underlying
|
|
1775
|
+
* generator — `run()` simply doesn't dispatch on it. A consumer that wants
|
|
1776
|
+
* to dispatch on it constructs a `DebugSession` instead.
|
|
1777
|
+
*
|
|
1778
|
+
* Symmetric reversal of v4's `run` → `async run` change: v4 made the method
|
|
1779
|
+
* async to support awaited `onPause`; with callbacks moved to `DebugSession`
|
|
1780
|
+
* there's no async work left, so the method returns `void` again.
|
|
1781
|
+
*/
|
|
1782
|
+
run({ initialState, stepsLimit = 1e5 }) {
|
|
1783
|
+
// Drain the generator. We don't care about the yielded values — the
|
|
1784
|
+
// generator's job is to advance the tape; only side effects matter here.
|
|
1785
|
+
// Casting to unknown so eslint doesn't flag the unused `_` variable.
|
|
1786
|
+
for (const machineState of this.runStepByStep({ initialState, stepsLimit })) {
|
|
1654
1787
|
}
|
|
1655
1788
|
}
|
|
1656
1789
|
*runStepByStep({ initialState, stepsLimit = 1e5 }) {
|
|
1657
1790
|
const executionSymbol = Symbol('execution');
|
|
1658
1791
|
try {
|
|
1659
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].check(executionSymbol);
|
|
1660
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].lock(executionSymbol);
|
|
1661
|
-
// Halt-stack is run-scoped, not machine-scoped (#196)
|
|
1662
|
-
//
|
|
1663
|
-
//
|
|
1664
|
-
//
|
|
1665
|
-
// halt-bound transition. Before this change `#stack` was an instance
|
|
1666
|
-
// field and accumulated one extra push per call when the same machine
|
|
1667
|
-
// was reused.
|
|
1792
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].check(executionSymbol);
|
|
1793
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].lock(executionSymbol);
|
|
1794
|
+
// Halt-stack is run-scoped, not machine-scoped (#196) — local
|
|
1795
|
+
// declaration prevents leftover entries from a previous
|
|
1796
|
+
// `runStepByStep` call (e.g. a build-time peek that never drained
|
|
1797
|
+
// the generator) from leaking into a subsequent halt-bound transition.
|
|
1668
1798
|
const stack = [];
|
|
1669
1799
|
let state = initialState;
|
|
1670
1800
|
if (state.overriddenHaltState) {
|
|
@@ -1676,30 +1806,43 @@ class TuringMachine {
|
|
|
1676
1806
|
throw new Error('Long execution');
|
|
1677
1807
|
}
|
|
1678
1808
|
i += 1;
|
|
1679
|
-
const symbol = state.getSymbol(__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f"));
|
|
1809
|
+
const symbol = state.getSymbol(__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f"));
|
|
1680
1810
|
const command = state.getCommand(symbol);
|
|
1681
|
-
|
|
1811
|
+
const matched = state.getMatchedTransition(symbol);
|
|
1812
|
+
let nextState = matched.nextState.ref;
|
|
1813
|
+
// For wrapper-entry iters, the wrapper's transitions in `toGraph`
|
|
1814
|
+
// are empty (wrappers delegate to the bare via shared
|
|
1815
|
+
// `#symbolToDataMap`); the resolvable transition id lives under
|
|
1816
|
+
// the bare's stateId. `bareState` is non-null only when `state`
|
|
1817
|
+
// is a wrapper produced by `withOverriddenHaltState`. Accessed
|
|
1818
|
+
// via the STATE_INTERNAL package-private view (same pattern
|
|
1819
|
+
// `utilities/stateGraph.ts` uses) to avoid widening the public
|
|
1820
|
+
// State API for this internal need.
|
|
1821
|
+
const stateInternal = state[STATE_INTERNAL]();
|
|
1822
|
+
const resolvableStateId = stateInternal.bareState?.id ?? state.id;
|
|
1823
|
+
const matchedTransition = {
|
|
1824
|
+
id: `${resolvableStateId}.${matched.ix}`,
|
|
1825
|
+
matchKinds: __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").patternKinds(matched.matchedSymbol),
|
|
1826
|
+
};
|
|
1682
1827
|
try {
|
|
1683
|
-
//
|
|
1684
|
-
//
|
|
1685
|
-
//
|
|
1686
|
-
|
|
1687
|
-
|| (nextState.isHalt && nextState.debug?.before === true);
|
|
1688
|
-
const afterMatch = matchFilter(state.debug?.after, symbol);
|
|
1828
|
+
// `runStepByStep` is the minimal execution primitive: it advances the
|
|
1829
|
+
// machine and reports state. It does NO breakpoint detection — that's
|
|
1830
|
+
// a debug concern that lives entirely in `DebugSession`. The yielded
|
|
1831
|
+
// `MachineState` has no `pause` / `debugBreak` field.
|
|
1689
1832
|
const nextStateForYield = nextState.isHalt && stack.length
|
|
1690
1833
|
? stack.slice(-1)[0]
|
|
1691
1834
|
: nextState;
|
|
1692
1835
|
const yielded = {
|
|
1693
1836
|
step: i,
|
|
1694
1837
|
state,
|
|
1695
|
-
currentSymbols: __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").currentSymbols,
|
|
1838
|
+
currentSymbols: __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").currentSymbols,
|
|
1696
1839
|
nextSymbols: command.tapesCommands.map((tapeCommand, ix) => {
|
|
1697
1840
|
if (typeof tapeCommand.symbol === 'symbol') {
|
|
1698
1841
|
switch (tapeCommand.symbol) {
|
|
1699
1842
|
case symbolCommands.erase:
|
|
1700
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].alphabet.blankSymbol;
|
|
1843
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").tapes[ix].alphabet.blankSymbol;
|
|
1701
1844
|
case symbolCommands.keep:
|
|
1702
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].symbol;
|
|
1845
|
+
return __classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").tapes[ix].symbol;
|
|
1703
1846
|
default:
|
|
1704
1847
|
throw new Error('invalid symbol command');
|
|
1705
1848
|
}
|
|
@@ -1708,17 +1851,26 @@ class TuringMachine {
|
|
|
1708
1851
|
}),
|
|
1709
1852
|
movements: command.tapesCommands.map((tapeCommand) => tapeCommand.movement),
|
|
1710
1853
|
nextState: nextStateForYield,
|
|
1854
|
+
matchedTransition,
|
|
1711
1855
|
};
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1856
|
+
// #102: expose the pre-iter halt-stack + the matched symbol to
|
|
1857
|
+
// DebugSession via a Symbol-keyed accessor (non-enumerable, so it
|
|
1858
|
+
// doesn't leak into serialization / spread / toEqual). The stack
|
|
1859
|
+
// snapshot is frozen so a consumer holding a reference can't mutate
|
|
1860
|
+
// the engine's stack. DebugSession reads `matchedSymbol` to evaluate
|
|
1861
|
+
// `state.debug` filters — keeping breakpoint detection out of this
|
|
1862
|
+
// primitive.
|
|
1863
|
+
const stackSnapshot = Object.freeze(stack.slice());
|
|
1864
|
+
// Snapshot halt-imminence on the RAW nextState NOW, before the
|
|
1865
|
+
// post-yield pop reassigns `nextState` — so the closure can't capture
|
|
1866
|
+
// the mutated value.
|
|
1867
|
+
const haltImminent = nextState === haltState;
|
|
1868
|
+
Object.defineProperty(yielded, MACHINE_STATE_INTERNAL, {
|
|
1869
|
+
value: () => ({ stack: stackSnapshot, matchedSymbol: symbol, haltImminent }),
|
|
1870
|
+
enumerable: false,
|
|
1871
|
+
});
|
|
1720
1872
|
yield yielded;
|
|
1721
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").applyCommand(command, executionSymbol);
|
|
1873
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f").applyCommand(command, executionSymbol);
|
|
1722
1874
|
if (nextState.isHalt && stack.length) {
|
|
1723
1875
|
nextState = stack.pop();
|
|
1724
1876
|
}
|
|
@@ -1736,12 +1888,312 @@ class TuringMachine {
|
|
|
1736
1888
|
}
|
|
1737
1889
|
}
|
|
1738
1890
|
finally {
|
|
1739
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].unlock(executionSymbol);
|
|
1891
|
+
__classPrivateFieldGet$1(this, _TuringMachine_tapeBlock, "f")[lockSymbol].unlock(executionSymbol);
|
|
1740
1892
|
}
|
|
1741
1893
|
}
|
|
1742
1894
|
}
|
|
1743
1895
|
_TuringMachine_tapeBlock = new WeakMap();
|
|
1744
1896
|
|
|
1897
|
+
var __classPrivateFieldSet = (undefined && undefined.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
1898
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
1899
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
1900
|
+
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");
|
|
1901
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
1902
|
+
};
|
|
1903
|
+
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
1904
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
1905
|
+
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");
|
|
1906
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
1907
|
+
};
|
|
1908
|
+
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;
|
|
1909
|
+
/**
|
|
1910
|
+
* Interactive debugger session for `TuringMachine`. Owns the coordination
|
|
1911
|
+
* layer that every UI debugger / IDE extension / educational demo would
|
|
1912
|
+
* otherwise reimplement: breakpoint dispatch, step-in / step-over / step-out,
|
|
1913
|
+
* click-pause from outside, per-iter throttle, pause/resume promise plumbing.
|
|
1914
|
+
*
|
|
1915
|
+
* Construction is direct — the engine class stays minimal and doesn't expose a
|
|
1916
|
+
* `debugRun()` factory; consumers import both classes and write
|
|
1917
|
+
* `new DebugSession(machine, {initialState})`.
|
|
1918
|
+
*
|
|
1919
|
+
* Lifecycle:
|
|
1920
|
+
* const session = new DebugSession(machine, {initialState});
|
|
1921
|
+
* session.on('pause', (m) => { ...; session.continue(); });
|
|
1922
|
+
* session.on('halt', () => { ... });
|
|
1923
|
+
* await session.start(); // resolves on natural halt or stop()
|
|
1924
|
+
*
|
|
1925
|
+
* Each session is single-use: `start()` may only be called once. Construct a
|
|
1926
|
+
* fresh session to re-run.
|
|
1927
|
+
*/
|
|
1928
|
+
class DebugSession {
|
|
1929
|
+
constructor(machine, parameter) {
|
|
1930
|
+
_DebugSession_instances.add(this);
|
|
1931
|
+
_DebugSession_machine.set(this, void 0);
|
|
1932
|
+
_DebugSession_parameter.set(this, void 0);
|
|
1933
|
+
_DebugSession_listeners.set(this, {
|
|
1934
|
+
pause: [],
|
|
1935
|
+
step: [],
|
|
1936
|
+
iter: [],
|
|
1937
|
+
halt: [],
|
|
1938
|
+
});
|
|
1939
|
+
_DebugSession_started.set(this, false);
|
|
1940
|
+
_DebugSession_stopped.set(this, false);
|
|
1941
|
+
_DebugSession_iterating.set(this, false);
|
|
1942
|
+
_DebugSession_pauseResolver.set(this, null);
|
|
1943
|
+
_DebugSession_activeStepMode.set(this, null);
|
|
1944
|
+
/**
|
|
1945
|
+
* Halt-stack DEPTH snapshotted at the most recent pause dispatch (= number
|
|
1946
|
+
* of frames on the stack). DevTools-style step granularity is depth-based:
|
|
1947
|
+
* stepOver pauses at the next iter with `depth <= clickTimeDepth` (skip
|
|
1948
|
+
* frames the stepped-over iter pushes, pause back at the start level);
|
|
1949
|
+
* stepOut at `depth < clickTimeDepth` (the current frame itself exited).
|
|
1950
|
+
* Captured on EVERY pause so a step* call from the listener can freeze it.
|
|
1951
|
+
*/
|
|
1952
|
+
_DebugSession_capturedDepth.set(this, 0);
|
|
1953
|
+
/** The click-time depth frozen when a stepOver / stepOut directive is issued. */
|
|
1954
|
+
_DebugSession_clickTimeDepth.set(this, 0);
|
|
1955
|
+
_DebugSession_runIntervalMs.set(this, 0);
|
|
1956
|
+
_DebugSession_pauseRequested.set(this, false);
|
|
1957
|
+
__classPrivateFieldSet(this, _DebugSession_machine, machine, "f");
|
|
1958
|
+
__classPrivateFieldSet(this, _DebugSession_parameter, parameter, "f");
|
|
1959
|
+
}
|
|
1960
|
+
on(event, listener) {
|
|
1961
|
+
__classPrivateFieldGet(this, _DebugSession_listeners, "f")[event].push(listener);
|
|
1962
|
+
return this;
|
|
1963
|
+
}
|
|
1964
|
+
off(event, listener) {
|
|
1965
|
+
const arr = __classPrivateFieldGet(this, _DebugSession_listeners, "f")[event];
|
|
1966
|
+
const ix = arr.indexOf(listener);
|
|
1967
|
+
if (ix >= 0)
|
|
1968
|
+
arr.splice(ix, 1);
|
|
1969
|
+
return this;
|
|
1970
|
+
}
|
|
1971
|
+
stop() {
|
|
1972
|
+
__classPrivateFieldSet(this, _DebugSession_stopped, true, "f");
|
|
1973
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Request a pause from outside the run loop. The pause fires on the next
|
|
1977
|
+
* iter's before-side with `cause: 'manual'`. If a breakpoint matches that
|
|
1978
|
+
* same iter, the breakpoint takes precedence and the request is consumed
|
|
1979
|
+
* silently (one pause, cause: 'breakpoint').
|
|
1980
|
+
*
|
|
1981
|
+
* No-op if the session is already paused — the next `continue` / step call
|
|
1982
|
+
* resumes normal execution, then the flag fires on the iter AFTER that.
|
|
1983
|
+
* Equivalent to a debouncing one-shot.
|
|
1984
|
+
*/
|
|
1985
|
+
pause() {
|
|
1986
|
+
__classPrivateFieldSet(this, _DebugSession_pauseRequested, true, "f");
|
|
1987
|
+
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Set the per-iter throttle delay in milliseconds. After each iter (including
|
|
1990
|
+
* any pause + step + iter listeners on that iter), the loop awaits
|
|
1991
|
+
* `setTimeout(ms)` before proceeding to the next iter. `0` disables the
|
|
1992
|
+
* throttle.
|
|
1993
|
+
*
|
|
1994
|
+
* Useful for visualization UIs that want to animate execution at a fixed
|
|
1995
|
+
* pace. Updates take effect on the next iter.
|
|
1996
|
+
*/
|
|
1997
|
+
setRunInterval(ms) {
|
|
1998
|
+
if (!Number.isFinite(ms) || ms < 0) {
|
|
1999
|
+
throw new Error(`DebugSession.setRunInterval(${ms}): expected a non-negative finite number.`);
|
|
2000
|
+
}
|
|
2001
|
+
__classPrivateFieldSet(this, _DebugSession_runIntervalMs, ms, "f");
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Resume from the current pause, returning to normal execution until the
|
|
2005
|
+
* next breakpoint or natural halt. No-op when called outside of a paused
|
|
2006
|
+
* state.
|
|
2007
|
+
*/
|
|
2008
|
+
continue() {
|
|
2009
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, null, "f");
|
|
2010
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2011
|
+
}
|
|
2012
|
+
/**
|
|
2013
|
+
* Resume and force a pause on the next iter regardless of whether that
|
|
2014
|
+
* iter's `state.debug` filter matches. Step-mode is one-shot: any
|
|
2015
|
+
* subsequent pause dispatch (this step-in's endpoint, an inner
|
|
2016
|
+
* breakpoint, or a manual pause) drops it. To keep stepping, call
|
|
2017
|
+
* stepIn() again from the new pause.
|
|
2018
|
+
*/
|
|
2019
|
+
stepIn() {
|
|
2020
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-in', "f");
|
|
2021
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Resume and pause at the next iter back at (or above) the click-time depth
|
|
2025
|
+
* — i.e. `depth <= clickTimeDepth`. Frames the stepped-over iter pushes are
|
|
2026
|
+
* run to completion without pausing inside (the engine's continuation-passing
|
|
2027
|
+
* `withOverriddenHaltState` "calls"). Mirrors DevTools Step Over.
|
|
2028
|
+
*
|
|
2029
|
+
* For a plain iter (no frame push) this coincides with stepIn (next iter is
|
|
2030
|
+
* already at the same depth). The Over-vs-In / Over-vs-Out distinction only
|
|
2031
|
+
* appears under genuine nesting (a bare that itself enters a wrapper).
|
|
2032
|
+
*
|
|
2033
|
+
* One-shot: an inner breakpoint or any other pause drops the step-over
|
|
2034
|
+
* intent. The endpoint pause carries `cause: 'step'`.
|
|
2035
|
+
*/
|
|
2036
|
+
stepOver() {
|
|
2037
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-over', "f");
|
|
2038
|
+
__classPrivateFieldSet(this, _DebugSession_clickTimeDepth, __classPrivateFieldGet(this, _DebugSession_capturedDepth, "f"), "f");
|
|
2039
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Resume and pause at the next iter STRICTLY shallower than the click-time
|
|
2043
|
+
* depth — `depth < clickTimeDepth` — i.e. once the current frame itself has
|
|
2044
|
+
* been popped. Mirrors DevTools Step Out.
|
|
2045
|
+
*
|
|
2046
|
+
* Throws when the click-time depth is 0: there's no enclosing frame to exit
|
|
2047
|
+
* (IDE convention — "step out of nothing" is a programming error, not a
|
|
2048
|
+
* silent no-op).
|
|
2049
|
+
*/
|
|
2050
|
+
stepOut() {
|
|
2051
|
+
if (__classPrivateFieldGet(this, _DebugSession_capturedDepth, "f") === 0) {
|
|
2052
|
+
throw new Error('DebugSession.stepOut() called with an empty click-time halt-stack — there is no enclosing frame to exit.');
|
|
2053
|
+
}
|
|
2054
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, 'step-out', "f");
|
|
2055
|
+
__classPrivateFieldSet(this, _DebugSession_clickTimeDepth, __classPrivateFieldGet(this, _DebugSession_capturedDepth, "f"), "f");
|
|
2056
|
+
__classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_releasePause).call(this);
|
|
2057
|
+
}
|
|
2058
|
+
async start() {
|
|
2059
|
+
if (__classPrivateFieldGet(this, _DebugSession_started, "f")) {
|
|
2060
|
+
throw new Error('DebugSession.start() has already been called; construct a fresh session to re-run.');
|
|
2061
|
+
}
|
|
2062
|
+
__classPrivateFieldSet(this, _DebugSession_started, true, "f");
|
|
2063
|
+
try {
|
|
2064
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_drive).call(this);
|
|
2065
|
+
}
|
|
2066
|
+
catch (error) {
|
|
2067
|
+
// `runStepByStep` acquires the TapeBlock lock at its first advance. If
|
|
2068
|
+
// another DebugSession (or a bare `run()`) is already active on this
|
|
2069
|
+
// machine, that acquisition throws the low-level 'Lock check failed'.
|
|
2070
|
+
// Remap it to a message that names the real cause. The `#iterating`
|
|
2071
|
+
// guard scopes the remap to the startup acquisition only — once we hold
|
|
2072
|
+
// the lock and are iterating, a same-named error can't originate here.
|
|
2073
|
+
if (!__classPrivateFieldGet(this, _DebugSession_iterating, "f") && error instanceof Error && error.message === 'Lock check failed') {
|
|
2074
|
+
throw new Error('Cannot start this DebugSession: a run is already in progress on this machine. '
|
|
2075
|
+
+ 'Only one DebugSession or run() may be active on a TuringMachine at a time — '
|
|
2076
|
+
+ 'stop the active session (or let it halt) before starting another.');
|
|
2077
|
+
}
|
|
2078
|
+
throw error;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
_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() {
|
|
2083
|
+
const resolver = __classPrivateFieldGet(this, _DebugSession_pauseResolver, "f");
|
|
2084
|
+
if (resolver) {
|
|
2085
|
+
__classPrivateFieldSet(this, _DebugSession_pauseResolver, null, "f");
|
|
2086
|
+
resolver();
|
|
2087
|
+
}
|
|
2088
|
+
}, _DebugSession_dispatchPause =
|
|
2089
|
+
/**
|
|
2090
|
+
* Emit a `pause` event with the synthesized pause descriptor and await the
|
|
2091
|
+
* consumer's resume signal. Resolver is installed BEFORE listeners fire so a listener
|
|
2092
|
+
* that synchronously calls `session.continue()` (or any other resume method)
|
|
2093
|
+
* sees a live resolver to drop.
|
|
2094
|
+
*
|
|
2095
|
+
* One-shot rule: any pause dispatch (step-mode endpoint, inner breakpoint,
|
|
2096
|
+
* manual pause) drops the active step-mode BEFORE listeners fire. Listeners
|
|
2097
|
+
* that want to keep stepping must call stepIn/Over/Out from the new pause.
|
|
2098
|
+
*
|
|
2099
|
+
* The pre-iter halt-stack DEPTH is snapshotted into `#capturedDepth` so a
|
|
2100
|
+
* `stepOver` / `stepOut` issued from inside the listener can freeze it as
|
|
2101
|
+
* the click-time depth.
|
|
2102
|
+
*/
|
|
2103
|
+
async function _DebugSession_dispatchPause(machineState, pause) {
|
|
2104
|
+
__classPrivateFieldSet(this, _DebugSession_activeStepMode, null, "f");
|
|
2105
|
+
__classPrivateFieldSet(this, _DebugSession_capturedDepth, __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readStack).call(this, machineState).length, "f");
|
|
2106
|
+
// Note: the spread drops the non-enumerable MACHINE_STATE_INTERNAL Symbol
|
|
2107
|
+
// accessor — that's intentional. Pause listeners are public API; the
|
|
2108
|
+
// Symbol accessor is package-private and only consumed by the session's
|
|
2109
|
+
// OWN detection (which reads the original `machineState` via #readInternal).
|
|
2110
|
+
const paused = { ...machineState, pause };
|
|
2111
|
+
const pausePromise = new Promise((resolve) => {
|
|
2112
|
+
__classPrivateFieldSet(this, _DebugSession_pauseResolver, resolve, "f");
|
|
2113
|
+
});
|
|
2114
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").pause) {
|
|
2115
|
+
void fn(paused);
|
|
2116
|
+
}
|
|
2117
|
+
await pausePromise;
|
|
2118
|
+
}, _DebugSession_readInternal = function _DebugSession_readInternal(machineState) {
|
|
2119
|
+
const fn = machineState[MACHINE_STATE_INTERNAL];
|
|
2120
|
+
return typeof fn === 'function' ? fn() : null;
|
|
2121
|
+
}, _DebugSession_readStack = function _DebugSession_readStack(machineState) {
|
|
2122
|
+
return __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readInternal).call(this, machineState)?.stack ?? [];
|
|
2123
|
+
}, _DebugSession_drive = async function _DebugSession_drive() {
|
|
2124
|
+
for (const machineState of __classPrivateFieldGet(this, _DebugSession_machine, "f").runStepByStep(__classPrivateFieldGet(this, _DebugSession_parameter, "f"))) {
|
|
2125
|
+
__classPrivateFieldSet(this, _DebugSession_iterating, true, "f");
|
|
2126
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2127
|
+
return;
|
|
2128
|
+
// Breakpoint detection lives HERE (not in the generator). Evaluate the
|
|
2129
|
+
// current state's debug filters against the matched symbol the generator
|
|
2130
|
+
// stashed in the internal accessor. `machineState.state` is always
|
|
2131
|
+
// non-halt (halt is terminal), so `.debug` is a DebugConfig at runtime.
|
|
2132
|
+
// The after side also fires on halt-imminent (`haltState.debug`, #207) —
|
|
2133
|
+
// read via the internal flag, since the yielded `nextState` shows the
|
|
2134
|
+
// post-pop continuation on subroutine-return iters, not haltState.
|
|
2135
|
+
const internal = __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readInternal).call(this, machineState);
|
|
2136
|
+
const matchedSymbol = internal?.matchedSymbol;
|
|
2137
|
+
const hasBeforeBreakpoint = matchedSymbol !== undefined
|
|
2138
|
+
&& matchFilter(machineState.state.debug?.before, matchedSymbol);
|
|
2139
|
+
const hasAfterBreakpoint = (matchedSymbol !== undefined
|
|
2140
|
+
&& matchFilter(machineState.state.debug?.after, matchedSymbol))
|
|
2141
|
+
|| (internal?.haltImminent === true && haltState.debug === true);
|
|
2142
|
+
const stepInForcesPause = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-in';
|
|
2143
|
+
// Depth-based endpoints (DevTools semantics). currentDepth = pre-iter
|
|
2144
|
+
// halt-stack length. stepOver: back at/above click-time depth (skip
|
|
2145
|
+
// pushed frames). stepOut: strictly shallower (current frame exited).
|
|
2146
|
+
const currentDepth = __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_readStack).call(this, machineState).length;
|
|
2147
|
+
const stepOverEndpointReached = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-over' && currentDepth <= __classPrivateFieldGet(this, _DebugSession_clickTimeDepth, "f");
|
|
2148
|
+
const stepOutEndpointReached = __classPrivateFieldGet(this, _DebugSession_activeStepMode, "f") === 'step-out' && currentDepth < __classPrivateFieldGet(this, _DebugSession_clickTimeDepth, "f");
|
|
2149
|
+
// Consume the manual-pause flag at iter start. If a breakpoint also
|
|
2150
|
+
// matches this iter, the request is silently consumed by the
|
|
2151
|
+
// breakpoint dispatch (one pause, cause: 'breakpoint').
|
|
2152
|
+
const manualPauseFires = __classPrivateFieldGet(this, _DebugSession_pauseRequested, "f");
|
|
2153
|
+
if (manualPauseFires)
|
|
2154
|
+
__classPrivateFieldSet(this, _DebugSession_pauseRequested, false, "f");
|
|
2155
|
+
// Before-side pause: fires if any of breakpoint / step-mode endpoint /
|
|
2156
|
+
// manual request is true. Precedence: breakpoint > step > manual.
|
|
2157
|
+
const fireBeforePause = hasBeforeBreakpoint || stepInForcesPause || stepOverEndpointReached || stepOutEndpointReached || manualPauseFires;
|
|
2158
|
+
if (fireBeforePause) {
|
|
2159
|
+
const cause = hasBeforeBreakpoint ? 'breakpoint'
|
|
2160
|
+
: (stepInForcesPause || stepOverEndpointReached || stepOutEndpointReached) ? 'step'
|
|
2161
|
+
: 'manual';
|
|
2162
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_dispatchPause).call(this, machineState, { side: 'before', cause });
|
|
2163
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
// step: fires once per iter, after any before-pause and before any after-pause.
|
|
2167
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").step) {
|
|
2168
|
+
void fn(machineState);
|
|
2169
|
+
}
|
|
2170
|
+
if (hasAfterBreakpoint) {
|
|
2171
|
+
await __classPrivateFieldGet(this, _DebugSession_instances, "m", _DebugSession_dispatchPause).call(this, machineState, { side: 'after', cause: 'breakpoint' });
|
|
2172
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
// iter: end-of-iter, after both before- and after-pause have fired.
|
|
2176
|
+
// Listeners are AWAITED (sequenced, blocking the engine) — matches the
|
|
2177
|
+
// v6 `onIter` contract that downstream consumers rely on for
|
|
2178
|
+
// throttle / per-iter coordination / step-boundary synthesis.
|
|
2179
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").iter) {
|
|
2180
|
+
await fn(machineState);
|
|
2181
|
+
}
|
|
2182
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2183
|
+
return;
|
|
2184
|
+
if (__classPrivateFieldGet(this, _DebugSession_runIntervalMs, "f") > 0) {
|
|
2185
|
+
await new Promise((resolve) => setTimeout(resolve, __classPrivateFieldGet(this, _DebugSession_runIntervalMs, "f")));
|
|
2186
|
+
if (__classPrivateFieldGet(this, _DebugSession_stopped, "f"))
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
if (!__classPrivateFieldGet(this, _DebugSession_stopped, "f")) {
|
|
2191
|
+
for (const fn of __classPrivateFieldGet(this, _DebugSession_listeners, "f").halt) {
|
|
2192
|
+
void fn();
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
|
|
1745
2197
|
// Format converters between a Graph (the data model produced by State.toGraph
|
|
1746
2198
|
// and consumed by State.fromGraph) and external string representations.
|
|
1747
2199
|
//
|
|
@@ -1851,6 +2303,8 @@ function unescapeMermaidLabel(s) {
|
|
|
1851
2303
|
const n = Number.parseInt(hex, 16);
|
|
1852
2304
|
return n <= 0xFFFF ? String.fromCharCode(n) : String.fromCodePoint(n);
|
|
1853
2305
|
}
|
|
2306
|
+
/* c8 ignore next 2 — defensive: the regex shape guarantees one of
|
|
2307
|
+
named / dec / hex is always set, so this fallback is unreachable. */
|
|
1854
2308
|
return match;
|
|
1855
2309
|
}
|
|
1856
2310
|
}
|
|
@@ -2455,10 +2909,10 @@ function summarizeGraph(graph) {
|
|
|
2455
2909
|
}
|
|
2456
2910
|
let hasCycles = false;
|
|
2457
2911
|
const visit = (id) => {
|
|
2458
|
-
// No `if (hasCycles) return` guard at function entry: the
|
|
2459
|
-
//
|
|
2460
|
-
//
|
|
2461
|
-
//
|
|
2912
|
+
// No `if (hasCycles) return` guard at function entry: the call pattern
|
|
2913
|
+
// (outer for-loop checks before calling, inner loop checks after each
|
|
2914
|
+
// recursive call) ensures visit() is never invoked when hasCycles is
|
|
2915
|
+
// already true.
|
|
2462
2916
|
if (color.get(id) === GREY) {
|
|
2463
2917
|
hasCycles = true;
|
|
2464
2918
|
return;
|
|
@@ -2577,6 +3031,7 @@ function runOnce(runnable, input, stepsLimit) {
|
|
|
2577
3031
|
exports.Alphabet = Alphabet;
|
|
2578
3032
|
exports.Command = Command;
|
|
2579
3033
|
exports.DebugConfig = DebugConfig;
|
|
3034
|
+
exports.DebugSession = DebugSession;
|
|
2580
3035
|
exports.Reference = Reference;
|
|
2581
3036
|
exports.State = State;
|
|
2582
3037
|
exports.Tape = Tape;
|