@turing-machine-js/machine 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/index.cjs +17 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +17 -9
- package/package.json +2 -2
- package/dist/classes/Alphabet.js +0 -50
- package/dist/classes/Command.js +0 -38
- package/dist/classes/Lock.js +0 -34
- package/dist/classes/Reference.js +0 -31
- package/dist/classes/State.js +0 -283
- package/dist/classes/Tape.js +0 -95
- package/dist/classes/TapeBlock.js +0 -197
- package/dist/classes/TapeCommand.js +0 -46
- package/dist/classes/TuringMachine.js +0 -102
- package/dist/index.js +0 -11
- package/dist/utilities/equivalence.js +0 -68
- package/dist/utilities/functions.js +0 -13
- package/dist/utilities/graph.js +0 -127
- package/dist/utilities/graphFormats.js +0 -141
- package/dist/utilities/introspection.js +0 -88
package/dist/classes/Tape.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
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");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _Tape_alphabet, _Tape_symbols, _Tape_position, _Tape_viewportWidth;
|
|
13
|
-
import Alphabet from './Alphabet';
|
|
14
|
-
class Tape {
|
|
15
|
-
constructor({ alphabet, symbols = [], position = 0, viewportWidth = 1, }) {
|
|
16
|
-
_Tape_alphabet.set(this, void 0);
|
|
17
|
-
_Tape_symbols.set(this, void 0);
|
|
18
|
-
_Tape_position.set(this, void 0);
|
|
19
|
-
_Tape_viewportWidth.set(this, void 0);
|
|
20
|
-
const isSymbolsValid = symbols.every((symbol) => alphabet.has(symbol));
|
|
21
|
-
if (!isSymbolsValid) {
|
|
22
|
-
throw new Error('symbolList contains invalid symbol');
|
|
23
|
-
}
|
|
24
|
-
__classPrivateFieldSet(this, _Tape_alphabet, new Alphabet(alphabet), "f");
|
|
25
|
-
__classPrivateFieldSet(this, _Tape_position, position, "f");
|
|
26
|
-
__classPrivateFieldSet(this, _Tape_viewportWidth, viewportWidth, "f");
|
|
27
|
-
const symbolsCopy = Array.from(symbols);
|
|
28
|
-
if (symbolsCopy.length === 0) {
|
|
29
|
-
symbolsCopy.push(__classPrivateFieldGet(this, _Tape_alphabet, "f").blankSymbol);
|
|
30
|
-
}
|
|
31
|
-
__classPrivateFieldSet(this, _Tape_symbols, symbolsCopy.map((symbol) => __classPrivateFieldGet(this, _Tape_alphabet, "f").index(symbol)), "f");
|
|
32
|
-
}
|
|
33
|
-
get alphabet() {
|
|
34
|
-
return __classPrivateFieldGet(this, _Tape_alphabet, "f");
|
|
35
|
-
}
|
|
36
|
-
get extraCellsCount() {
|
|
37
|
-
return (__classPrivateFieldGet(this, _Tape_viewportWidth, "f") - 1) / 2;
|
|
38
|
-
}
|
|
39
|
-
get position() {
|
|
40
|
-
return __classPrivateFieldGet(this, _Tape_position, "f");
|
|
41
|
-
}
|
|
42
|
-
get symbol() {
|
|
43
|
-
return __classPrivateFieldGet(this, _Tape_alphabet, "f").get(__classPrivateFieldGet(this, _Tape_symbols, "f")[__classPrivateFieldGet(this, _Tape_position, "f")]);
|
|
44
|
-
}
|
|
45
|
-
set symbol(symbol) {
|
|
46
|
-
if (!__classPrivateFieldGet(this, _Tape_alphabet, "f").has(symbol)) {
|
|
47
|
-
throw new Error('Invalid symbol');
|
|
48
|
-
}
|
|
49
|
-
__classPrivateFieldGet(this, _Tape_symbols, "f")[__classPrivateFieldGet(this, _Tape_position, "f")] = __classPrivateFieldGet(this, _Tape_alphabet, "f").index(symbol);
|
|
50
|
-
}
|
|
51
|
-
get symbols() {
|
|
52
|
-
return __classPrivateFieldGet(this, _Tape_symbols, "f")
|
|
53
|
-
.map((index) => __classPrivateFieldGet(this, _Tape_alphabet, "f").get(index));
|
|
54
|
-
}
|
|
55
|
-
get viewport() {
|
|
56
|
-
const startIx = __classPrivateFieldGet(this, _Tape_position, "f") - this.extraCellsCount;
|
|
57
|
-
const endIx = __classPrivateFieldGet(this, _Tape_position, "f") + this.extraCellsCount + 1;
|
|
58
|
-
return __classPrivateFieldGet(this, _Tape_symbols, "f")
|
|
59
|
-
.slice(startIx, endIx)
|
|
60
|
-
.map((index) => __classPrivateFieldGet(this, _Tape_alphabet, "f").get(index));
|
|
61
|
-
}
|
|
62
|
-
get viewportWidth() {
|
|
63
|
-
return __classPrivateFieldGet(this, _Tape_viewportWidth, "f");
|
|
64
|
-
}
|
|
65
|
-
set viewportWidth(width) {
|
|
66
|
-
let finalWidth = width;
|
|
67
|
-
if (finalWidth < 1) {
|
|
68
|
-
throw new Error('Invalid viewportWidth');
|
|
69
|
-
}
|
|
70
|
-
if (finalWidth % 2 === 0) {
|
|
71
|
-
finalWidth += 1;
|
|
72
|
-
}
|
|
73
|
-
__classPrivateFieldSet(this, _Tape_viewportWidth, finalWidth, "f");
|
|
74
|
-
this.normalise();
|
|
75
|
-
}
|
|
76
|
-
left() {
|
|
77
|
-
__classPrivateFieldSet(this, _Tape_position, __classPrivateFieldGet(this, _Tape_position, "f") - 1, "f");
|
|
78
|
-
this.normalise();
|
|
79
|
-
}
|
|
80
|
-
normalise() {
|
|
81
|
-
while (__classPrivateFieldGet(this, _Tape_position, "f") - this.extraCellsCount < 0) {
|
|
82
|
-
__classPrivateFieldGet(this, _Tape_symbols, "f").unshift(0);
|
|
83
|
-
__classPrivateFieldSet(this, _Tape_position, __classPrivateFieldGet(this, _Tape_position, "f") + 1, "f");
|
|
84
|
-
}
|
|
85
|
-
while (__classPrivateFieldGet(this, _Tape_position, "f") + this.extraCellsCount >= __classPrivateFieldGet(this, _Tape_symbols, "f").length) {
|
|
86
|
-
__classPrivateFieldGet(this, _Tape_symbols, "f").push(0);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
right() {
|
|
90
|
-
__classPrivateFieldSet(this, _Tape_position, __classPrivateFieldGet(this, _Tape_position, "f") + 1, "f");
|
|
91
|
-
this.normalise();
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
_Tape_alphabet = new WeakMap(), _Tape_symbols = new WeakMap(), _Tape_position = new WeakMap(), _Tape_viewportWidth = new WeakMap();
|
|
95
|
-
export default Tape;
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
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");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _a, _TapeBlock_symbolToPatternListMap, _TapeBlock_lock, _TapeBlock_tapes, _TapeBlock_generateSymbolHint, _TapeBlock_buildPatternList, _TapeBlock_getSymbolForPatternList, _TapeBlock_symbol;
|
|
13
|
-
import Tape from './Tape';
|
|
14
|
-
import { ifOtherSymbol } from './State';
|
|
15
|
-
import { movements, symbolCommands } from './TapeCommand';
|
|
16
|
-
import Lock from './Lock';
|
|
17
|
-
const symbolToPatternListMapSymbol = Symbol('symbol for symbolToPatternListMap setter');
|
|
18
|
-
export const lockSymbol = Symbol('capture symbol');
|
|
19
|
-
class TapeBlock {
|
|
20
|
-
constructor(argument) {
|
|
21
|
-
_TapeBlock_symbolToPatternListMap.set(this, new Map());
|
|
22
|
-
_TapeBlock_lock.set(this, new Lock());
|
|
23
|
-
_TapeBlock_tapes.set(this, void 0);
|
|
24
|
-
_TapeBlock_buildPatternList.set(this, (symbolList) => symbolList.reduce((result, symbol, ix) => {
|
|
25
|
-
const row = Math.floor(ix / __classPrivateFieldGet(this, _TapeBlock_tapes, "f").length);
|
|
26
|
-
if (!Array.isArray(result[row])) {
|
|
27
|
-
result[row] = [];
|
|
28
|
-
}
|
|
29
|
-
result[row].push(symbol);
|
|
30
|
-
return result;
|
|
31
|
-
}, [])
|
|
32
|
-
.filter((pattern, ix, patternList) => {
|
|
33
|
-
const samePatternIx = patternList.findIndex((otherPattern) => (pattern
|
|
34
|
-
.every((symbol, symbolIx) => symbol === otherPattern[symbolIx])));
|
|
35
|
-
return samePatternIx === ix;
|
|
36
|
-
}));
|
|
37
|
-
_TapeBlock_getSymbolForPatternList.set(this, (patternList) => {
|
|
38
|
-
if (patternList.some((pattern) => pattern.every((symbol) => symbol === ifOtherSymbol))) {
|
|
39
|
-
return ifOtherSymbol;
|
|
40
|
-
}
|
|
41
|
-
const [storedPatternListSymbol] = [...__classPrivateFieldGet(this, _TapeBlock_symbolToPatternListMap, "f").entries()]
|
|
42
|
-
.find(([, storedPatternList]) => {
|
|
43
|
-
if (storedPatternList.length !== patternList.length) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
return patternList
|
|
47
|
-
.every((pattern, patternIx) => pattern
|
|
48
|
-
.every((symbol, symbolIx) => symbol === storedPatternList[patternIx][symbolIx]));
|
|
49
|
-
}) || [null, null];
|
|
50
|
-
let symbol;
|
|
51
|
-
if (storedPatternListSymbol) {
|
|
52
|
-
symbol = storedPatternListSymbol;
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
symbol = Symbol(__classPrivateFieldGet(_a, _a, "f", _TapeBlock_generateSymbolHint).call(_a, patternList));
|
|
56
|
-
__classPrivateFieldGet(this, _TapeBlock_symbolToPatternListMap, "f").set(symbol, patternList);
|
|
57
|
-
}
|
|
58
|
-
return symbol;
|
|
59
|
-
});
|
|
60
|
-
_TapeBlock_symbol.set(this, (symbols) => {
|
|
61
|
-
let localSymbols = [];
|
|
62
|
-
if (symbols === ifOtherSymbol) {
|
|
63
|
-
return ifOtherSymbol;
|
|
64
|
-
}
|
|
65
|
-
if (typeof symbols === 'string') {
|
|
66
|
-
localSymbols = symbols.split('');
|
|
67
|
-
}
|
|
68
|
-
else if (Array.isArray(symbols)) {
|
|
69
|
-
localSymbols = [...symbols];
|
|
70
|
-
}
|
|
71
|
-
if (localSymbols.length === 0 || localSymbols.length % __classPrivateFieldGet(this, _TapeBlock_tapes, "f").length > 0) {
|
|
72
|
-
throw new Error('invalid symbol parameter');
|
|
73
|
-
}
|
|
74
|
-
const invalidSymbolIndex = localSymbols.findIndex((symbol, ix) => (symbol !== ifOtherSymbol
|
|
75
|
-
&& !__classPrivateFieldGet(this, _TapeBlock_tapes, "f")[ix % __classPrivateFieldGet(this, _TapeBlock_tapes, "f").length].alphabet.has(symbol)));
|
|
76
|
-
if (invalidSymbolIndex >= 0) {
|
|
77
|
-
throw new Error('invalid symbol parameter');
|
|
78
|
-
}
|
|
79
|
-
if (localSymbols.every((symbol) => symbol === ifOtherSymbol)) {
|
|
80
|
-
return ifOtherSymbol;
|
|
81
|
-
}
|
|
82
|
-
return __classPrivateFieldGet(this, _TapeBlock_getSymbolForPatternList, "f").call(this, __classPrivateFieldGet(this, _TapeBlock_buildPatternList, "f").call(this, localSymbols));
|
|
83
|
-
});
|
|
84
|
-
__classPrivateFieldSet(this, _TapeBlock_tapes, [], "f");
|
|
85
|
-
if ('alphabets' in argument) {
|
|
86
|
-
const { alphabets } = argument;
|
|
87
|
-
if (alphabets.length === 0) {
|
|
88
|
-
throw new Error('empty alphabet list');
|
|
89
|
-
}
|
|
90
|
-
__classPrivateFieldSet(this, _TapeBlock_tapes, alphabets.map((alphabet) => new Tape({
|
|
91
|
-
alphabet,
|
|
92
|
-
})), "f");
|
|
93
|
-
}
|
|
94
|
-
else if ('tapes' in argument) {
|
|
95
|
-
__classPrivateFieldSet(this, _TapeBlock_tapes, argument.tapes, "f");
|
|
96
|
-
}
|
|
97
|
-
if (__classPrivateFieldGet(this, _TapeBlock_tapes, "f").length === 0) {
|
|
98
|
-
throw new Error('empty tape list');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
get alphabets() {
|
|
102
|
-
return [...__classPrivateFieldGet(this, _TapeBlock_tapes, "f").map((tape) => tape.alphabet)];
|
|
103
|
-
}
|
|
104
|
-
get currentSymbols() {
|
|
105
|
-
return __classPrivateFieldGet(this, _TapeBlock_tapes, "f").map((tape) => tape.symbol);
|
|
106
|
-
}
|
|
107
|
-
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)]() {
|
|
108
|
-
return __classPrivateFieldGet(this, _TapeBlock_lock, "f");
|
|
109
|
-
}
|
|
110
|
-
get symbol() {
|
|
111
|
-
return __classPrivateFieldGet(this, _TapeBlock_symbol, "f").bind(this);
|
|
112
|
-
}
|
|
113
|
-
get tapes() {
|
|
114
|
-
return [...__classPrivateFieldGet(this, _TapeBlock_tapes, "f")];
|
|
115
|
-
}
|
|
116
|
-
set [symbolToPatternListMapSymbol](symbolToPatternListMap) {
|
|
117
|
-
__classPrivateFieldSet(this, _TapeBlock_symbolToPatternListMap, new Map(symbolToPatternListMap), "f");
|
|
118
|
-
}
|
|
119
|
-
applyCommand(command, executionSymbol = null) {
|
|
120
|
-
__classPrivateFieldGet(this, _TapeBlock_lock, "f").check(executionSymbol);
|
|
121
|
-
if (__classPrivateFieldGet(this, _TapeBlock_tapes, "f").length !== command.tapesCommands.length) {
|
|
122
|
-
throw new Error('invalid command');
|
|
123
|
-
}
|
|
124
|
-
__classPrivateFieldGet(this, _TapeBlock_tapes, "f").forEach((tape, ix) => {
|
|
125
|
-
const { movement, symbol } = command.tapesCommands[ix];
|
|
126
|
-
if (typeof symbol === 'string') {
|
|
127
|
-
tape.symbol = symbol;
|
|
128
|
-
}
|
|
129
|
-
if (typeof symbol === 'symbol') {
|
|
130
|
-
switch (symbol) {
|
|
131
|
-
case symbolCommands.keep:
|
|
132
|
-
break;
|
|
133
|
-
case symbolCommands.erase:
|
|
134
|
-
tape.symbol = tape.alphabet.blankSymbol;
|
|
135
|
-
break;
|
|
136
|
-
// no default
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
switch (movement) {
|
|
140
|
-
case movements.left:
|
|
141
|
-
tape.left();
|
|
142
|
-
break;
|
|
143
|
-
case movements.stay:
|
|
144
|
-
break;
|
|
145
|
-
case movements.right:
|
|
146
|
-
tape.right();
|
|
147
|
-
break;
|
|
148
|
-
// no default
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
clone(cloneTapes = false) {
|
|
153
|
-
let tapeBlock;
|
|
154
|
-
if (cloneTapes) {
|
|
155
|
-
tapeBlock = _a.fromTapes(this.tapes.map((tape) => new Tape(tape)));
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
tapeBlock = _a.fromAlphabets(this.alphabets);
|
|
159
|
-
}
|
|
160
|
-
tapeBlock[symbolToPatternListMapSymbol] = __classPrivateFieldGet(this, _TapeBlock_symbolToPatternListMap, "f");
|
|
161
|
-
return tapeBlock;
|
|
162
|
-
}
|
|
163
|
-
isMatched({ currentSymbols = this.currentSymbols, symbol }) {
|
|
164
|
-
if (symbol === ifOtherSymbol) {
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
if (!__classPrivateFieldGet(this, _TapeBlock_symbolToPatternListMap, "f").has(symbol)) {
|
|
168
|
-
throw new Error('invalid symbol');
|
|
169
|
-
}
|
|
170
|
-
const patternList = __classPrivateFieldGet(this, _TapeBlock_symbolToPatternListMap, "f").get(symbol);
|
|
171
|
-
return patternList?.some((pattern) => (pattern
|
|
172
|
-
.every((everySymbol, ix) => (everySymbol === ifOtherSymbol
|
|
173
|
-
|| everySymbol === currentSymbols[ix])))) ?? false;
|
|
174
|
-
}
|
|
175
|
-
replaceTape(tape, tapeIx = 0) {
|
|
176
|
-
if (__classPrivateFieldGet(this, _TapeBlock_tapes, "f")[tapeIx] == null) {
|
|
177
|
-
throw new Error('invalid tapeIx');
|
|
178
|
-
}
|
|
179
|
-
if (tape.alphabet.symbols.join('') === __classPrivateFieldGet(this, _TapeBlock_tapes, "f")[tapeIx].alphabet.symbols.join('')) {
|
|
180
|
-
__classPrivateFieldGet(this, _TapeBlock_tapes, "f")[tapeIx] = tape;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
throw new Error('invalid tape');
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
_a = TapeBlock;
|
|
188
|
-
TapeBlock.fromAlphabets = (alphabets) => {
|
|
189
|
-
return new _a({ alphabets });
|
|
190
|
-
};
|
|
191
|
-
TapeBlock.fromTapes = (tapes) => {
|
|
192
|
-
return new _a({ tapes });
|
|
193
|
-
};
|
|
194
|
-
_TapeBlock_generateSymbolHint = { value: (patternList) => JSON.stringify(patternList
|
|
195
|
-
.map((pattern) => pattern
|
|
196
|
-
.map((symbol) => (symbol === ifOtherSymbol ? null : symbol)))) };
|
|
197
|
-
export default TapeBlock;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
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");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _TapeCommand_movement, _TapeCommand_symbol;
|
|
13
|
-
export const movements = {
|
|
14
|
-
left: Symbol('move caret left command'),
|
|
15
|
-
right: Symbol('move caret right command'),
|
|
16
|
-
stay: Symbol('do not move carer'),
|
|
17
|
-
};
|
|
18
|
-
export const symbolCommands = {
|
|
19
|
-
erase: Symbol('erase symbol command'),
|
|
20
|
-
keep: Symbol('keep symbol command'),
|
|
21
|
-
};
|
|
22
|
-
class TapeCommand {
|
|
23
|
-
constructor({ movement = movements.stay, symbol = symbolCommands.keep, }) {
|
|
24
|
-
_TapeCommand_movement.set(this, void 0);
|
|
25
|
-
_TapeCommand_symbol.set(this, void 0);
|
|
26
|
-
const isValidMovement = [movements.left, movements.stay, movements.right].includes(movement);
|
|
27
|
-
if (!isValidMovement) {
|
|
28
|
-
throw new Error('invalid movement');
|
|
29
|
-
}
|
|
30
|
-
__classPrivateFieldSet(this, _TapeCommand_movement, movement, "f");
|
|
31
|
-
const isValidSymbol = ((typeof symbol === 'string' && symbol.length === 1)
|
|
32
|
-
|| [symbolCommands.keep, symbolCommands.erase].includes(symbol));
|
|
33
|
-
if (!isValidSymbol) {
|
|
34
|
-
throw new Error('invalid symbol');
|
|
35
|
-
}
|
|
36
|
-
__classPrivateFieldSet(this, _TapeCommand_symbol, symbol, "f");
|
|
37
|
-
}
|
|
38
|
-
get symbol() {
|
|
39
|
-
return __classPrivateFieldGet(this, _TapeCommand_symbol, "f");
|
|
40
|
-
}
|
|
41
|
-
get movement() {
|
|
42
|
-
return __classPrivateFieldGet(this, _TapeCommand_movement, "f");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
_TapeCommand_movement = new WeakMap(), _TapeCommand_symbol = new WeakMap();
|
|
46
|
-
export default TapeCommand;
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
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");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
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");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _TuringMachine_tapeBlock, _TuringMachine_stack;
|
|
13
|
-
import { haltState } from './State';
|
|
14
|
-
import { lockSymbol } from './TapeBlock';
|
|
15
|
-
import { symbolCommands } from './TapeCommand';
|
|
16
|
-
class TuringMachine {
|
|
17
|
-
constructor({ tapeBlock, } = {}) {
|
|
18
|
-
_TuringMachine_tapeBlock.set(this, void 0);
|
|
19
|
-
_TuringMachine_stack.set(this, []);
|
|
20
|
-
if (!tapeBlock) {
|
|
21
|
-
throw new Error('invalid tapeBlock');
|
|
22
|
-
}
|
|
23
|
-
__classPrivateFieldSet(this, _TuringMachine_tapeBlock, tapeBlock, "f");
|
|
24
|
-
}
|
|
25
|
-
get tapeBlock() {
|
|
26
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f");
|
|
27
|
-
}
|
|
28
|
-
run({ initialState, stepsLimit = 1e5, onStep }) {
|
|
29
|
-
const generator = this.runStepByStep({ initialState, stepsLimit });
|
|
30
|
-
for (const machineState of generator) {
|
|
31
|
-
if (onStep instanceof Function) {
|
|
32
|
-
onStep(machineState);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
*runStepByStep({ initialState, stepsLimit = 1e5 }) {
|
|
37
|
-
const executionSymbol = Symbol('execution');
|
|
38
|
-
try {
|
|
39
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].check(executionSymbol);
|
|
40
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].lock(executionSymbol);
|
|
41
|
-
const stack = __classPrivateFieldGet(this, _TuringMachine_stack, "f");
|
|
42
|
-
let state = initialState;
|
|
43
|
-
if (state.overrodeHaltState) {
|
|
44
|
-
stack.push(state.overrodeHaltState);
|
|
45
|
-
}
|
|
46
|
-
let i = 0;
|
|
47
|
-
while (!state.isHalt) {
|
|
48
|
-
if (i === stepsLimit) {
|
|
49
|
-
throw new Error('Long execution');
|
|
50
|
-
}
|
|
51
|
-
i += 1;
|
|
52
|
-
const symbol = state.getSymbol(__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f"));
|
|
53
|
-
const command = state.getCommand(symbol);
|
|
54
|
-
let nextState = state.getNextState(symbol).ref;
|
|
55
|
-
try {
|
|
56
|
-
const nextStateForYield = nextState.isHalt && stack.length
|
|
57
|
-
? stack.slice(-1)[0]
|
|
58
|
-
: nextState;
|
|
59
|
-
yield {
|
|
60
|
-
step: i,
|
|
61
|
-
state,
|
|
62
|
-
currentSymbols: __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").currentSymbols,
|
|
63
|
-
nextSymbols: command.tapesCommands.map((tapeCommand, ix) => {
|
|
64
|
-
if (typeof tapeCommand.symbol === 'symbol') {
|
|
65
|
-
switch (tapeCommand.symbol) {
|
|
66
|
-
case symbolCommands.erase:
|
|
67
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].alphabet.blankSymbol;
|
|
68
|
-
case symbolCommands.keep:
|
|
69
|
-
return __classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").tapes[ix].symbol;
|
|
70
|
-
default:
|
|
71
|
-
throw new Error('invalid symbol command');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return tapeCommand.symbol;
|
|
75
|
-
}),
|
|
76
|
-
movements: command.tapesCommands.map((tapeCommand) => tapeCommand.movement),
|
|
77
|
-
nextState: nextStateForYield,
|
|
78
|
-
};
|
|
79
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f").applyCommand(command, executionSymbol);
|
|
80
|
-
if (nextState.isHalt && stack.length) {
|
|
81
|
-
nextState = stack.pop();
|
|
82
|
-
}
|
|
83
|
-
if (state !== nextState && nextState.overrodeHaltState) {
|
|
84
|
-
stack.push(nextState.overrodeHaltState);
|
|
85
|
-
}
|
|
86
|
-
state = nextState;
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
if (error !== haltState) {
|
|
90
|
-
throw error;
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
finally {
|
|
97
|
-
__classPrivateFieldGet(this, _TuringMachine_tapeBlock, "f")[lockSymbol].unlock(executionSymbol);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
_TuringMachine_tapeBlock = new WeakMap(), _TuringMachine_stack = new WeakMap();
|
|
102
|
-
export default TuringMachine;
|
package/dist/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { default as Alphabet } from './classes/Alphabet';
|
|
2
|
-
export { default as Command } from './classes/Command';
|
|
3
|
-
export { default as Reference } from './classes/Reference';
|
|
4
|
-
export { default as State, haltState, ifOtherSymbol } from './classes/State';
|
|
5
|
-
export { default as Tape } from './classes/Tape';
|
|
6
|
-
export { default as TapeBlock } from './classes/TapeBlock';
|
|
7
|
-
export { default as TapeCommand, movements, symbolCommands } from './classes/TapeCommand';
|
|
8
|
-
export { default as TuringMachine } from './classes/TuringMachine';
|
|
9
|
-
export { toMermaid, fromMermaid } from './utilities/graphFormats';
|
|
10
|
-
export { summarize, summarizeGraph } from './utilities/introspection';
|
|
11
|
-
export { equivalentOn, } from './utilities/equivalence';
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import Tape from '../classes/Tape';
|
|
2
|
-
import TuringMachine from '../classes/TuringMachine';
|
|
3
|
-
const defaultCompare = (a, b) => a === b;
|
|
4
|
-
export function equivalentOn(reference, candidate, cases, options = {}) {
|
|
5
|
-
const compareOutputs = options.compareOutputs ?? defaultCompare;
|
|
6
|
-
const compareSnapshots = options.compareSnapshots === undefined
|
|
7
|
-
? defaultCompare
|
|
8
|
-
: options.compareSnapshots;
|
|
9
|
-
const stepsLimit = options.stepsLimit ?? 1e5;
|
|
10
|
-
const results = cases.map((c) => {
|
|
11
|
-
const pair = typeof c === 'string' ? { reference: c, candidate: c } : c;
|
|
12
|
-
const refRun = runOnce(reference, pair.reference, stepsLimit);
|
|
13
|
-
const candRun = runOnce(candidate, pair.candidate, stepsLimit);
|
|
14
|
-
const agree = compareOutputs(refRun.finalOutput, candRun.finalOutput);
|
|
15
|
-
let firstDivergenceStep = null;
|
|
16
|
-
if (!agree && compareSnapshots !== null) {
|
|
17
|
-
const minLen = Math.min(refRun.snapshots.length, candRun.snapshots.length);
|
|
18
|
-
for (let i = 0; i < minLen; i += 1) {
|
|
19
|
-
if (!compareSnapshots(refRun.snapshots[i], candRun.snapshots[i])) {
|
|
20
|
-
firstDivergenceStep = i;
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
if (firstDivergenceStep === null && refRun.snapshots.length !== candRun.snapshots.length) {
|
|
25
|
-
firstDivergenceStep = minLen;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
case: pair,
|
|
30
|
-
agree,
|
|
31
|
-
referenceOutput: refRun.finalOutput,
|
|
32
|
-
candidateOutput: candRun.finalOutput,
|
|
33
|
-
referenceSteps: refRun.stepCount,
|
|
34
|
-
candidateSteps: candRun.stepCount,
|
|
35
|
-
firstDivergenceStep,
|
|
36
|
-
};
|
|
37
|
-
});
|
|
38
|
-
return {
|
|
39
|
-
results,
|
|
40
|
-
allAgree: results.every((r) => r.agree),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
// Single-machine runner: snapshots the tape after each step and returns the
|
|
44
|
-
// final output, the snapshot list, and the step count.
|
|
45
|
-
function runOnce(runnable, input, stepsLimit) {
|
|
46
|
-
const tapeBlock = runnable.getTapeBlock();
|
|
47
|
-
const tape = new Tape({
|
|
48
|
-
alphabet: tapeBlock.tapes[0].alphabet,
|
|
49
|
-
symbols: input.split(''),
|
|
50
|
-
});
|
|
51
|
-
tapeBlock.replaceTape(tape);
|
|
52
|
-
const machine = new TuringMachine({ tapeBlock });
|
|
53
|
-
const snapshots = [];
|
|
54
|
-
let stepCount = 0;
|
|
55
|
-
// Inside the for-of body, the tape reflects the state BEFORE the current
|
|
56
|
-
// step's command (i.e. AFTER the previous step's command — or initial for
|
|
57
|
-
// step 1). After the loop, the tape has had every command applied.
|
|
58
|
-
for (const _ of machine.runStepByStep({ initialState: runnable.state, stepsLimit })) {
|
|
59
|
-
snapshots.push(tape.symbols.join(''));
|
|
60
|
-
stepCount += 1;
|
|
61
|
-
}
|
|
62
|
-
snapshots.push(tape.symbols.join(''));
|
|
63
|
-
return {
|
|
64
|
-
finalOutput: tape.symbols.join('').trim(),
|
|
65
|
-
snapshots,
|
|
66
|
-
stepCount,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const uniquePredicate = (v, i, a) => a.indexOf(v) === i;
|
|
2
|
-
const idKey = Symbol('idCurrentKey');
|
|
3
|
-
const idWeakMapKey = Symbol('idWeakMapKey');
|
|
4
|
-
function id(object) {
|
|
5
|
-
if (!id[idWeakMapKey].has(object)) {
|
|
6
|
-
id[idWeakMapKey].set(object, id[idKey]);
|
|
7
|
-
id[idKey] += 1;
|
|
8
|
-
}
|
|
9
|
-
return id[idWeakMapKey].get(object);
|
|
10
|
-
}
|
|
11
|
-
id[idKey] = 0;
|
|
12
|
-
id[idWeakMapKey] = new WeakMap();
|
|
13
|
-
export { id, uniquePredicate, };
|
package/dist/utilities/graph.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { movements, symbolCommands } from '../classes/TapeCommand';
|
|
2
|
-
const movementDescriptionToLabel = {
|
|
3
|
-
'move caret left command': 'L',
|
|
4
|
-
'move caret right command': 'R',
|
|
5
|
-
'do not move carer': 'S',
|
|
6
|
-
};
|
|
7
|
-
const symbolCommandDescriptionToLabel = {
|
|
8
|
-
'keep symbol command': '·',
|
|
9
|
-
'erase symbol command': '⌫',
|
|
10
|
-
};
|
|
11
|
-
// Reserved characters in the encoded pattern string:
|
|
12
|
-
// '*' per-cell ifOtherSymbol (matches any symbol on that tape)
|
|
13
|
-
// '-' the tape's blank symbol
|
|
14
|
-
// ',' separates per-tape cells inside one pattern
|
|
15
|
-
// '|' separates alternative patterns
|
|
16
|
-
// '\\' escape prefix — to represent any of '*', '-', ',', '|', or '\\' as a
|
|
17
|
-
// *literal* alphabet symbol, prefix it with '\\' (e.g. '\\*' for literal '*').
|
|
18
|
-
function escapeAlphabetSymbol(s) {
|
|
19
|
-
return s
|
|
20
|
-
.replace(/\\/g, '\\\\')
|
|
21
|
-
.replace(/\*/g, '\\*')
|
|
22
|
-
.replace(/-/g, '\\-')
|
|
23
|
-
.replace(/,/g, '\\,')
|
|
24
|
-
.replace(/\|/g, '\\|');
|
|
25
|
-
}
|
|
26
|
-
export function decodePatternDescription(description, alphabets) {
|
|
27
|
-
if (!description) {
|
|
28
|
-
return '?';
|
|
29
|
-
}
|
|
30
|
-
if (description === 'other symbol') {
|
|
31
|
-
return '*';
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const patternList = JSON.parse(description);
|
|
35
|
-
return patternList
|
|
36
|
-
.map((pattern) => pattern
|
|
37
|
-
.map((s, tapeIx) => {
|
|
38
|
-
if (s === null) {
|
|
39
|
-
return '*';
|
|
40
|
-
}
|
|
41
|
-
if (s === alphabets[tapeIx]?.[0]) {
|
|
42
|
-
return '-';
|
|
43
|
-
}
|
|
44
|
-
return escapeAlphabetSymbol(s);
|
|
45
|
-
})
|
|
46
|
-
.join(','))
|
|
47
|
-
.join('|');
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
return description;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
export function decodeMovement(description) {
|
|
54
|
-
if (!description) {
|
|
55
|
-
return '?';
|
|
56
|
-
}
|
|
57
|
-
return movementDescriptionToLabel[description] ?? description;
|
|
58
|
-
}
|
|
59
|
-
export function splitUnescaped(s, sep) {
|
|
60
|
-
const parts = [];
|
|
61
|
-
let current = '';
|
|
62
|
-
let i = 0;
|
|
63
|
-
while (i < s.length) {
|
|
64
|
-
if (s[i] === '\\' && i + 1 < s.length) {
|
|
65
|
-
current += s[i + 1];
|
|
66
|
-
i += 2;
|
|
67
|
-
}
|
|
68
|
-
else if (s[i] === sep) {
|
|
69
|
-
parts.push(current);
|
|
70
|
-
current = '';
|
|
71
|
-
i += 1;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
current += s[i];
|
|
75
|
-
i += 1;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
parts.push(current);
|
|
79
|
-
return parts;
|
|
80
|
-
}
|
|
81
|
-
export function parsePatternString(s, alphabets) {
|
|
82
|
-
if (s === '*') {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
const alternatives = splitUnescaped(s, '|');
|
|
86
|
-
return alternatives.map((alt) => {
|
|
87
|
-
const cells = splitUnescaped(alt, ',');
|
|
88
|
-
return cells.map((cell, tapeIx) => {
|
|
89
|
-
if (cell === '*') {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
if (cell === '-') {
|
|
93
|
-
return alphabets[tapeIx]?.[0] ?? cell;
|
|
94
|
-
}
|
|
95
|
-
return cell;
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
const movementLabelToSymbol = {
|
|
100
|
-
L: movements.left,
|
|
101
|
-
R: movements.right,
|
|
102
|
-
S: movements.stay,
|
|
103
|
-
};
|
|
104
|
-
export function parseMovementLabel(label) {
|
|
105
|
-
const m = movementLabelToSymbol[label];
|
|
106
|
-
if (!m) {
|
|
107
|
-
throw new Error(`unknown movement label: ${label}`);
|
|
108
|
-
}
|
|
109
|
-
return m;
|
|
110
|
-
}
|
|
111
|
-
export function parseWriteSymbolLabel(label) {
|
|
112
|
-
if (label === '·') {
|
|
113
|
-
return symbolCommands.keep;
|
|
114
|
-
}
|
|
115
|
-
if (label === '⌫') {
|
|
116
|
-
return symbolCommands.erase;
|
|
117
|
-
}
|
|
118
|
-
return label;
|
|
119
|
-
}
|
|
120
|
-
export function decodeWriteSymbol(symbol) {
|
|
121
|
-
if (typeof symbol === 'symbol') {
|
|
122
|
-
const description = symbol.description ?? '?';
|
|
123
|
-
return symbolCommandDescriptionToLabel[description] ?? description;
|
|
124
|
-
}
|
|
125
|
-
return symbol;
|
|
126
|
-
}
|
|
127
|
-
// Format converters (toMermaid / fromMermaid) live in ./graphFormats.
|