-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathinterpreter.js
124 lines (94 loc) · 3.11 KB
/
interpreter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import program from 'program';
import codeCell from 'codeCell';
import tmath from 'tmath';
import core from 'core';
export class Interpreter {
constructor() {
this.tape = new core.Tape();
this.program = null;
this.accept = false;
this.running = false;
this.position = new tmath.Vec2(0, 0);
this.facing = program.directions.UP;
this.cycles = 0;
}
setProgram(program) {
this.program = program;
}
setTape(tape) {
this.tape = tape;
}
start() {
this.accept = false;
this.running = true;
this.cycles = 0;
// Go to the start
for (let x of _.range(this.program.cols)) {
for (let y of _.range(this.program.rows)) {
if (this.program.getCell(x, y).type == 'Start') {
this.position.x = x;
this.position.y = y;
}
}
}
// Face +y;
this.facing = program.directions.UP;
}
convertDirectionGlobalToCell(d, cell) {
return cell.orientation.apply(d);
}
convertDirectionCellToGlobal(d, cell) {
return cell.orientation.invert().apply(d);
}
// Returns tuple [pop tape head or not (bool), symbol to push (maybe null), new facing direction]
evalCell(cell, tapeHead) {
let cellFunc = codeCell.codeCells[cell.type];
let result = null;
if (cellFunc) {
if (cell.type == 'CrossConveyor') {
// Special case. Convert this.facing into cell coordinates for CrossConveyor's function:
let cellFacing = this.convertDirectionGlobalToCell(this.facing, cell);
result = cellFunc(tapeHead, cellFacing);
} else {
// No knowledge of current facing needed
result = cellFunc(tapeHead);
}
// Convert cell's returned direction into global direction
result[2] = this.convertDirectionCellToGlobal(result[2], cell);
return result;
}
console.log('Invalid cell type.');
return [false, null, program.directions.UP];
}
step() {
if (!this.running) return;
// Get state
let cell = this.program.getCell(this.position.x, this.position.y);
let head = this.tape.head();
// Check if done
if (cell.type == 'Empty' || (cell.type == 'Start' && this.cycles > 0)) {
this.running = false;
this.accept = false;
} else if (cell.type == 'End') {
this.running = false;
this.accept = true;
} else {
// Evaluate cell
let result = this.evalCell(cell, head);
// Perform result
if (result[0]) {
this.tape.pop();
}
if (result[1] != null) {
this.tape.append(result[1]);
}
this.facing = result[2];
// Move 'facing' direction:
this.position = this.position.add(this.facing);
this.cycles += 1;
}
}
};
export default {
Interpreter
};