-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathVMWriter.js
96 lines (76 loc) · 2.44 KB
/
VMWriter.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
const fs = require('fs');
const assert = require('assert');
const {Enum} = require('./Enum');
const Segments = new Enum({
CONST: {value: 0, description: 'constant'},
ARG: {value: 1, description: 'argument'},
LOCAL: {value: 2, description: 'local'},
STATIC: {value: 3, description: 'static'},
THIS: {value: 4, description: 'this'},
THAT: {value: 5, description: 'that'},
POINTER: {value: 6, description: 'pointer'},
TEMP: {value: 7, description: 'temp'},
});
const Commands = new Enum({
ADD: {value:0, description: 'add'},
SUB: {value:1, description: 'sub'},
NEG: {value:2, description: 'neg'},
EQ: {value:3, description: 'eq'},
GT: {value:4, description: 'gt'},
LT: {value:5, description: 'lt'},
AND: {value:6, description: 'and'},
OR: {value:7, description: 'or'},
NOT: {value:8, description: 'not'},
});
class VMWriter {
constructor(outputFilename) {
this.outputFile = fs.openSync(outputFilename + '.vm', 'w+');
}
write(str) {
fs.appendFileSync(this.outputFile, str + '\n');
}
writePush(segment, index) {
assert(Segments.contains(segment), 'Segment must be a Segments.CONST, Segments.ARG, etc');
assert(Number.isInteger(index) && index >= 0, 'index must be an integer >= 0');
this.write(`push ${segment.display} ${index}`);
}
writePop(segment, index) {
assert(Segments.contains(segment), 'Segment must be a Segments.CONST, Segments.ARG, etc');
assert(Number.isInteger(index) && index >= 0, 'index must be an integer >= 0');
assert.notEqual(segment, Segments.CONST, 'Cannot pop constant');
this.write(`pop ${segment.display} ${index}`);
}
writeArithmetic(command) {
assert(Commands.contains(command), 'Command must be a Commands.ADD, Commands.SUB, etc');
this.write(command.display);
}
writeLabel(label) {
this.write(`label ${label}`);
}
writeGoto(label) {
this.write(`goto ${label}`);
}
writeIf(label) {
this.write(`if-goto ${label}`);
}
writeCall(name, nArgs) {
assert(Number.isInteger(nArgs) && nArgs >= 0, 'nArgs must be an integer >= 0');
this.write(`call ${name} ${nArgs}`);
}
writeFunction(name, nLocals) {
assert(Number.isInteger(nLocals) && nLocals >= 0, 'nLocals must be an integer >= 0');
this.write(`function ${name} ${nLocals}`);
}
writeReturn() {
this.write('return');
}
close() {
fs.closeSync(this.outputFile);
this.outputFile = null;
}
}
module.exports = {
Segments,
Commands,
VMWriter,
};