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