.
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Average/Main.jack
|
||||
|
||||
// (Same as projects/09/Average/Main.jack)
|
||||
|
||||
// Inputs some numbers and computes their average
|
||||
class Main {
|
||||
function void main() {
|
||||
var Array a;
|
||||
var int length;
|
||||
var int i, sum;
|
||||
|
||||
let length = Keyboard.readInt("How many numbers? ");
|
||||
let a = Array.new(length); // constructs the array
|
||||
|
||||
let i = 0;
|
||||
while (i < length) {
|
||||
let a[i] = Keyboard.readInt("Enter a number: ");
|
||||
let sum = sum + a[i];
|
||||
let i = i + 1;
|
||||
}
|
||||
|
||||
do Output.printString("The average is ");
|
||||
do Output.printInt(sum / length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
function Main.main 4
|
||||
push constant 18
|
||||
call String.new 1
|
||||
push constant 72
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 119
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 121
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 63
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Keyboard.readInt 1
|
||||
pop local 1
|
||||
push local 1
|
||||
call Array.new 1
|
||||
pop local 0
|
||||
push constant 0
|
||||
pop local 2
|
||||
label L0
|
||||
push local 2
|
||||
push local 1
|
||||
lt
|
||||
not
|
||||
if-goto L1
|
||||
push local 0
|
||||
push local 2
|
||||
push constant 16
|
||||
call String.new 1
|
||||
push constant 69
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 110
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 98
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Keyboard.readInt 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 3
|
||||
push local 0
|
||||
push local 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop local 3
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop local 2
|
||||
goto L0
|
||||
label L1
|
||||
push constant 15
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 104
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 118
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 103
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 105
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 3
|
||||
push local 1
|
||||
call Math.divide 2
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/ComplexArrays/Main.jack
|
||||
|
||||
/**
|
||||
* Performs several complex array processing tests.
|
||||
* For each test, the expected result is printed, along with the
|
||||
* actual result. In each test, the two results should be equal.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
function void main() {
|
||||
var Array a, b, c;
|
||||
|
||||
let a = Array.new(10);
|
||||
let b = Array.new(5);
|
||||
let c = Array.new(1);
|
||||
|
||||
let a[3] = 2;
|
||||
let a[4] = 8;
|
||||
let a[5] = 4;
|
||||
let b[a[3]] = a[3] + 3; // b[2] = 5
|
||||
let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40
|
||||
let c[0] = null;
|
||||
let c = c[0];
|
||||
|
||||
do Output.printString("Test 1: expected result: 5; actual result: ");
|
||||
do Output.printInt(b[2]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 2: expected result: 40; actual result: ");
|
||||
do Output.printInt(a[5]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 3: expected result: 0; actual result: ");
|
||||
do Output.printInt(c);
|
||||
do Output.println();
|
||||
|
||||
let c = null;
|
||||
|
||||
if (c = null) {
|
||||
do Main.fill(a, 10);
|
||||
let c = a[3];
|
||||
let c[1] = 33;
|
||||
let c = a[7];
|
||||
let c[1] = 77;
|
||||
let b = a[3];
|
||||
let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110;
|
||||
}
|
||||
|
||||
do Output.printString("Test 4: expected result: 77; actual result: ");
|
||||
do Output.printInt(c[1]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 5: expected result: 110; actual result: ");
|
||||
do Output.printInt(b[1]);
|
||||
do Output.println();
|
||||
return;
|
||||
}
|
||||
|
||||
function int double(int a) {
|
||||
return a * 2;
|
||||
}
|
||||
|
||||
function void fill(Array a, int size) {
|
||||
while (size > 0) {
|
||||
let size = size - 1;
|
||||
let a[size] = Array.new(3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+703
@@ -0,0 +1,703 @@
|
||||
function Main.main 3
|
||||
push constant 10
|
||||
call Array.new 1
|
||||
pop local 0
|
||||
push constant 5
|
||||
call Array.new 1
|
||||
pop local 1
|
||||
push constant 1
|
||||
call Array.new 1
|
||||
pop local 2
|
||||
push local 0
|
||||
push constant 3
|
||||
push constant 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 4
|
||||
push constant 8
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 5
|
||||
push constant 4
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 1
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push constant 3
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push local 1
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 0
|
||||
push local 0
|
||||
push constant 5
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 1
|
||||
push constant 7
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
sub
|
||||
push constant 2
|
||||
call Main.double 1
|
||||
sub
|
||||
push constant 1
|
||||
add
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Math.multiply 2
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 0
|
||||
push constant 0
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 2
|
||||
push constant 0
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 2
|
||||
push constant 43
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 120
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 53
|
||||
call String.appendChar 2
|
||||
push constant 59
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
push constant 2
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 44
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 50
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 120
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 52
|
||||
call String.appendChar 2
|
||||
push constant 48
|
||||
call String.appendChar 2
|
||||
push constant 59
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 5
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 43
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 51
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 120
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 48
|
||||
call String.appendChar 2
|
||||
push constant 59
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 2
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L0
|
||||
push local 0
|
||||
push constant 10
|
||||
call Main.fill 2
|
||||
pop temp 0
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 1
|
||||
push constant 33
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 7
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 2
|
||||
push local 2
|
||||
push constant 1
|
||||
push constant 77
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
push local 0
|
||||
push constant 3
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
pop local 1
|
||||
push local 1
|
||||
push constant 1
|
||||
push local 1
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
add
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push constant 44
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 52
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 120
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 55
|
||||
call String.appendChar 2
|
||||
push constant 55
|
||||
call String.appendChar 2
|
||||
push constant 59
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 2
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 45
|
||||
call String.new 1
|
||||
push constant 84
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 53
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 120
|
||||
call String.appendChar 2
|
||||
push constant 112
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 100
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 49
|
||||
call String.appendChar 2
|
||||
push constant 48
|
||||
call String.appendChar 2
|
||||
push constant 59
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 115
|
||||
call String.appendChar 2
|
||||
push constant 117
|
||||
call String.appendChar 2
|
||||
push constant 108
|
||||
call String.appendChar 2
|
||||
push constant 116
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push local 1
|
||||
push constant 1
|
||||
add
|
||||
pop pointer 1
|
||||
push that 0
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
call Output.println 0
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Main.double 0
|
||||
push argument 0
|
||||
push constant 2
|
||||
call Math.multiply 2
|
||||
return
|
||||
function Main.fill 0
|
||||
label L2
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L3
|
||||
push argument 1
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 1
|
||||
push argument 0
|
||||
push argument 1
|
||||
push constant 3
|
||||
call Array.new 1
|
||||
pop temp 1
|
||||
add
|
||||
pop pointer 1
|
||||
push temp 1
|
||||
pop that 0
|
||||
goto L2
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/ConvertToBin/Main.jack
|
||||
|
||||
/**
|
||||
* Unpacks a 16-bit number into its binary representation:
|
||||
* Takes the 16-bit number stored in RAM[8000] and stores its individual
|
||||
* bits in RAM[8001..8016] (each location will contain 0 or 1).
|
||||
* Before the conversion, RAM[8001]..RAM[8016] are initialized to -1.
|
||||
*
|
||||
* The program should be tested as follows:
|
||||
* 1) Load the program into the supplied VM emulator
|
||||
* 2) Put some value in RAM[8000]
|
||||
* 3) Switch to "no animation"
|
||||
* 4) Run the program (give it enough time to run)
|
||||
* 5) Stop the program
|
||||
* 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and
|
||||
* that none of these memory locations contains -1.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
/**
|
||||
* Initializes RAM[8001]..RAM[8016] to -1,
|
||||
* and converts the value in RAM[8000] to binary.
|
||||
*/
|
||||
function void main() {
|
||||
var int value;
|
||||
do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1
|
||||
let value = Memory.peek(8000); // reads a value from RAM[8000]
|
||||
do Main.convert(value); // performs the conversion
|
||||
return;
|
||||
}
|
||||
|
||||
/** Converts the given decimal value to binary, and puts
|
||||
* the resulting bits in RAM[8001]..RAM[8016]. */
|
||||
function void convert(int value) {
|
||||
var int mask, position;
|
||||
var boolean loop;
|
||||
|
||||
let loop = true;
|
||||
while (loop) {
|
||||
let position = position + 1;
|
||||
let mask = Main.nextMask(mask);
|
||||
|
||||
if (~(position > 16)) {
|
||||
|
||||
if (~((value & mask) = 0)) {
|
||||
do Memory.poke(8000 + position, 1);
|
||||
}
|
||||
else {
|
||||
do Memory.poke(8000 + position, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let loop = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the next mask (the mask that should follow the given mask). */
|
||||
function int nextMask(int mask) {
|
||||
if (mask = 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return mask * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Fills 'length' consecutive memory locations with 'value',
|
||||
* starting at 'startAddress'. */
|
||||
function void fillMemory(int startAddress, int length, int value) {
|
||||
while (length > 0) {
|
||||
do Memory.poke(startAddress, value);
|
||||
let length = length - 1;
|
||||
let startAddress = startAddress + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+106
@@ -0,0 +1,106 @@
|
||||
function Main.main 1
|
||||
push constant 8001
|
||||
push constant 16
|
||||
push constant 1
|
||||
neg
|
||||
call Main.fillMemory 3
|
||||
pop temp 0
|
||||
push constant 8000
|
||||
call Memory.peek 1
|
||||
pop local 0
|
||||
push local 0
|
||||
call Main.convert 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Main.convert 3
|
||||
push constant 1
|
||||
neg
|
||||
pop local 2
|
||||
label L0
|
||||
push local 2
|
||||
not
|
||||
if-goto L1
|
||||
push local 1
|
||||
push constant 1
|
||||
add
|
||||
pop local 1
|
||||
push local 0
|
||||
call Main.nextMask 1
|
||||
pop local 0
|
||||
push local 1
|
||||
push constant 16
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto L2
|
||||
push argument 0
|
||||
push local 0
|
||||
and
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
not
|
||||
if-goto L3
|
||||
push constant 8000
|
||||
push local 1
|
||||
add
|
||||
push constant 1
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
goto L4
|
||||
label L3
|
||||
push constant 8000
|
||||
push local 1
|
||||
add
|
||||
push constant 0
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
label L4
|
||||
goto L5
|
||||
label L2
|
||||
push constant 0
|
||||
pop local 2
|
||||
label L5
|
||||
goto L0
|
||||
label L1
|
||||
push constant 0
|
||||
return
|
||||
function Main.nextMask 0
|
||||
push argument 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push constant 1
|
||||
return
|
||||
goto L7
|
||||
label L6
|
||||
push argument 0
|
||||
push constant 2
|
||||
call Math.multiply 2
|
||||
return
|
||||
label L7
|
||||
function Main.fillMemory 0
|
||||
label L8
|
||||
push argument 1
|
||||
push constant 0
|
||||
gt
|
||||
not
|
||||
if-goto L9
|
||||
push argument 0
|
||||
push argument 2
|
||||
call Memory.poke 2
|
||||
pop temp 0
|
||||
push argument 1
|
||||
push constant 1
|
||||
sub
|
||||
pop argument 1
|
||||
push argument 0
|
||||
push constant 1
|
||||
add
|
||||
pop argument 0
|
||||
goto L8
|
||||
label L9
|
||||
push constant 0
|
||||
return
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from tokenizer import Tokenizer
|
||||
from vmwriter import VMWriter
|
||||
from symbol_table import SymbolTable
|
||||
|
||||
|
||||
# TODO add names to variables when you call for them, aka current_vm_append(thingtobeappended=blablac)
|
||||
|
||||
class CompilationEngine:
|
||||
def __init__(self, tokenizer, full_path_vm):
|
||||
self.string = self.sub_type = self.class_name = self.function_type = ''
|
||||
self.tab = self.recursion_index = 0
|
||||
self.tokenizer = tokenizer
|
||||
self.sym_table = []
|
||||
self.vmwriter = VMWriter(full_path_vm)
|
||||
self.current_vm = [] # used to reverse some of the commands, eg a+b need to be a b +
|
||||
|
||||
def search_kind_of_sym(self, current_vm):
|
||||
if self.sym_table[-1].kind_of(current_vm) is not None:
|
||||
return self.sym_table[-1].kind_of(current_vm), self.sym_table[-1].index_of(current_vm)
|
||||
for i in range(len(self.sym_table) - 2, -1,
|
||||
-1): # start from the amount of sym_tables -2 so it starts from one below the current,
|
||||
# until it is bigger than -1, walking it backwards
|
||||
if self.sym_table[i].kind_of(current_vm) in ('static', 'this'):
|
||||
return self.sym_table[i].kind_of(current_vm), self.sym_table[i].index_of(current_vm)
|
||||
|
||||
def search_type_of_sym(self, current_vm):
|
||||
for i in range(len(self.sym_table) - 1, -1, -1):
|
||||
if self.sym_table[i].type_of(current_vm) is not None:
|
||||
return self.sym_table[i].type_of(current_vm)
|
||||
|
||||
def write_token(self):
|
||||
if self.tokenizer.token_type() == 'stringConstant':
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token.strip(
|
||||
'"') + ' </' + self.tokenizer.token_type() + '>\n'
|
||||
else:
|
||||
self.string += ' ' * self.tab + '<' + self.tokenizer.token_type() + '> ' + self.tokenizer.token + ' </' \
|
||||
+ self.tokenizer.token_type() + '>\n'
|
||||
|
||||
def compile_class(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.tokenizer.advance() # class ->
|
||||
self.tokenizer.advance() # type ->
|
||||
self.class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token != '}':
|
||||
if self.tokenizer.token in ['static', 'field']:
|
||||
self.compile_class_var_dec()
|
||||
if self.tokenizer.token in ['constructor', 'function', 'method']:
|
||||
self.compile_subroutine()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
self.vmwriter.close_vm_file()
|
||||
|
||||
def compile_class_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_subroutine(self):
|
||||
self.sym_table.append(SymbolTable())
|
||||
self.sub_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine type(function|method|constructor) ->
|
||||
self.function_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine kind(int|void|etc..) ->
|
||||
sub_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
if self.sub_type == 'method':
|
||||
self.sym_table[-1].start_subroutine('this', self.class_name)
|
||||
self.compile_parameter_list()
|
||||
self.tokenizer.advance() # { ->
|
||||
while self.tokenizer.token == 'var': # create only symbol teable entries
|
||||
self.compile_var_dec()
|
||||
if self.sub_type == 'constructor':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('constant', self.sym_table[-2].var_count('field'))
|
||||
self.vmwriter.write_call('Memory.alloc', 1)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
elif self.sub_type == 'method':
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
self.vmwriter.write_push('argument', 0)
|
||||
self.vmwriter.write_pop('pointer', 0)
|
||||
else:
|
||||
self.vmwriter.write_function(f'{self.class_name}.{sub_name}', self.sym_table[-1].var_count('var'))
|
||||
while self.tokenizer.token != '}':
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance()
|
||||
self.sym_table.pop()
|
||||
|
||||
def compile_parameter_list(self):
|
||||
if self.tokenizer.token != ')':
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # var ype ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # var name ->
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance() # , ->
|
||||
var_type = self.tokenizer.token
|
||||
self.tokenizer.advance() # type ->
|
||||
var_name = self.tokenizer.token
|
||||
self.sym_table[-1].define(var_name, var_type, 'argument')
|
||||
self.tokenizer.advance() # name ->
|
||||
self.tokenizer.advance() # )->
|
||||
|
||||
def compile_var_dec(self):
|
||||
var_kind = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_type = tokenizer_main.token
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
while self.tokenizer.token == ',':
|
||||
self.tokenizer.advance()
|
||||
var_name = tokenizer_main.token
|
||||
self.sym_table[-1].define(var_name, var_type, var_kind)
|
||||
self.tokenizer.advance()
|
||||
self.tokenizer.advance()
|
||||
|
||||
def compile_statements(self):
|
||||
while True:
|
||||
if self.tokenizer.token == 'let':
|
||||
self.compile_let()
|
||||
elif self.tokenizer.token == 'if':
|
||||
self.compile_if()
|
||||
elif self.tokenizer.token == 'while':
|
||||
self.compile_while()
|
||||
elif self.tokenizer.token == 'do':
|
||||
self.compile_do()
|
||||
elif self.tokenizer.token == 'return':
|
||||
self.compile_return()
|
||||
else:
|
||||
break
|
||||
|
||||
def compile_do(self):
|
||||
self.tokenizer.advance() # do ->
|
||||
class_name = self.tokenizer.token
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.tokenizer.token == '(': # method
|
||||
self.vmwriter.write_push('pointer', 0)
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{class_name}', count + 1)
|
||||
elif self.tokenizer.token == '.': # method or function
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = f'{class_name}.{self.tokenizer.token}'
|
||||
sname = f'{self.search_type_of_sym(class_name)}.{self.tokenizer.token}'
|
||||
self.tokenizer.advance() # name ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(class_name))
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if self.search_kind_of_sym(class_name) is not None:
|
||||
self.vmwriter.write_call(f'{sname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{fname}', count)
|
||||
self.vmwriter.write_pop('temp', '0')
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_let(self):
|
||||
flag_array = 0
|
||||
self.tokenizer.advance() # let ->
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # var_name ->
|
||||
if self.tokenizer.token == '[':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ] ->
|
||||
flag_array = 1
|
||||
self.tokenizer.advance() # = ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ; ->
|
||||
if flag_array == 0:
|
||||
self.vmwriter.write_pop(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
self.vmwriter.write_pop('temp', 1)
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('temp', 1)
|
||||
self.vmwriter.write_pop('that', 0)
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_while(self):
|
||||
self.tokenizer.advance() # while ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_lable(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_goto(label1)
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_return(self):
|
||||
self.tokenizer.advance() # return ->
|
||||
if self.tokenizer.token != ';':
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_return(self.function_type)
|
||||
self.tokenizer.advance() # ; ->
|
||||
|
||||
def compile_if(self):
|
||||
self.tokenizer.advance() # if ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
label1 = self.vmwriter.label_index
|
||||
self.vmwriter.write_if(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
label2 = self.vmwriter.label_index
|
||||
self.vmwriter.write_goto(self.vmwriter.label_index)
|
||||
self.vmwriter.label_index += 1
|
||||
self.vmwriter.write_lable(label1)
|
||||
if self.tokenizer.token == 'else':
|
||||
self.tokenizer.advance() # else ->
|
||||
self.tokenizer.advance() # { ->
|
||||
self.compile_statements()
|
||||
self.tokenizer.advance() # } ->
|
||||
self.vmwriter.write_lable(label2)
|
||||
|
||||
def compile_expression(self):
|
||||
self.compile_term()
|
||||
while self.tokenizer.token in ['+', '-', '*', '/', '|', '=', '>', '<', '&']:
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # symbol ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_term(self):
|
||||
if self.tokenizer.token == '(': # expression ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
self.compile_expression()
|
||||
self.tokenizer.advance() # ) ->
|
||||
elif self.tokenizer.token in ['~', '-']: # uniry op
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
tmp = 'neg' if self.tokenizer.token == '-' else self.tokenizer.token
|
||||
self.tokenizer.advance() # ~ or - ->
|
||||
self.compile_term()
|
||||
self.vmwriter.write_arithmetic(tmp)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type() != 'symbol':
|
||||
self.current_vm.append(self.tokenizer.token)
|
||||
self.tokenizer.advance() # integer, string, keyword, varnname, subroutine_name, class_name, var_name ->
|
||||
if self.tokenizer.token == '[': # Array
|
||||
self.tokenizer.advance() # [ ->
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
self.compile_expression()
|
||||
self.vmwriter.write_arithmetic('+')
|
||||
self.vmwriter.write_pop('pointer', 1)
|
||||
self.vmwriter.write_push('that', 0)
|
||||
self.tokenizer.advance() # ] ->
|
||||
elif self.tokenizer.token == '(': # subroutine_name ()
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
self.vmwriter.write_call(f'{self.class_name}.{self.current_vm[-1]}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token == '.': # method
|
||||
if self.search_type_of_sym(self.current_vm[-1]) is not None:
|
||||
flag = 1
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
else:
|
||||
flag = 0
|
||||
self.tokenizer.advance() # . ->
|
||||
fname = self.tokenizer.token
|
||||
self.tokenizer.advance() # subroutine name ->
|
||||
self.tokenizer.advance() # ( ->
|
||||
count = self.compile_expression_list()
|
||||
self.tokenizer.advance() # ) ->
|
||||
if flag == 1:
|
||||
self.vmwriter.write_call(f'{self.search_type_of_sym(self.current_vm[-1])}.{fname}', count + 1)
|
||||
else:
|
||||
self.vmwriter.write_call(f'{self.current_vm[-1]}.{fname}', count)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'stringConstant':
|
||||
self.vmwriter.write_push('constant', len(self.current_vm[-1].strip('"')))
|
||||
self.vmwriter.write_call('String.new', 1)
|
||||
for index, item in enumerate(self.current_vm[-1].strip('"')):
|
||||
self.vmwriter.write_push('constant', ord(item))
|
||||
self.vmwriter.write_call('String.appendChar', 2)
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'integerConstant':
|
||||
self.vmwriter.write_push('constant', self.current_vm[-1])
|
||||
self.current_vm.pop()
|
||||
elif self.tokenizer.token_type(self.current_vm[-1]) == 'identifier':
|
||||
self.vmwriter.write_push(*self.search_kind_of_sym(self.current_vm[-1]))
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'true':
|
||||
self.vmwriter.write_push('constant', '1')
|
||||
self.vmwriter.write_arithmetic('neg')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'false' or self.current_vm[-1] == 'null':
|
||||
self.vmwriter.write_push('constant', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'this':
|
||||
self.vmwriter.write_push('pointer', '0')
|
||||
self.current_vm.pop()
|
||||
elif self.current_vm[-1] == 'that':
|
||||
self.vmwriter.write_push('pointer', '1')
|
||||
self.current_vm.pop()
|
||||
|
||||
def compile_expression_list(self):
|
||||
count_exp = 0
|
||||
if self.tokenizer.token in ['(', '~', '-'] or self.tokenizer.token_type() != 'symbol':
|
||||
count_exp += 1
|
||||
self.compile_expression()
|
||||
while self.tokenizer.token == ',':
|
||||
count_exp += 1
|
||||
self.tokenizer.advance() # ,
|
||||
self.compile_expression()
|
||||
return count_exp
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
path = os.getcwd()
|
||||
for root, dirs, files in os.walk(path, topdown=False):
|
||||
for name in files:
|
||||
if name[-4:] == 'jack':
|
||||
tokenizer_main = Tokenizer()
|
||||
tokenizer_main.clear_file(Path(root, name))
|
||||
full_path = Path(root, name[:-4] + 'vm')
|
||||
comp_eng_main = CompilationEngine(tokenizer_main, full_path)
|
||||
comp_eng_main.compile_class()
|
||||
Executable
+203
@@ -0,0 +1,203 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Ball.jack
|
||||
|
||||
/**
|
||||
* A graphical ball. Characterized by a screen location and distance of
|
||||
* last destination. Has methods for drawing, erasing and moving on the screen.
|
||||
* The ball is displayed as a filled, 6-by-6 pixles rectangle.
|
||||
*/
|
||||
class Ball {
|
||||
|
||||
field int x, y; // the ball's screen location (in pixels)
|
||||
field int lengthx, lengthy; // distance of last destination (in pixels)
|
||||
|
||||
field int d, straightD, diagonalD; // used for straight line movement computation
|
||||
field boolean invert, positivex, positivey; // (same)
|
||||
|
||||
field int leftWall, rightWall, topWall, bottomWall; // wall locations
|
||||
|
||||
field int wall; // last wall that the ball was bounced off of
|
||||
|
||||
/** Constructs a new ball with the given initial location and wall locations. */
|
||||
constructor Ball new(int Ax, int Ay,
|
||||
int AleftWall, int ArightWall, int AtopWall, int AbottomWall) {
|
||||
let x = Ax;
|
||||
let y = Ay;
|
||||
let leftWall = AleftWall;
|
||||
let rightWall = ArightWall - 6; // -6 for ball size
|
||||
let topWall = AtopWall;
|
||||
let bottomWall = AbottomWall - 6; // -6 for ball size
|
||||
let wall = 0;
|
||||
do show();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the Ball's memory. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Shows the ball. */
|
||||
method void show() {
|
||||
do Screen.setColor(true);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Hides the ball. */
|
||||
method void hide() {
|
||||
do Screen.setColor(false);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the ball. */
|
||||
method void draw() {
|
||||
do Screen.drawRectangle(x, y, x + 5, y + 5);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the ball's left edge. */
|
||||
method int getLeft() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the ball's right edge. */
|
||||
method int getRight() {
|
||||
return x + 5;
|
||||
}
|
||||
|
||||
/** Computes and sets the ball's destination. */
|
||||
method void setDestination(int destx, int desty) {
|
||||
var int dx, dy, temp;
|
||||
let lengthx = destx - x;
|
||||
let lengthy = desty - y;
|
||||
let dx = Math.abs(lengthx);
|
||||
let dy = Math.abs(lengthy);
|
||||
let invert = (dx < dy);
|
||||
|
||||
if (invert) {
|
||||
let temp = dx; // swap dx, dy
|
||||
let dx = dy;
|
||||
let dy = temp;
|
||||
let positivex = (y < desty);
|
||||
let positivey = (x < destx);
|
||||
}
|
||||
else {
|
||||
let positivex = (x < destx);
|
||||
let positivey = (y < desty);
|
||||
}
|
||||
|
||||
let d = (2 * dy) - dx;
|
||||
let straightD = 2 * dy;
|
||||
let diagonalD = 2 * (dy - dx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the ball one unit towards its destination.
|
||||
* If the ball has reached a wall, returns 0.
|
||||
* Else, returns a value according to the wall:
|
||||
* 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall).
|
||||
*/
|
||||
method int move() {
|
||||
|
||||
do hide();
|
||||
|
||||
if (d < 0) { let d = d + straightD; }
|
||||
else {
|
||||
let d = d + diagonalD;
|
||||
|
||||
if (positivey) {
|
||||
if (invert) { let x = x + 4; }
|
||||
else { let y = y + 4; }
|
||||
}
|
||||
else {
|
||||
if (invert) { let x = x - 4; }
|
||||
else { let y = y - 4; }
|
||||
}
|
||||
}
|
||||
|
||||
if (positivex) {
|
||||
if (invert) { let y = y + 4; }
|
||||
else { let x = x + 4; }
|
||||
}
|
||||
else {
|
||||
if (invert) { let y = y - 4; }
|
||||
else { let x = x - 4; }
|
||||
}
|
||||
|
||||
if (~(x > leftWall)) {
|
||||
let wall = 1;
|
||||
let x = leftWall;
|
||||
}
|
||||
if (~(x < rightWall)) {
|
||||
let wall = 2;
|
||||
let x = rightWall;
|
||||
}
|
||||
if (~(y > topWall)) {
|
||||
let wall = 3;
|
||||
let y = topWall;
|
||||
}
|
||||
if (~(y < bottomWall)) {
|
||||
let wall = 4;
|
||||
let y = bottomWall;
|
||||
}
|
||||
|
||||
do show();
|
||||
|
||||
return wall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounces off the current wall: sets the new destination
|
||||
* of the ball according to the ball's angle and the given
|
||||
* bouncing direction (-1/0/1=left/center/right or up/center/down).
|
||||
*/
|
||||
method void bounce(int bouncingDirection) {
|
||||
var int newx, newy, divLengthx, divLengthy, factor;
|
||||
|
||||
// dividing by 10 first since results are too big
|
||||
let divLengthx = lengthx / 10;
|
||||
let divLengthy = lengthy / 10;
|
||||
if (bouncingDirection = 0) { let factor = 10; }
|
||||
else {
|
||||
if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) {
|
||||
let factor = 20; // bounce direction is in ball direction
|
||||
}
|
||||
else { let factor = 5; } // bounce direction is against ball direction
|
||||
}
|
||||
|
||||
if (wall = 1) {
|
||||
let newx = 506;
|
||||
let newy = (divLengthy * (-50)) / divLengthx;
|
||||
let newy = y + (newy * factor);
|
||||
}
|
||||
else {
|
||||
if (wall = 2) {
|
||||
let newx = 0;
|
||||
let newy = (divLengthy * 50) / divLengthx;
|
||||
let newy = y + (newy * factor);
|
||||
}
|
||||
else {
|
||||
if (wall = 3) {
|
||||
let newy = 250;
|
||||
let newx = (divLengthx * (-25)) / divLengthy;
|
||||
let newx = x + (newx * factor);
|
||||
}
|
||||
else { // assumes wall = 4
|
||||
let newy = 0;
|
||||
let newx = (divLengthx * 25) / divLengthy;
|
||||
let newx = x + (newx * factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do setDestination(newx, newy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+435
@@ -0,0 +1,435 @@
|
||||
function Ball.new 0
|
||||
push constant 15
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
pop this 0
|
||||
push argument 1
|
||||
pop this 1
|
||||
push argument 2
|
||||
pop this 10
|
||||
push argument 3
|
||||
push constant 6
|
||||
sub
|
||||
pop this 11
|
||||
push argument 4
|
||||
pop this 12
|
||||
push argument 5
|
||||
push constant 6
|
||||
sub
|
||||
pop this 13
|
||||
push constant 0
|
||||
pop this 14
|
||||
push pointer 0
|
||||
call Ball.show 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
return
|
||||
function Ball.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Ball.show 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Ball.draw 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Ball.hide 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Ball.draw 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Ball.draw 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push constant 5
|
||||
add
|
||||
push this 1
|
||||
push constant 5
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Ball.getLeft 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
return
|
||||
function Ball.getRight 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 5
|
||||
add
|
||||
return
|
||||
function Ball.setDestination 3
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
push this 0
|
||||
sub
|
||||
pop this 2
|
||||
push argument 2
|
||||
push this 1
|
||||
sub
|
||||
pop this 3
|
||||
push this 2
|
||||
call Math.abs 1
|
||||
pop local 0
|
||||
push this 3
|
||||
call Math.abs 1
|
||||
pop local 1
|
||||
push local 0
|
||||
push local 1
|
||||
lt
|
||||
pop this 7
|
||||
push this 7
|
||||
not
|
||||
if-goto L0
|
||||
push local 0
|
||||
pop local 2
|
||||
push local 1
|
||||
pop local 0
|
||||
push local 2
|
||||
pop local 1
|
||||
push this 1
|
||||
push argument 2
|
||||
lt
|
||||
pop this 8
|
||||
push this 0
|
||||
push argument 1
|
||||
lt
|
||||
pop this 9
|
||||
goto L1
|
||||
label L0
|
||||
push this 0
|
||||
push argument 1
|
||||
lt
|
||||
pop this 8
|
||||
push this 1
|
||||
push argument 2
|
||||
lt
|
||||
pop this 9
|
||||
label L1
|
||||
push constant 2
|
||||
push local 1
|
||||
call Math.multiply 2
|
||||
push local 0
|
||||
sub
|
||||
pop this 4
|
||||
push constant 2
|
||||
push local 1
|
||||
call Math.multiply 2
|
||||
pop this 5
|
||||
push constant 2
|
||||
push local 1
|
||||
push local 0
|
||||
sub
|
||||
call Math.multiply 2
|
||||
pop this 6
|
||||
push constant 0
|
||||
return
|
||||
function Ball.move 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Ball.hide 1
|
||||
pop temp 0
|
||||
push this 4
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L2
|
||||
push this 4
|
||||
push this 5
|
||||
add
|
||||
pop this 4
|
||||
goto L3
|
||||
label L2
|
||||
push this 4
|
||||
push this 6
|
||||
add
|
||||
pop this 4
|
||||
push this 9
|
||||
not
|
||||
if-goto L4
|
||||
push this 7
|
||||
not
|
||||
if-goto L5
|
||||
push this 0
|
||||
push constant 4
|
||||
add
|
||||
pop this 0
|
||||
goto L6
|
||||
label L5
|
||||
push this 1
|
||||
push constant 4
|
||||
add
|
||||
pop this 1
|
||||
label L6
|
||||
goto L7
|
||||
label L4
|
||||
push this 7
|
||||
not
|
||||
if-goto L8
|
||||
push this 0
|
||||
push constant 4
|
||||
sub
|
||||
pop this 0
|
||||
goto L9
|
||||
label L8
|
||||
push this 1
|
||||
push constant 4
|
||||
sub
|
||||
pop this 1
|
||||
label L9
|
||||
label L7
|
||||
label L3
|
||||
push this 8
|
||||
not
|
||||
if-goto L10
|
||||
push this 7
|
||||
not
|
||||
if-goto L11
|
||||
push this 1
|
||||
push constant 4
|
||||
add
|
||||
pop this 1
|
||||
goto L12
|
||||
label L11
|
||||
push this 0
|
||||
push constant 4
|
||||
add
|
||||
pop this 0
|
||||
label L12
|
||||
goto L13
|
||||
label L10
|
||||
push this 7
|
||||
not
|
||||
if-goto L14
|
||||
push this 1
|
||||
push constant 4
|
||||
sub
|
||||
pop this 1
|
||||
goto L15
|
||||
label L14
|
||||
push this 0
|
||||
push constant 4
|
||||
sub
|
||||
pop this 0
|
||||
label L15
|
||||
label L13
|
||||
push this 0
|
||||
push this 10
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto L16
|
||||
push constant 1
|
||||
pop this 14
|
||||
push this 10
|
||||
pop this 0
|
||||
goto L17
|
||||
label L16
|
||||
label L17
|
||||
push this 0
|
||||
push this 11
|
||||
lt
|
||||
not
|
||||
not
|
||||
if-goto L18
|
||||
push constant 2
|
||||
pop this 14
|
||||
push this 11
|
||||
pop this 0
|
||||
goto L19
|
||||
label L18
|
||||
label L19
|
||||
push this 1
|
||||
push this 12
|
||||
gt
|
||||
not
|
||||
not
|
||||
if-goto L20
|
||||
push constant 3
|
||||
pop this 14
|
||||
push this 12
|
||||
pop this 1
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
push this 1
|
||||
push this 13
|
||||
lt
|
||||
not
|
||||
not
|
||||
if-goto L22
|
||||
push constant 4
|
||||
pop this 14
|
||||
push this 13
|
||||
pop this 1
|
||||
goto L23
|
||||
label L22
|
||||
label L23
|
||||
push pointer 0
|
||||
call Ball.show 1
|
||||
pop temp 0
|
||||
push this 14
|
||||
return
|
||||
function Ball.bounce 5
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 10
|
||||
call Math.divide 2
|
||||
pop local 2
|
||||
push this 3
|
||||
push constant 10
|
||||
call Math.divide 2
|
||||
pop local 3
|
||||
push argument 1
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L24
|
||||
push constant 10
|
||||
pop local 4
|
||||
goto L25
|
||||
label L24
|
||||
push this 2
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
push argument 1
|
||||
push constant 1
|
||||
eq
|
||||
and
|
||||
push this 2
|
||||
push constant 0
|
||||
lt
|
||||
push argument 1
|
||||
push constant 1
|
||||
neg
|
||||
eq
|
||||
and
|
||||
or
|
||||
not
|
||||
if-goto L26
|
||||
push constant 20
|
||||
pop local 4
|
||||
goto L27
|
||||
label L26
|
||||
push constant 5
|
||||
pop local 4
|
||||
label L27
|
||||
label L25
|
||||
push this 14
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L28
|
||||
push constant 506
|
||||
pop local 0
|
||||
push local 3
|
||||
push constant 50
|
||||
neg
|
||||
call Math.multiply 2
|
||||
push local 2
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push this 1
|
||||
push local 1
|
||||
push local 4
|
||||
call Math.multiply 2
|
||||
add
|
||||
pop local 1
|
||||
goto L29
|
||||
label L28
|
||||
push this 14
|
||||
push constant 2
|
||||
eq
|
||||
not
|
||||
if-goto L30
|
||||
push constant 0
|
||||
pop local 0
|
||||
push local 3
|
||||
push constant 50
|
||||
call Math.multiply 2
|
||||
push local 2
|
||||
call Math.divide 2
|
||||
pop local 1
|
||||
push this 1
|
||||
push local 1
|
||||
push local 4
|
||||
call Math.multiply 2
|
||||
add
|
||||
pop local 1
|
||||
goto L31
|
||||
label L30
|
||||
push this 14
|
||||
push constant 3
|
||||
eq
|
||||
not
|
||||
if-goto L32
|
||||
push constant 250
|
||||
pop local 1
|
||||
push local 2
|
||||
push constant 25
|
||||
neg
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push this 0
|
||||
push local 0
|
||||
push local 4
|
||||
call Math.multiply 2
|
||||
add
|
||||
pop local 0
|
||||
goto L33
|
||||
label L32
|
||||
push constant 0
|
||||
pop local 1
|
||||
push local 2
|
||||
push constant 25
|
||||
call Math.multiply 2
|
||||
push local 3
|
||||
call Math.divide 2
|
||||
pop local 0
|
||||
push this 0
|
||||
push local 0
|
||||
push local 4
|
||||
call Math.multiply 2
|
||||
add
|
||||
pop local 0
|
||||
label L33
|
||||
label L31
|
||||
label L29
|
||||
push pointer 0
|
||||
push local 0
|
||||
push local 1
|
||||
call Ball.setDestination 3
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Bat.jack
|
||||
|
||||
/**
|
||||
* A graphical Pong bat.
|
||||
* Displayed as a filled horizontal rectangle that has
|
||||
* a screen location, a width and a height.
|
||||
* Has methods for drawing, erasing, moving left and right,
|
||||
* and changing its width (to make the hitting action more challenging).
|
||||
* This class should have been called "paddle", following the
|
||||
* standard Pong terminology. But, unaware of this terminology,
|
||||
* we called it "bat", and then decided to stick to it.
|
||||
*/
|
||||
class Bat {
|
||||
|
||||
field int x, y; // the bat's screen location
|
||||
field int width, height; // the bat's width and height
|
||||
field int direction; // direction of the bat's movement (1 = left, 2 = right)
|
||||
|
||||
/** Constructs a new bat with the given location and width. */
|
||||
constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) {
|
||||
let x = Ax;
|
||||
let y = Ay;
|
||||
let width = Awidth;
|
||||
let height = Aheight;
|
||||
let direction = 2;
|
||||
do show();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the object's memory. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Shows the bat. */
|
||||
method void show() {
|
||||
do Screen.setColor(true);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Hides the bat. */
|
||||
method void hide() {
|
||||
do Screen.setColor(false);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the bat. */
|
||||
method void draw() {
|
||||
do Screen.drawRectangle(x, y, x + width, y + height);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sets the bat's direction (0=stop, 1=left, 2=right). */
|
||||
method void setDirection(int Adirection) {
|
||||
let direction = Adirection;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the bat's left edge. */
|
||||
method int getLeft() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the bat's right edge. */
|
||||
method int getRight() {
|
||||
return x + width;
|
||||
}
|
||||
|
||||
/** Sets the bat's width. */
|
||||
method void setWidth(int Awidth) {
|
||||
do hide();
|
||||
let width = Awidth;
|
||||
do show();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the bat one step in the bat's direction. */
|
||||
method void move() {
|
||||
if (direction = 1) {
|
||||
let x = x - 4;
|
||||
if (x < 0) { let x = 0; }
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height);
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + 3, y + height);
|
||||
}
|
||||
else {
|
||||
let x = x + 4;
|
||||
if ((x + width) > 511) { let x = 511 - width; }
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x - 4, y, x - 1, y + height);
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle((x + width) - 3, y, x + width, y + height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+208
@@ -0,0 +1,208 @@
|
||||
function Bat.new 0
|
||||
push constant 5
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
pop this 0
|
||||
push argument 1
|
||||
pop this 1
|
||||
push argument 2
|
||||
pop this 2
|
||||
push argument 3
|
||||
pop this 3
|
||||
push constant 2
|
||||
pop this 4
|
||||
push pointer 0
|
||||
call Bat.show 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
return
|
||||
function Bat.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Bat.show 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Bat.draw 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Bat.hide 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Bat.draw 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Bat.draw 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 3
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Bat.setDirection 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push argument 1
|
||||
pop this 4
|
||||
push constant 0
|
||||
return
|
||||
function Bat.getLeft 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
return
|
||||
function Bat.getRight 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
return
|
||||
function Bat.setWidth 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Bat.hide 1
|
||||
pop temp 0
|
||||
push argument 1
|
||||
pop this 2
|
||||
push pointer 0
|
||||
call Bat.show 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Bat.move 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 4
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L0
|
||||
push this 0
|
||||
push constant 4
|
||||
sub
|
||||
pop this 0
|
||||
push this 0
|
||||
push constant 0
|
||||
lt
|
||||
not
|
||||
if-goto L1
|
||||
push constant 0
|
||||
pop this 0
|
||||
goto L2
|
||||
label L1
|
||||
label L2
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 1
|
||||
add
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 4
|
||||
add
|
||||
push this 1
|
||||
push this 3
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push constant 3
|
||||
add
|
||||
push this 1
|
||||
push this 3
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
goto L3
|
||||
label L0
|
||||
push this 0
|
||||
push constant 4
|
||||
add
|
||||
pop this 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 511
|
||||
gt
|
||||
not
|
||||
if-goto L4
|
||||
push constant 511
|
||||
push this 2
|
||||
sub
|
||||
pop this 0
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push constant 4
|
||||
sub
|
||||
push this 1
|
||||
push this 0
|
||||
push constant 1
|
||||
sub
|
||||
push this 1
|
||||
push this 3
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 3
|
||||
sub
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 3
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Main.jack
|
||||
|
||||
/**
|
||||
* The main class of the Pong game.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
/** Initializes a Pong game and starts running it. */
|
||||
function void main() {
|
||||
var PongGame game;
|
||||
do PongGame.newInstance();
|
||||
let game = PongGame.getInstance();
|
||||
do game.run();
|
||||
do game.dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
function Main.main 1
|
||||
call PongGame.newInstance 0
|
||||
pop temp 0
|
||||
call PongGame.getInstance 0
|
||||
pop local 0
|
||||
push local 0
|
||||
call PongGame.run 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call PongGame.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/PongGame.jack
|
||||
|
||||
/**
|
||||
* Represents a Pong game.
|
||||
*/
|
||||
class PongGame {
|
||||
|
||||
static PongGame instance; // the singelton, a Pong game instance
|
||||
field Bat bat; // the bat
|
||||
field Ball ball; // the ball
|
||||
field int wall; // the current wall that the ball is bouncing off of.
|
||||
field boolean exit; // true when the game is over
|
||||
field int score; // the current score.
|
||||
field int lastWall; // the last wall that the ball bounced off of.
|
||||
|
||||
// The current width of the bat
|
||||
field int batWidth;
|
||||
|
||||
/** Constructs a new Pong game. */
|
||||
constructor PongGame new() {
|
||||
do Screen.clearScreen();
|
||||
let batWidth = 50; // initial bat size
|
||||
let bat = Bat.new(230, 229, batWidth, 7);
|
||||
let ball = Ball.new(253, 222, 0, 511, 0, 229);
|
||||
do ball.setDestination(400,0);
|
||||
do Screen.drawRectangle(0, 238, 511, 240);
|
||||
do Output.moveCursor(22,0);
|
||||
do Output.printString("Score: 0");
|
||||
|
||||
let exit = false;
|
||||
let score = 0;
|
||||
let wall = 0;
|
||||
let lastWall = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the object's memory. */
|
||||
method void dispose() {
|
||||
do bat.dispose();
|
||||
do ball.dispose();
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Creates an instance of Pong game, and stores it. */
|
||||
function void newInstance() {
|
||||
let instance = PongGame.new();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the single instance of this Pong game. */
|
||||
function PongGame getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Starts the game, and andles inputs from the user that control
|
||||
* the bat's movement direction. */
|
||||
method void run() {
|
||||
var char key;
|
||||
|
||||
while (~exit) {
|
||||
// waits for a key to be pressed.
|
||||
while ((key = 0) & (~exit)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do bat.move();
|
||||
do moveBall();
|
||||
do Sys.wait(50);
|
||||
}
|
||||
|
||||
if (key = 130) { do bat.setDirection(1); }
|
||||
else {
|
||||
if (key = 132) { do bat.setDirection(2); }
|
||||
else {
|
||||
if (key = 140) { let exit = true; }
|
||||
}
|
||||
}
|
||||
|
||||
// Waits for the key to be released.
|
||||
while ((~(key = 0)) & (~exit)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do bat.move();
|
||||
do moveBall();
|
||||
do Sys.wait(50);
|
||||
}
|
||||
}
|
||||
|
||||
if (exit) {
|
||||
do Output.moveCursor(10,27);
|
||||
do Output.printString("Game Over");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles ball movement, including bouncing.
|
||||
* If the ball bounces off a wall, finds its new direction.
|
||||
* If the ball bounces off the bat, increases the score by one
|
||||
* and shrinks the bat's size, to make the game more challenging.
|
||||
*/
|
||||
method void moveBall() {
|
||||
var int bouncingDirection, batLeft, batRight, ballLeft, ballRight;
|
||||
|
||||
let wall = ball.move();
|
||||
|
||||
if ((wall > 0) & (~(wall = lastWall))) {
|
||||
let lastWall = wall;
|
||||
let bouncingDirection = 0;
|
||||
let batLeft = bat.getLeft();
|
||||
let batRight = bat.getRight();
|
||||
let ballLeft = ball.getLeft();
|
||||
let ballRight = ball.getRight();
|
||||
|
||||
if (wall = 4) {
|
||||
let exit = (batLeft > ballRight) | (batRight < ballLeft);
|
||||
if (~exit) {
|
||||
if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; }
|
||||
else {
|
||||
if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; }
|
||||
}
|
||||
|
||||
let batWidth = batWidth - 2;
|
||||
do bat.setWidth(batWidth);
|
||||
let score = score + 1;
|
||||
do Output.moveCursor(22,7);
|
||||
do Output.printInt(score);
|
||||
}
|
||||
}
|
||||
do ball.bounce(bouncingDirection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+321
@@ -0,0 +1,321 @@
|
||||
function PongGame.new 0
|
||||
push constant 7
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
call Screen.clearScreen 0
|
||||
pop temp 0
|
||||
push constant 50
|
||||
pop this 6
|
||||
push constant 230
|
||||
push constant 229
|
||||
push this 6
|
||||
push constant 7
|
||||
call Bat.new 4
|
||||
pop this 0
|
||||
push constant 253
|
||||
push constant 222
|
||||
push constant 0
|
||||
push constant 511
|
||||
push constant 0
|
||||
push constant 229
|
||||
call Ball.new 6
|
||||
pop this 1
|
||||
push this 1
|
||||
push constant 400
|
||||
push constant 0
|
||||
call Ball.setDestination 3
|
||||
pop temp 0
|
||||
push constant 0
|
||||
push constant 238
|
||||
push constant 511
|
||||
push constant 240
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 22
|
||||
push constant 0
|
||||
call Output.moveCursor 2
|
||||
pop temp 0
|
||||
push constant 8
|
||||
call String.new 1
|
||||
push constant 83
|
||||
call String.appendChar 2
|
||||
push constant 99
|
||||
call String.appendChar 2
|
||||
push constant 111
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 58
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 48
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
pop this 3
|
||||
push constant 0
|
||||
pop this 4
|
||||
push constant 0
|
||||
pop this 2
|
||||
push constant 0
|
||||
pop this 5
|
||||
push pointer 0
|
||||
return
|
||||
function PongGame.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
call Bat.dispose 1
|
||||
pop temp 0
|
||||
push this 1
|
||||
call Ball.dispose 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function PongGame.newInstance 0
|
||||
call PongGame.new 0
|
||||
pop static 0
|
||||
push constant 0
|
||||
return
|
||||
function PongGame.getInstance 0
|
||||
push static 0
|
||||
return
|
||||
function PongGame.run 1
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
label L0
|
||||
push this 3
|
||||
not
|
||||
not
|
||||
if-goto L1
|
||||
label L2
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
push this 3
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L3
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push this 0
|
||||
call Bat.move 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call PongGame.moveBall 1
|
||||
pop temp 0
|
||||
push constant 50
|
||||
call Sys.wait 1
|
||||
pop temp 0
|
||||
goto L2
|
||||
label L3
|
||||
push local 0
|
||||
push constant 130
|
||||
eq
|
||||
not
|
||||
if-goto L4
|
||||
push this 0
|
||||
push constant 1
|
||||
call Bat.setDirection 2
|
||||
pop temp 0
|
||||
goto L5
|
||||
label L4
|
||||
push local 0
|
||||
push constant 132
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push this 0
|
||||
push constant 2
|
||||
call Bat.setDirection 2
|
||||
pop temp 0
|
||||
goto L7
|
||||
label L6
|
||||
push local 0
|
||||
push constant 140
|
||||
eq
|
||||
not
|
||||
if-goto L8
|
||||
push constant 1
|
||||
neg
|
||||
pop this 3
|
||||
goto L9
|
||||
label L8
|
||||
label L9
|
||||
label L7
|
||||
label L5
|
||||
label L10
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
push this 3
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L11
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push this 0
|
||||
call Bat.move 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call PongGame.moveBall 1
|
||||
pop temp 0
|
||||
push constant 50
|
||||
call Sys.wait 1
|
||||
pop temp 0
|
||||
goto L10
|
||||
label L11
|
||||
goto L0
|
||||
label L1
|
||||
push this 3
|
||||
not
|
||||
if-goto L12
|
||||
push constant 10
|
||||
push constant 27
|
||||
call Output.moveCursor 2
|
||||
pop temp 0
|
||||
push constant 9
|
||||
call String.new 1
|
||||
push constant 71
|
||||
call String.appendChar 2
|
||||
push constant 97
|
||||
call String.appendChar 2
|
||||
push constant 109
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 32
|
||||
call String.appendChar 2
|
||||
push constant 79
|
||||
call String.appendChar 2
|
||||
push constant 118
|
||||
call String.appendChar 2
|
||||
push constant 101
|
||||
call String.appendChar 2
|
||||
push constant 114
|
||||
call String.appendChar 2
|
||||
call Output.printString 1
|
||||
pop temp 0
|
||||
goto L13
|
||||
label L12
|
||||
label L13
|
||||
push constant 0
|
||||
return
|
||||
function PongGame.moveBall 5
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
call Ball.move 1
|
||||
pop this 2
|
||||
push this 2
|
||||
push constant 0
|
||||
gt
|
||||
push this 2
|
||||
push this 5
|
||||
eq
|
||||
not
|
||||
and
|
||||
not
|
||||
if-goto L14
|
||||
push this 2
|
||||
pop this 5
|
||||
push constant 0
|
||||
pop local 0
|
||||
push this 0
|
||||
call Bat.getLeft 1
|
||||
pop local 1
|
||||
push this 0
|
||||
call Bat.getRight 1
|
||||
pop local 2
|
||||
push this 1
|
||||
call Ball.getLeft 1
|
||||
pop local 3
|
||||
push this 1
|
||||
call Ball.getRight 1
|
||||
pop local 4
|
||||
push this 2
|
||||
push constant 4
|
||||
eq
|
||||
not
|
||||
if-goto L15
|
||||
push local 1
|
||||
push local 4
|
||||
gt
|
||||
push local 2
|
||||
push local 3
|
||||
lt
|
||||
or
|
||||
pop this 3
|
||||
push this 3
|
||||
not
|
||||
not
|
||||
if-goto L16
|
||||
push local 4
|
||||
push local 1
|
||||
push constant 10
|
||||
add
|
||||
lt
|
||||
not
|
||||
if-goto L17
|
||||
push constant 1
|
||||
neg
|
||||
pop local 0
|
||||
goto L18
|
||||
label L17
|
||||
push local 3
|
||||
push local 2
|
||||
push constant 10
|
||||
sub
|
||||
gt
|
||||
not
|
||||
if-goto L19
|
||||
push constant 1
|
||||
pop local 0
|
||||
goto L20
|
||||
label L19
|
||||
label L20
|
||||
label L18
|
||||
push this 6
|
||||
push constant 2
|
||||
sub
|
||||
pop this 6
|
||||
push this 0
|
||||
push this 6
|
||||
call Bat.setWidth 2
|
||||
pop temp 0
|
||||
push this 4
|
||||
push constant 1
|
||||
add
|
||||
pop this 4
|
||||
push constant 22
|
||||
push constant 7
|
||||
call Output.moveCursor 2
|
||||
pop temp 0
|
||||
push this 4
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
goto L21
|
||||
label L16
|
||||
label L21
|
||||
goto L22
|
||||
label L15
|
||||
label L22
|
||||
push this 1
|
||||
push local 0
|
||||
call Ball.bounce 2
|
||||
pop temp 0
|
||||
goto L23
|
||||
label L14
|
||||
label L23
|
||||
push constant 0
|
||||
return
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Seven/Main.jack
|
||||
|
||||
/**
|
||||
* Computes the value of 1 + (2 * 3) and prints the result
|
||||
* at the top-left of the screen.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
function void main() {
|
||||
do Output.printInt(1 + (2 * 3));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
function Main.main 0
|
||||
push constant 1
|
||||
push constant 2
|
||||
push constant 3
|
||||
call Math.multiply 2
|
||||
add
|
||||
call Output.printInt 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Square/Main.jack
|
||||
|
||||
// (same as projects/09/Square/Main.jack)
|
||||
|
||||
/** Initializes a new Square Dance game and starts running it. */
|
||||
class Main {
|
||||
function void main() {
|
||||
var SquareGame game;
|
||||
let game = SquareGame.new();
|
||||
do game.run();
|
||||
do game.dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
function Main.main 1
|
||||
call SquareGame.new 0
|
||||
pop local 0
|
||||
push local 0
|
||||
call SquareGame.run 1
|
||||
pop temp 0
|
||||
push local 0
|
||||
call SquareGame.dispose 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
Executable
+110
@@ -0,0 +1,110 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Square/Square.jack
|
||||
|
||||
// (same as projects/09/Square/Square.jack)
|
||||
|
||||
/** Implements a graphical square. */
|
||||
class Square {
|
||||
|
||||
field int x, y; // screen location of the square's top-left corner
|
||||
field int size; // length of this square, in pixels
|
||||
|
||||
/** Constructs a new square with a given location and size. */
|
||||
constructor Square new(int Ax, int Ay, int Asize) {
|
||||
let x = Ax;
|
||||
let y = Ay;
|
||||
let size = Asize;
|
||||
do draw();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this square. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the square on the screen. */
|
||||
method void draw() {
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + size, y + size);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases the square from the screen. */
|
||||
method void erase() {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + size, y + size);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Increments the square size by 2 pixels. */
|
||||
method void incSize() {
|
||||
if (((y + size) < 254) & ((x + size) < 510)) {
|
||||
do erase();
|
||||
let size = size + 2;
|
||||
do draw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Decrements the square size by 2 pixels. */
|
||||
method void decSize() {
|
||||
if (size > 2) {
|
||||
do erase();
|
||||
let size = size - 2;
|
||||
do draw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square up by 2 pixels. */
|
||||
method void moveUp() {
|
||||
if (y > 1) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
|
||||
let y = y - 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + size, y + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square down by 2 pixels. */
|
||||
method void moveDown() {
|
||||
if ((y + size) < 254) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + size, y + 1);
|
||||
let y = y + 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square left by 2 pixels. */
|
||||
method void moveLeft() {
|
||||
if (x > 1) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
|
||||
let x = x - 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + 1, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square right by 2 pixels. */
|
||||
method void moveRight() {
|
||||
if ((x + size) < 510) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + 1, y + size);
|
||||
let x = x + 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Executable
+310
@@ -0,0 +1,310 @@
|
||||
function Square.new 0
|
||||
push constant 3
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push argument 0
|
||||
pop this 0
|
||||
push argument 1
|
||||
pop this 1
|
||||
push argument 2
|
||||
pop this 2
|
||||
push pointer 0
|
||||
call Square.draw 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
return
|
||||
function Square.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Square.draw 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Square.erase 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function Square.incSize 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
push constant 254
|
||||
lt
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 510
|
||||
lt
|
||||
and
|
||||
not
|
||||
if-goto L0
|
||||
push pointer 0
|
||||
call Square.erase 1
|
||||
pop temp 0
|
||||
push this 2
|
||||
push constant 2
|
||||
add
|
||||
pop this 2
|
||||
push pointer 0
|
||||
call Square.draw 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push constant 0
|
||||
return
|
||||
function Square.decSize 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 2
|
||||
push constant 2
|
||||
gt
|
||||
not
|
||||
if-goto L2
|
||||
push pointer 0
|
||||
call Square.erase 1
|
||||
pop temp 0
|
||||
push this 2
|
||||
push constant 2
|
||||
sub
|
||||
pop this 2
|
||||
push pointer 0
|
||||
call Square.draw 1
|
||||
pop temp 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push constant 0
|
||||
return
|
||||
function Square.moveUp 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
push constant 1
|
||||
gt
|
||||
not
|
||||
if-goto L4
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push this 1
|
||||
push constant 2
|
||||
sub
|
||||
pop this 1
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push constant 1
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push constant 0
|
||||
return
|
||||
function Square.moveDown 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
push constant 254
|
||||
lt
|
||||
not
|
||||
if-goto L6
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push constant 1
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push this 1
|
||||
push constant 2
|
||||
add
|
||||
pop this 1
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
goto L7
|
||||
label L6
|
||||
label L7
|
||||
push constant 0
|
||||
return
|
||||
function Square.moveLeft 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push constant 1
|
||||
gt
|
||||
not
|
||||
if-goto L8
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push this 0
|
||||
push constant 2
|
||||
sub
|
||||
pop this 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push constant 1
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
goto L9
|
||||
label L8
|
||||
label L9
|
||||
push constant 0
|
||||
return
|
||||
function Square.moveRight 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 510
|
||||
lt
|
||||
not
|
||||
if-goto L10
|
||||
push constant 0
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 1
|
||||
push this 0
|
||||
push constant 1
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
push this 0
|
||||
push constant 2
|
||||
add
|
||||
pop this 0
|
||||
push constant 1
|
||||
neg
|
||||
call Screen.setColor 1
|
||||
pop temp 0
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push constant 1
|
||||
sub
|
||||
push this 1
|
||||
push this 0
|
||||
push this 2
|
||||
add
|
||||
push this 1
|
||||
push this 2
|
||||
add
|
||||
call Screen.drawRectangle 4
|
||||
pop temp 0
|
||||
goto L11
|
||||
label L10
|
||||
label L11
|
||||
push constant 0
|
||||
return
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Square/SquareGame.jack
|
||||
|
||||
// (same as projects/09/Square/SquareGame.jack)
|
||||
|
||||
/**
|
||||
* Implements the Square Dance game.
|
||||
* This simple game allows the user to move a black square around
|
||||
* the screen, and change the square's size during the movement.
|
||||
* When the game starts, a square of 30 by 30 pixels is shown at the
|
||||
* top-left corner of the screen. The user controls the square as follows.
|
||||
* The 4 arrow keys are used to move the square up, down, left, and right.
|
||||
* The 'z' and 'x' keys are used, respectively, to decrement and increment
|
||||
* the square's size. The 'q' key is used to quit the game.
|
||||
*/
|
||||
|
||||
class SquareGame {
|
||||
field Square square; // the square of this game
|
||||
field int direction; // the square's current direction:
|
||||
// 0=none, 1=up, 2=down, 3=left, 4=right
|
||||
|
||||
/** Constructs a new Square Game. */
|
||||
constructor SquareGame new() {
|
||||
// Creates a 30 by 30 pixels square and positions it at the top-left
|
||||
// of the screen.
|
||||
let square = Square.new(0, 0, 30);
|
||||
let direction = 0; // initial state is no movement
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this game. */
|
||||
method void dispose() {
|
||||
do square.dispose();
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square in the current direction. */
|
||||
method void moveSquare() {
|
||||
if (direction = 1) { do square.moveUp(); }
|
||||
if (direction = 2) { do square.moveDown(); }
|
||||
if (direction = 3) { do square.moveLeft(); }
|
||||
if (direction = 4) { do square.moveRight(); }
|
||||
do Sys.wait(5); // delays the next movement
|
||||
return;
|
||||
}
|
||||
|
||||
/** Runs the game: handles the user's inputs and moves the square accordingly */
|
||||
method void run() {
|
||||
var char key; // the key currently pressed by the user
|
||||
var boolean exit;
|
||||
let exit = false;
|
||||
|
||||
while (~exit) {
|
||||
// waits for a key to be pressed
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do moveSquare();
|
||||
}
|
||||
if (key = 81) { let exit = true; } // q key
|
||||
if (key = 90) { do square.decSize(); } // z key
|
||||
if (key = 88) { do square.incSize(); } // x key
|
||||
if (key = 131) { let direction = 1; } // up arrow
|
||||
if (key = 133) { let direction = 2; } // down arrow
|
||||
if (key = 130) { let direction = 3; } // left arrow
|
||||
if (key = 132) { let direction = 4; } // right arrow
|
||||
|
||||
// waits for the key to be released
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do moveSquare();
|
||||
}
|
||||
} // while
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Executable
+190
@@ -0,0 +1,190 @@
|
||||
function SquareGame.new 0
|
||||
push constant 2
|
||||
call Memory.alloc 1
|
||||
pop pointer 0
|
||||
push constant 0
|
||||
push constant 0
|
||||
push constant 30
|
||||
call Square.new 3
|
||||
pop this 0
|
||||
push constant 0
|
||||
pop this 1
|
||||
push pointer 0
|
||||
return
|
||||
function SquareGame.dispose 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 0
|
||||
call Square.dispose 1
|
||||
pop temp 0
|
||||
push pointer 0
|
||||
call Memory.deAlloc 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function SquareGame.moveSquare 0
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push this 1
|
||||
push constant 1
|
||||
eq
|
||||
not
|
||||
if-goto L0
|
||||
push this 0
|
||||
call Square.moveUp 1
|
||||
pop temp 0
|
||||
goto L1
|
||||
label L0
|
||||
label L1
|
||||
push this 1
|
||||
push constant 2
|
||||
eq
|
||||
not
|
||||
if-goto L2
|
||||
push this 0
|
||||
call Square.moveDown 1
|
||||
pop temp 0
|
||||
goto L3
|
||||
label L2
|
||||
label L3
|
||||
push this 1
|
||||
push constant 3
|
||||
eq
|
||||
not
|
||||
if-goto L4
|
||||
push this 0
|
||||
call Square.moveLeft 1
|
||||
pop temp 0
|
||||
goto L5
|
||||
label L4
|
||||
label L5
|
||||
push this 1
|
||||
push constant 4
|
||||
eq
|
||||
not
|
||||
if-goto L6
|
||||
push this 0
|
||||
call Square.moveRight 1
|
||||
pop temp 0
|
||||
goto L7
|
||||
label L6
|
||||
label L7
|
||||
push constant 5
|
||||
call Sys.wait 1
|
||||
pop temp 0
|
||||
push constant 0
|
||||
return
|
||||
function SquareGame.run 2
|
||||
push argument 0
|
||||
pop pointer 0
|
||||
push constant 0
|
||||
pop local 1
|
||||
label L8
|
||||
push local 1
|
||||
not
|
||||
not
|
||||
if-goto L9
|
||||
label L10
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
if-goto L11
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push pointer 0
|
||||
call SquareGame.moveSquare 1
|
||||
pop temp 0
|
||||
goto L10
|
||||
label L11
|
||||
push local 0
|
||||
push constant 81
|
||||
eq
|
||||
not
|
||||
if-goto L12
|
||||
push constant 1
|
||||
neg
|
||||
pop local 1
|
||||
goto L13
|
||||
label L12
|
||||
label L13
|
||||
push local 0
|
||||
push constant 90
|
||||
eq
|
||||
not
|
||||
if-goto L14
|
||||
push this 0
|
||||
call Square.decSize 1
|
||||
pop temp 0
|
||||
goto L15
|
||||
label L14
|
||||
label L15
|
||||
push local 0
|
||||
push constant 88
|
||||
eq
|
||||
not
|
||||
if-goto L16
|
||||
push this 0
|
||||
call Square.incSize 1
|
||||
pop temp 0
|
||||
goto L17
|
||||
label L16
|
||||
label L17
|
||||
push local 0
|
||||
push constant 131
|
||||
eq
|
||||
not
|
||||
if-goto L18
|
||||
push constant 1
|
||||
pop this 1
|
||||
goto L19
|
||||
label L18
|
||||
label L19
|
||||
push local 0
|
||||
push constant 133
|
||||
eq
|
||||
not
|
||||
if-goto L20
|
||||
push constant 2
|
||||
pop this 1
|
||||
goto L21
|
||||
label L20
|
||||
label L21
|
||||
push local 0
|
||||
push constant 130
|
||||
eq
|
||||
not
|
||||
if-goto L22
|
||||
push constant 3
|
||||
pop this 1
|
||||
goto L23
|
||||
label L22
|
||||
label L23
|
||||
push local 0
|
||||
push constant 132
|
||||
eq
|
||||
not
|
||||
if-goto L24
|
||||
push constant 4
|
||||
pop this 1
|
||||
goto L25
|
||||
label L24
|
||||
label L25
|
||||
label L26
|
||||
push local 0
|
||||
push constant 0
|
||||
eq
|
||||
not
|
||||
not
|
||||
if-goto L27
|
||||
call Keyboard.keyPressed 0
|
||||
pop local 0
|
||||
push pointer 0
|
||||
call SquareGame.moveSquare 1
|
||||
pop temp 0
|
||||
goto L26
|
||||
label L27
|
||||
goto L8
|
||||
label L9
|
||||
push constant 0
|
||||
return
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
+2
@@ -0,0 +1,2 @@
|
||||
python3
|
||||
debug
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
class Symbol:
|
||||
def __init__(self):
|
||||
self.s_name = ''
|
||||
self.s_kind = ''
|
||||
self.s_type = ''
|
||||
self.s_index = 0
|
||||
|
||||
|
||||
class SymbolTable:
|
||||
def __init__(self):
|
||||
self.sym = []
|
||||
|
||||
def define(self, s_name, s_type, s_kind):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = s_kind
|
||||
self.sym[-1].s_index = self.var_count(s_kind) - 1
|
||||
|
||||
def start_subroutine(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = s_name
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'argument'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def start_class(self, s_name, s_type):
|
||||
self.sym.append(Symbol())
|
||||
self.sym[-1].s_name = 'this'
|
||||
self.sym[-1].s_type = s_type
|
||||
self.sym[-1].s_kind = 'field'
|
||||
self.sym[-1].s_index = 0
|
||||
|
||||
def var_count(self, s_kind):
|
||||
count = 0 # it is -1 so the first index is 0
|
||||
for i in self.sym:
|
||||
if i.s_kind == s_kind:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def kind_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
if i.s_kind == 'var':
|
||||
return 'local'
|
||||
elif i.s_kind == 'field':
|
||||
return 'this'
|
||||
else:
|
||||
return i.s_kind
|
||||
return None
|
||||
|
||||
def type_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_type
|
||||
return None
|
||||
|
||||
def index_of(self, s_name):
|
||||
for i in self.sym:
|
||||
if i.s_name == s_name:
|
||||
return i.s_index
|
||||
return None
|
||||
Executable
+78
@@ -0,0 +1,78 @@
|
||||
import re
|
||||
|
||||
|
||||
class Tokenizer:
|
||||
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
self.file = ''
|
||||
self.symbols = ('(', ')', '[', ']', '}', '{', '>', '<', '=', '*', '+', '-', '/', '.', ';', ',', '&', '|',
|
||||
'~')
|
||||
self.key_word = (
|
||||
'class', 'method', 'function', 'constructor', 'int', 'boolean', 'char', 'void', 'var', 'static', 'field',
|
||||
'let', 'do', 'if', 'else', 'while', 'return', 'true', 'false', 'null', 'this')
|
||||
self.token = ''
|
||||
|
||||
def token_type(self, token=None):
|
||||
if token is None:
|
||||
token = self.token
|
||||
if token is None or token == '':
|
||||
return None
|
||||
if token in self.key_word:
|
||||
return 'keyword'
|
||||
elif token[0] == '"':
|
||||
return 'stringConstant'
|
||||
elif re.match(r"\d+", token):
|
||||
return 'integerConstant'
|
||||
elif token in self.symbols:
|
||||
return 'symbol'
|
||||
else:
|
||||
return 'identifier'
|
||||
|
||||
def advance(self):
|
||||
token = ''
|
||||
i = self.i
|
||||
while i < len(self.file):
|
||||
if re.match(r'\s', self.file[i]):
|
||||
i = i + 1
|
||||
continue
|
||||
else:
|
||||
if self.file[i] in self.symbols:
|
||||
self.token = self.file[i]
|
||||
self.i = i + 1
|
||||
return
|
||||
elif self.file[i] == '"':
|
||||
i += 1
|
||||
while self.file[i] != '"':
|
||||
token += self.file[i]
|
||||
i += 1
|
||||
self.i = i + 1
|
||||
self.token = '"' + token + '"'
|
||||
return
|
||||
else:
|
||||
while re.match(r'\w', self.file[i]):
|
||||
token += self.file[i]
|
||||
if i + 1 > len(self.file) - 1:
|
||||
break
|
||||
i += 1
|
||||
self.i = i
|
||||
self.token = token
|
||||
return
|
||||
|
||||
def clear_file(self, directory):
|
||||
with open(directory, "r") as my_file:
|
||||
txt = my_file.read()
|
||||
txt = re.sub(r"//.*", "", txt)
|
||||
txt = re.sub(r"/[*][*].*[*]/", "", txt)
|
||||
i = 0
|
||||
# TODO this should be a regex
|
||||
while i < len(txt):
|
||||
if txt[i] == '/' and txt[i + 1] == '*' and txt[i + 2] == '*':
|
||||
start = i
|
||||
while txt[i] != '*' or txt[i + 1] != '/':
|
||||
i += 1
|
||||
stop = i + 2
|
||||
txt = txt[:start] + txt[stop:len(txt)]
|
||||
i = start - 1
|
||||
i += 1
|
||||
self.file = txt
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
class VMWriter:
|
||||
def __init__(self, vm_path):
|
||||
self.my_vm = open(vm_path, "w+")
|
||||
self.label_index = 0
|
||||
|
||||
def write_push(self, segment, index):
|
||||
self.my_vm.write(f'push {segment} {index}\n')
|
||||
print(f'push {segment} {index}')
|
||||
|
||||
def write_lable(self, label):
|
||||
self.my_vm.write(f'label L{label}\n')
|
||||
print(f'label L{label}')
|
||||
|
||||
def write_arithmetic(self, command):
|
||||
if command == '+':
|
||||
self.my_vm.write('add\n')
|
||||
print('add')
|
||||
elif command == '-':
|
||||
self.my_vm.write('sub\n')
|
||||
print('sub')
|
||||
elif command == 'neg':
|
||||
self.my_vm.write('neg\n')
|
||||
print('neg')
|
||||
elif command == '=':
|
||||
self.my_vm.write('eq\n')
|
||||
print('eq')
|
||||
elif command == '>':
|
||||
self.my_vm.write('gt\n')
|
||||
print('gt')
|
||||
elif command == '<':
|
||||
self.my_vm.write('lt\n')
|
||||
print('lt')
|
||||
elif command == '&':
|
||||
self.my_vm.write('and\n')
|
||||
print('and')
|
||||
elif command == '|':
|
||||
self.my_vm.write('or\n')
|
||||
print('or')
|
||||
elif command == '~':
|
||||
self.my_vm.write('not\n')
|
||||
print('not')
|
||||
elif command == '*':
|
||||
self.write_call('Math.multiply', 2)
|
||||
elif command == '/':
|
||||
self.write_call('Math.divide', 2)
|
||||
|
||||
def write_pop(self, segment, index):
|
||||
print(f'pop {segment} {index}')
|
||||
self.my_vm.write(f'pop {segment} {index}\n')
|
||||
|
||||
def write_goto(self, label):
|
||||
self.my_vm.write(f'goto L{label}\n')
|
||||
print(f'goto L{label}')
|
||||
|
||||
def write_if(self, label):
|
||||
self.write_arithmetic('~')
|
||||
self.my_vm.write(f'if-goto L{label}\n')
|
||||
print(f'if-goto L{label}')
|
||||
|
||||
def write_call(self, label, num_args):
|
||||
self.my_vm.write(f'call {label} {num_args}\n')
|
||||
print(f'call {label} {num_args}')
|
||||
|
||||
def write_function(self, label, num_locals):
|
||||
self.my_vm.write(f'function {label} {num_locals}\n')
|
||||
print(f'function {label} {num_locals}')
|
||||
|
||||
def write_return(self, func_type):
|
||||
if func_type == 'void':
|
||||
self.write_push('constant', '0')
|
||||
self.my_vm.write('return\n')
|
||||
print(f'return')
|
||||
|
||||
def close_vm_file(self):
|
||||
self.my_vm.close()
|
||||
Reference in New Issue
Block a user