This commit is contained in:
QkoSad
2025-07-16 13:00:37 +03:00
commit 7894b48931
806 changed files with 162532 additions and 0 deletions
+29
View File
@@ -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/12/Array.jack
/**
* Represents an array.
* In the Jack language, arrays are instances of the Array class.
* Once declared, the array entries can be accessed using the usual
* syntax arr[i]. Each array entry can hold a primitive data type as
* well as any object type. Different array entries can have different
* data types.
*/
class Array {
/** Constructs a new Array of the given size. */
function Array new(int size) {
if(size < 0){
do Sys.error(7);
}
return Memory.alloc(size);
}
/** Disposes this array. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
}
+29
View File
@@ -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/12/Array.jack
/**
* Represents an array.
* In the Jack language, arrays are instances of the Array class.
* Once declared, the array entries can be accessed using the usual
* syntax arr[i]. Each array entry can hold a primitive data type as
* well as any object type. Different array entries can have different
* data types.
*/
class Array {
/** Constructs a new Array of the given size. */
function Array new(int size) {
if(size < 0){
do Sys.error(7);
}
return Memory.alloc(size);
}
/** Disposes this array. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
}
+23
View File
@@ -0,0 +1,23 @@
function Array.new 0
push argument 0
push constant 0
lt
not
if-goto L0
push constant 7
call Sys.error 1
pop temp 0
goto L1
label L0
label L1
push argument 0
call Memory.alloc 1
return
function Array.dispose 0
push argument 0
pop pointer 0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
+2
View File
@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|
| 222 | 122 | 100 | 10 |
View File
+15
View File
@@ -0,0 +1,15 @@
// 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/12/ArrayTest/ArrayTest.tst
load,
output-file ArrayTest.out,
compare-to ArrayTest.cmp,
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1;
repeat 1000000 {
vmstep;
}
output;
+40
View File
@@ -0,0 +1,40 @@
// 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/12/ArrayTest/Main.jack
/** Test program for the OS Array class. */
class Main {
/** Performs several Array manipulations. */
function void main() {
var Array r; // stores test results
var Array a, b, c;
let r = 8000;
let a = Array.new(3);
let a[2] = 222;
let r[0] = a[2]; // RAM[8000] = 222
let b = Array.new(3);
let b[1] = a[2] - 100;
let r[1] = b[1]; // RAM[8001] = 122
let c = Array.new(500);
let c[499] = a[2] - b[1];
let r[2] = c[499]; // RAM[8002] = 100
do a.dispose();
do b.dispose();
let b = Array.new(3);
let b[0] = c[499] - 90;
let r[3] = b[0]; // RAM[8003] = 10
do c.dispose();
do b.dispose();
return;
}
}
+131
View File
@@ -0,0 +1,131 @@
function Main.main 4
push constant 8000
pop local 0
push constant 3
call Array.new 1
pop local 1
push local 1
push constant 2
push constant 222
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 0
push local 1
push constant 2
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 3
call Array.new 1
pop local 2
push local 2
push constant 1
push local 1
push constant 2
add
pop pointer 1
push that 0
push constant 100
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 1
push local 2
push constant 1
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 500
call Array.new 1
pop local 3
push local 3
push constant 499
push local 1
push constant 2
add
pop pointer 1
push that 0
push local 2
push constant 1
add
pop pointer 1
push that 0
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 2
push local 3
push constant 499
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
call Array.dispose 1
pop temp 0
push local 2
call Array.dispose 1
pop temp 0
push constant 3
call Array.new 1
pop local 2
push local 2
push constant 0
push local 3
push constant 499
add
pop pointer 1
push that 0
push constant 90
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 3
push local 2
push constant 0
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
call Array.dispose 1
pop temp 0
push local 2
call Array.dispose 1
pop temp 0
push constant 0
return
+102
View File
@@ -0,0 +1,102 @@
// 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/12/Keyboard.jack
/**
* A library for handling user input from the keyboard.
*/
class Keyboard {
static Array mem;
/** Initializes the keyboard. */
function void init() {
let mem = 0;
return;
}
/**
* Returns the character of the currently pressed key on the keyboard;
* if no key is currently pressed, returns 0.
*
* Recognizes all ASCII characters, as well as the following keys:
* new line = 128 = String.newline()
* backspace = 129 = String.backspace()
* left arrow = 130
* up arrow = 131
* right arrow = 132
* down arrow = 133
* home = 134
* End = 135
* page up = 136
* page down = 137
* insert = 138
* delete = 139
* ESC = 140
* F1 - F12 = 141 - 152
*/
function char keyPressed() {
return mem[24576];
}
/**
* Waits until a key is pressed on the keyboard and released,
* then echoes the key to the screen, and returns the character
* of the pressed key.
*/
function char readChar() {
var char a, b;
do Output.printChar(0);
while ((b = 0) | (a > 0)){
let a = Keyboard.keyPressed();
if (a > 0){
let b = a;
}
}
do Output.printChar(String.backSpace());
do Output.printChar(b);
return b;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its value. Also handles user backspaces.
*/
function String readLine(String message) {
var String s, b;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Keyboard.readChar();
if (c = 128){
return s;
}
else{
if (c = 129){
do s.eraseLastChar();
}
else{
do s.appendChar(c);
}
}
}
return;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its integer value (until the first non-digit character in the
* entered text is detected). Also handles user backspaces.
*/
function int readInt(String message) {
var starting a;
var int b;
let a = Main.readLine_stolen(message);
let b = String.intValue(a);
do String.dispose(a);
return b;
}
}
+101
View File
@@ -0,0 +1,101 @@
// 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/12/Keyboard.jack
/**
* A library for handling user input from the keyboard.
*/
class Keyboard {
static Array mem;
/** Initializes the keyboard. */
function void init() {
let mem = 0;
return;
}
/**
* Returns the character of the currently pressed key on the keyboard;
* if no key is currently pressed, returns 0.
*
* Recognizes all ASCII characters, as well as the following keys:
* new line = 128 = String.newline()
* backspace = 129 = String.backspace()
* left arrow = 130
* up arrow = 131
* right arrow = 132
* down arrow = 133
* home = 134
* End = 135
* page up = 136
* page down = 137
* insert = 138
* delete = 139
* ESC = 140
* F1 - F12 = 141 - 152
*/
function char keyPressed() {
return mem[24576];
}
/**
* Waits until a key is pressed on the keyboard and released,
* then echoes the key to the screen, and returns the character
* of the pressed key.
*/
function char readChar() {
var char a, b;
do Output.printChar(0);
while ((b = 0) | (a > 0)){
let a = Keyboard.keyPressed();
if (a > 0){
let b = a;
}
}
do Output.printChar(String.backSpace());
do Output.printChar(b);
return b;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its value. Also handles user backspaces.
*/
function String readLine(String message) {
var String s, b;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Keyboard.readChar();
if (c = 128){
return s;
}
else{
if (c = 129){
do s.eraseLastChar();
}
else{
do s.appendChar(c);
}
}
}
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its integer value (until the first non-digit character in the
* entered text is detected). Also handles user backspaces.
*/
function int readInt(String message) {
var starting a;
var int b;
let a = Main.readLine_stolen(message);
let b = String.intValue(a);
do String.dispose(a);
return b;
}
}
+156
View File
@@ -0,0 +1,156 @@
function Keyboard.init 0
push constant 0
pop static 0
push constant 0
return
function Keyboard.keyPressed 0
push static 0
push constant 24576
add
pop pointer 1
push that 0
return
function Keyboard.readChar 2
push constant 0
call Output.printChar 1
pop temp 0
label L0
push local 1
push constant 0
eq
push local 0
push constant 0
gt
or
not
if-goto L1
call Keyboard.keyPressed 0
pop local 0
push local 0
push constant 0
gt
not
if-goto L2
push local 0
pop local 1
goto L3
label L2
label L3
goto L0
label L1
call String.backSpace 0
call Output.printChar 1
pop temp 0
push local 1
call Output.printChar 1
pop temp 0
push local 1
return
function Keyboard.readLine 3
push constant 100
call String.new 1
pop local 0
push argument 0
call Output.printString 1
pop temp 0
label L4
push constant 1
neg
not
if-goto L5
call Keyboard.readChar 0
pop local 2
push local 2
push constant 128
eq
not
if-goto L6
push local 0
return
goto L7
label L6
push local 2
push constant 129
eq
not
if-goto L8
push local 0
call String.eraseLastChar 1
pop temp 0
goto L9
label L8
push local 0
push local 2
call String.appendChar 2
pop temp 0
label L9
label L7
goto L4
label L5
function Keyboard.readInt 2
push constant 100
call String.new 1
pop local 0
push argument 0
call Output.printString 1
pop temp 0
label L10
push constant 1
neg
not
if-goto L11
push local 1
call Keyboard.readChar 1
pop local 1
push local 1
push constant 128
eq
not
if-goto L12
push local 0
call String.intValue 1
return
goto L13
label L12
push local 1
push constant 129
eq
not
if-goto L14
push local 0
call String.eraseLastChar 1
pop temp 0
goto L15
label L14
push local 1
push constant 47
gt
push local 1
push constant 57
lt
and
not
if-goto L16
push local 0
push local 1
call String.appendChar 2
pop temp 0
goto L17
label L16
label L17
push local 1
push constant 45
eq
not
if-goto L18
push local 0
push local 1
call String.appendChar 2
pop temp 0
goto L19
label L18
label L19
label L15
label L13
goto L10
label L11
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+93
View File
@@ -0,0 +1,93 @@
// 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/12/KeyboardTest/Main.jack
/** Test program for the OS Keyboard class. */
class Main {
/** Gets input from the user and verifies its contents. */
function void main() {
var char c, key;
var String s;
var int i;
var boolean ok;
let ok = false;
do Output.printString("keyPressed test:");
do Output.println();
while (~ok) {
do Output.printString("Please press the 'Page Down' key");
while (key = 0) {
let key = Keyboard.keyPressed();
}
let c = key;
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
do Output.println();
if (c = 137) {
do Output.printString("ok");
do Output.println();
let ok = true;
}
}
let ok = false;
do Output.printString("readChar test:");
do Output.println();
do Output.printString("(Verify that the pressed character is echoed to the screen)");
do Output.println();
while (~ok) {
do Output.printString("Please press the number '3': ");
let c = Keyboard.readChar();
do Output.println();
if (c = 51) {
do Output.printString("ok");
do Output.println();
let ok = true;
}
}
let ok = false;
do Output.printString("readLine test:");
do Output.println();
do Output.printString("(Verify echo and usage of 'backspace')");
do Output.println();
while (~ok) {
let s = Keyboard.readLine("Please type 'JACK' and press enter: ");
if (s.length() = 4) {
if ((s.charAt(0) = 74) & (s.charAt(1) = 65) & (s.charAt(2) = 67) & (s.charAt(3) = 75)) {
do Output.printString("ok");
do Output.println();
let ok = true;
}
}
}
let ok = false;
do Output.printString("readInt test:");
do Output.println();
do Output.printString("(Verify echo and usage of 'backspace')");
do Output.println();
while (~ok) {
let i = Keyboard.readInt("Please type '-32123' and press enter: ");
if (i = (-32123)) {
do Output.printString("ok");
do Output.println();
let ok = true;
}
}
do Output.println();
do Output.printString("Test completed successfully");
return;
}
}
+954
View File
@@ -0,0 +1,954 @@
function Main.main 5
push constant 0
pop local 4
push constant 16
call String.new 1
push constant 107
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 80
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 115
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 116
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 58
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
label L0
push local 4
not
not
if-goto L1
push constant 32
call String.new 1
push constant 80
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 112
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 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 39
call String.appendChar 2
push constant 80
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 68
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 119
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 121
call String.appendChar 2
call Output.printString 1
pop temp 0
label L2
push local 1
push constant 0
eq
not
if-goto L3
call Keyboard.keyPressed 0
pop local 1
goto L2
label L3
push local 1
pop local 0
label L4
push local 1
push constant 0
eq
not
not
if-goto L5
call Keyboard.keyPressed 0
pop local 1
goto L4
label L5
call Output.println 0
pop temp 0
push local 0
push constant 137
eq
not
if-goto L6
push constant 2
call String.new 1
push constant 111
call String.appendChar 2
push constant 107
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 1
neg
pop local 4
goto L7
label L6
label L7
goto L0
label L1
push constant 0
pop local 4
push constant 14
call String.new 1
push constant 114
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 58
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 59
call String.new 1
push constant 40
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 112
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 115
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 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
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 101
call String.appendChar 2
push constant 114
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
push constant 101
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 111
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 116
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 115
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 41
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
label L8
push local 4
not
not
if-goto L9
push constant 29
call String.new 1
push constant 80
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 112
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 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 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 32
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 51
call String.appendChar 2
push constant 39
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
call Keyboard.readChar 0
pop local 0
call Output.println 0
pop temp 0
push local 0
push constant 51
eq
not
if-goto L10
push constant 2
call String.new 1
push constant 111
call String.appendChar 2
push constant 107
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 1
neg
pop local 4
goto L11
label L10
label L11
goto L8
label L9
push constant 0
pop local 4
push constant 14
call String.new 1
push constant 114
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 76
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 58
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 38
call String.new 1
push constant 40
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 115
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 111
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 98
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 41
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
label L12
push local 4
not
not
if-goto L13
push constant 36
call String.new 1
push constant 80
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 74
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 75
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 112
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 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 101
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 58
call String.appendChar 2
push constant 32
call String.appendChar 2
call Keyboard.readLine 1
pop local 2
push local 2
call String.length 1
push constant 4
eq
not
if-goto L14
push local 2
push constant 0
call String.charAt 2
push constant 74
eq
push local 2
push constant 1
call String.charAt 2
push constant 65
eq
and
push local 2
push constant 2
call String.charAt 2
push constant 67
eq
and
push local 2
push constant 3
call String.charAt 2
push constant 75
eq
and
not
if-goto L15
push constant 2
call String.new 1
push constant 111
call String.appendChar 2
push constant 107
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 1
neg
pop local 4
goto L16
label L15
label L16
goto L17
label L14
label L17
goto L12
label L13
push constant 0
pop local 4
push constant 13
call String.new 1
push constant 114
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 73
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 58
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 38
call String.new 1
push constant 40
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 115
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 111
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 98
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 41
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
label L18
push local 4
not
not
if-goto L19
push constant 38
call String.new 1
push constant 80
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 45
call String.appendChar 2
push constant 51
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 49
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 51
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 112
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 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 101
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 58
call String.appendChar 2
push constant 32
call String.appendChar 2
call Keyboard.readInt 1
pop local 3
push local 3
push constant 32123
neg
eq
not
if-goto L20
push constant 2
call String.new 1
push constant 111
call String.appendChar 2
push constant 107
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 1
neg
pop local 4
goto L21
label L20
label L21
goto L18
label L19
call Output.println 0
pop temp 0
push constant 27
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 99
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 109
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
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 115
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 102
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 121
call String.appendChar 2
call Output.printString 1
pop temp 0
push constant 0
return
+143
View File
@@ -0,0 +1,143 @@
// 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/12/Math.jack
/**
* A library of commonly used mathematical functions.
* Note: Jack compilers implement multiplication and division using OS method calls.
*/
class Math {
static Array st;
static int division_tmp, f;
/** Initializes the library. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
return;
}
/** Returns the absolute value of x. */
function int abs(int x) {
if (x > 0){
return x;
}
return -x;
}
/** Returns the product of x and y.
* When a Jack compiler detects the multiplication operator '*' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x*y and multiply(x,y) return the same value.
*/
function int multiply(int x, int y) {
var int sum, temp, y_comp, i, neg;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (x < y){
let temp = x;
let x = y;
let y = temp;
}
if (y = 1){
if(neg){
return -x;
}
return x;
}
while((y_comp - 1) < (y - 1)){
if ((st[i] & y) > 0) {
let sum = sum + x;
let y_comp = y_comp + st[i];
}
let x = x + x;
let i = i + 1;
}
if(neg){
let sum = -sum;
}
return sum;
}
/** Returns the integer part of x/y.
* When a Jack compiler detects the multiplication operator '/' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x/y and divide(x,y) return the same value.
*/
function int divide(int x, int y) {
var int q, neg;
if (f = 0){
let division_tmp = 0;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (y = 0){
do Sys.error(3);
}
let f = 1;
}
if ((y > x) | (y < 0)){
return 0;
}
let q = Math.divide(x, y + y);
let f = 0;
let q = Math.abs(q);
if ((q & 1) = 1){
let division_tmp = division_tmp + y + y;
}
if (x - division_tmp < y){
if (neg){
return -(q + q);
}
return q + q;
}
else{
if (neg){
return -(q + q + 1);
}
return q + q + 1;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int j, b, d, y;
if (x < 0){
do Sys.error(4);
}
let j = 7;
while (j > -1){
let d = y + st[j];
let b = d * d;
if ((~(b > x)) & (b > 0)){
let y = d;
}
let j = j - 1;
}
return y;
}
/** Returns the greater number. */
function int max(int a, int b) {
if (a > b){
return a;
}
return b;
}
/** Returns the smaller number. */
function int min(int a, int b) {
if (a < b){
return a;
}
return b;
}
}
+23
View File
@@ -0,0 +1,23 @@
function Array.new 0
push argument 0
push constant 0
gt
not
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 2
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
call Memory.alloc 1
return
function Array.dispose 0
push argument 0
pop pointer 0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
+102
View File
@@ -0,0 +1,102 @@
function Keyboard.init 0
push constant 0
return
function Keyboard.keyPressed 0
push constant 24576
call Memory.peek 1
return
function Keyboard.readChar 2
push constant 0
call Output.printChar 1
pop temp 0
label WHILE_EXP0
push local 1
push constant 0
eq
push local 0
push constant 0
gt
or
not
if-goto WHILE_END0
call Keyboard.keyPressed 0
pop local 0
push local 0
push constant 0
gt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 0
pop local 1
label IF_FALSE0
goto WHILE_EXP0
label WHILE_END0
call String.backSpace 0
call Output.printChar 1
pop temp 0
push local 1
call Output.printChar 1
pop temp 0
push local 1
return
function Keyboard.readLine 5
push constant 80
call String.new 1
pop local 3
push argument 0
call Output.printString 1
pop temp 0
call String.newLine 0
pop local 1
call String.backSpace 0
pop local 2
label WHILE_EXP0
push local 4
not
not
if-goto WHILE_END0
call Keyboard.readChar 0
pop local 0
push local 0
push local 1
eq
pop local 4
push local 4
not
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 0
push local 2
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 3
call String.eraseLastChar 1
pop temp 0
goto IF_END1
label IF_FALSE1
push local 3
push local 0
call String.appendChar 2
pop local 3
label IF_END1
label IF_FALSE0
goto WHILE_EXP0
label WHILE_END0
push local 3
return
function Keyboard.readInt 2
push argument 0
call Keyboard.readLine 1
pop local 0
push local 0
call String.intValue 1
pop local 1
push local 0
call String.dispose 1
pop temp 0
push local 1
return
+35
View File
@@ -0,0 +1,35 @@
// 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/12/MathTest/Main.jack
/** Test program for the OS Math class. */
class Main {
/** Performs various mathematical operations, using calls to the Math class methods. */
function void main() {
var Array r; // stores the test results;
let r = 8000;
let r[0] = 2 * 3; // 6
let r[1] = r[0] * (-30); // 6 * (-30) = -180
let r[2] = r[1] * 100; // (-180) * 100 = -18000
let r[3] = 1 * r[2]; // 1 * (-18000) = -18000
let r[4] = r[3] * 0; // 0
let r[5] = 9 / 3; // 3
let r[6] = (-18000) / 6; // -3000
let r[7] = 32766 / (-32767); // 0
let r[8] = Math.sqrt(9); // 3
let r[9] = Math.sqrt(32767); // 181
let r[10] = Math.min(345, 123); // 123
let r[11] = Math.max(123, -345); // 123
let r[12] = Math.abs(27); // 27
let r[13] = Math.abs(-32767); // 32767
return;
}
}
+162
View File
@@ -0,0 +1,162 @@
function Main.main 1
push constant 8000
pop local 0
push local 0
push constant 0
push constant 2
push constant 3
call Math.multiply 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 1
push local 0
push constant 0
add
pop pointer 1
push that 0
push constant 30
neg
call Math.multiply 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 2
push local 0
push constant 1
add
pop pointer 1
push that 0
push constant 100
call Math.multiply 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 3
push constant 1
push local 0
push constant 2
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 0
push constant 4
push local 0
push constant 3
add
pop pointer 1
push that 0
push constant 0
call Math.multiply 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 5
push constant 9
push constant 3
call Math.divide 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 6
push constant 18000
neg
push constant 6
call Math.divide 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 7
push constant 32766
push constant 32767
neg
call Math.divide 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 8
push constant 9
call Math.sqrt 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 9
push constant 32767
call Math.sqrt 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 10
push constant 345
push constant 123
call Math.min 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 11
push constant 123
push constant 345
neg
call Math.max 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 12
push constant 27
call Math.abs 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 13
push constant 32767
neg
call Math.abs 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
+143
View File
@@ -0,0 +1,143 @@
// 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/12/Math.jack
/**
* A library of commonly used mathematical functions.
* Note: Jack compilers implement multiplication and division using OS method calls.
*/
class Math {
static Array st;
static int division_tmp, f;
/** Initializes the library. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
return;
}
/** Returns the absolute value of x. */
function int abs(int x) {
if (x > 0){
return x;
}
return -x;
}
/** Returns the product of x and y.
* When a Jack compiler detects the multiplication operator '*' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x*y and multiply(x,y) return the same value.
*/
function int multiply(int x, int y) {
var int sum, temp, y_comp, i, neg;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (x < y){
let temp = x;
let x = y;
let y = temp;
}
if (y = 1){
if(neg){
return -x;
}
return x;
}
while((y_comp - 1) < (y - 1)){
if ((st[i] & y) > 0) {
let sum = sum + x;
let y_comp = y_comp + st[i];
}
let x = x + x;
let i = i + 1;
}
if(neg){
let sum = -sum;
}
return sum;
}
/** Returns the integer part of x/y.
* When a Jack compiler detects the multiplication operator '/' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x/y and divide(x,y) return the same value.
*/
function int divide(int x, int y) {
var int q, neg;
if (f = 0){
let division_tmp = 0;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (y = 0){
do Sys.error(3);
}
let f = 1;
}
if ((y > x) | (y < 0)){
return 0;
}
let q = divide(x, y + y);
let f = 0;
let q = Math.abs(q);
if ((q & 1) = 1){
let division_tmp = division_tmp + y + y;
}
if (x - division_tmp < y){
if (neg){
return -(q + q);
}
return q + q;
}
else{
if (neg){
return -(q + q + 1);
}
return q + q + 1;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int j, b, d, y;
if (x < 0){
do Sys.error(4);
}
let j = 7;
while (j > -1){
let d = y + st[j];
let b = d * d;
if ((~(b > x)) & (b > 0)){
let y = d;
}
let j = j - 1;
}
return y;
}
/** Returns the greater number. */
function int max(int a, int b) {
if (a > b){
return a;
}
return b;
}
/** Returns the smaller number. */
function int min(int a, int b) {
if (a < b){
return a;
}
return b;
}
}
+388
View File
@@ -0,0 +1,388 @@
function Math.init 1
push constant 16
call Array.new 1
pop static 0
push static 0
push constant 0
push constant 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
label L0
push local 0
push constant 15
lt
not
if-goto L1
push local 0
push constant 1
add
pop local 0
push static 0
push local 0
push static 0
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
push static 0
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
add
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
goto L0
label L1
push constant 0
return
function Math.abs 0
push argument 0
push constant 0
gt
not
if-goto L2
push argument 0
return
goto L3
label L2
label L3
push argument 0
neg
return
function Math.multiply 5
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 4
push argument 0
call Math.abs 1
pop argument 0
push argument 1
call Math.abs 1
pop argument 1
push argument 0
push argument 1
lt
not
if-goto L4
push argument 0
pop local 1
push argument 1
pop argument 0
push local 1
pop argument 1
goto L5
label L4
label L5
push argument 1
push constant 1
eq
not
if-goto L6
push local 4
not
if-goto L7
push argument 0
neg
return
goto L8
label L7
label L8
push argument 0
return
goto L9
label L6
label L9
label L10
push local 2
push constant 1
sub
push argument 1
push constant 1
sub
lt
not
if-goto L11
push static 0
push local 3
add
pop pointer 1
push that 0
push argument 1
and
push constant 0
gt
not
if-goto L12
push local 0
push argument 0
add
pop local 0
push local 2
push static 0
push local 3
add
pop pointer 1
push that 0
add
pop local 2
goto L13
label L12
label L13
push argument 0
push argument 0
add
pop argument 0
push local 3
push constant 1
add
pop local 3
goto L10
label L11
push local 4
not
if-goto L14
push local 0
neg
pop local 0
goto L15
label L14
label L15
push local 0
return
function Math.divide 2
push static 2
push constant 0
eq
not
if-goto L16
push constant 0
pop static 1
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 1
push argument 0
call Math.abs 1
pop argument 0
push argument 1
call Math.abs 1
pop argument 1
push argument 1
push constant 0
eq
not
if-goto L17
push constant 3
call Sys.error 1
pop temp 0
goto L18
label L17
label L18
push constant 1
pop static 2
goto L19
label L16
label L19
push argument 1
push argument 0
gt
push argument 1
push constant 0
lt
or
not
if-goto L20
push constant 0
return
goto L21
label L20
label L21
push argument 0
push argument 1
push argument 1
add
call Math.divide 2
pop local 0
push constant 0
pop static 2
push local 0
call Math.abs 1
pop local 0
push local 0
push constant 1
and
push constant 1
eq
not
if-goto L22
push static 1
push argument 1
add
push argument 1
add
pop static 1
goto L23
label L22
label L23
push argument 0
push static 1
sub
push argument 1
lt
not
if-goto L24
push local 1
not
if-goto L25
push local 0
push local 0
add
neg
return
goto L26
label L25
label L26
push local 0
push local 0
add
return
goto L27
label L24
push local 1
not
if-goto L28
push local 0
push local 0
add
push constant 1
add
neg
return
goto L29
label L28
label L29
push local 0
push local 0
add
push constant 1
add
return
label L27
function Math.sqrt 4
push argument 0
push constant 0
lt
not
if-goto L30
push constant 4
call Sys.error 1
pop temp 0
goto L31
label L30
label L31
push constant 7
pop local 0
label L32
push local 0
push constant 1
neg
gt
not
if-goto L33
push local 3
push static 0
push local 0
add
pop pointer 1
push that 0
add
pop local 2
push local 2
push local 2
call Math.multiply 2
pop local 1
push local 1
push argument 0
gt
not
push local 1
push constant 0
gt
and
not
if-goto L34
push local 2
pop local 3
goto L35
label L34
label L35
push local 0
push constant 1
sub
pop local 0
goto L32
label L33
push local 3
return
function Math.max 0
push argument 0
push argument 1
gt
not
if-goto L36
push argument 0
return
goto L37
label L36
label L37
push argument 1
return
function Math.min 0
push argument 0
push argument 1
lt
not
if-goto L38
push argument 0
return
goto L39
label L38
label L39
push argument 1
return
+2
View File
@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|RAM[8006]|RAM[8007]|RAM[8008]|RAM[8009]|RAM[8010]|RAM[8011]|RAM[8012]|RAM[8013]|
| 6 | -180 | -18000 | -18000 | 0 | 3 | -3000 | 0 | 3 | 181 | 123 | 123 | 27 | 32767 |
View File
+15
View File
@@ -0,0 +1,15 @@
// 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/12/MathTest/MathTest.tst
load,
output-file MathTest.out,
compare-to MathTest.cmp,
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1 RAM[8006]%D2.6.1 RAM[8007]%D2.6.1 RAM[8008]%D2.6.1 RAM[8009]%D2.6.1 RAM[8010]%D2.6.1 RAM[8011]%D2.6.1 RAM[8012]%D2.6.1 RAM[8013]%D2.6.1;
repeat 1150000 {
vmstep;
}
output;
+376
View File
@@ -0,0 +1,376 @@
function Memory.init 0
push constant 0
pop static 0
push constant 2048
push static 0
add
push constant 14334
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 2049
push static 0
add
push constant 2050
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 0
return
function Memory.peek 0
push argument 0
push static 0
add
pop pointer 1
push that 0
return
function Memory.poke 0
push argument 0
push static 0
add
push argument 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 0
return
function Memory.alloc 2
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 5
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 0
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 1
pop argument 0
label IF_FALSE1
push constant 2048
pop local 0
label WHILE_EXP0
push local 0
push constant 16383
lt
push constant 0
push local 0
add
pop pointer 1
push that 0
push argument 0
lt
and
not
if-goto WHILE_END0
push constant 1
push local 0
add
pop pointer 1
push that 0
pop local 1
push constant 0
push local 0
add
pop pointer 1
push that 0
push constant 0
eq
push local 1
push constant 16382
gt
or
push constant 0
push local 1
add
pop pointer 1
push that 0
push constant 0
eq
or
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 1
pop local 0
goto IF_END2
label IF_FALSE2
push constant 0
push local 0
add
push constant 1
push local 0
add
pop pointer 1
push that 0
push local 0
sub
push constant 0
push local 1
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 1
push local 1
add
pop pointer 1
push that 0
push local 1
push constant 2
add
eq
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push constant 1
push local 0
add
push local 0
push constant 2
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END3
label IF_FALSE3
push constant 1
push local 0
add
push constant 1
push local 1
add
pop pointer 1
push that 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_END3
label IF_END2
goto WHILE_EXP0
label WHILE_END0
push local 0
push argument 0
add
push constant 16379
gt
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push constant 6
call Sys.error 1
pop temp 0
label IF_FALSE4
push constant 0
push local 0
add
pop pointer 1
push that 0
push argument 0
push constant 2
add
gt
if-goto IF_TRUE5
goto IF_FALSE5
label IF_TRUE5
push argument 0
push constant 2
add
push local 0
add
push constant 0
push local 0
add
pop pointer 1
push that 0
push argument 0
sub
push constant 2
sub
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 1
push local 0
add
pop pointer 1
push that 0
push local 0
push constant 2
add
eq
if-goto IF_TRUE6
goto IF_FALSE6
label IF_TRUE6
push argument 0
push constant 3
add
push local 0
add
push local 0
push argument 0
add
push constant 4
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END6
label IF_FALSE6
push argument 0
push constant 3
add
push local 0
add
push constant 1
push local 0
add
pop pointer 1
push that 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_END6
push constant 1
push local 0
add
push local 0
push argument 0
add
push constant 2
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_FALSE5
push constant 0
push local 0
add
push constant 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 2
add
return
function Memory.deAlloc 2
push argument 0
push constant 2
sub
pop local 0
push constant 1
push local 0
add
pop pointer 1
push that 0
pop local 1
push constant 0
push local 1
add
pop pointer 1
push that 0
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 0
push local 0
add
push constant 1
push local 0
add
pop pointer 1
push that 0
push local 0
sub
push constant 2
sub
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END0
label IF_FALSE0
push constant 0
push local 0
add
push constant 1
push local 0
add
pop pointer 1
push that 0
push local 0
sub
push constant 0
push local 1
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 1
push local 1
add
pop pointer 1
push that 0
push local 1
push constant 2
add
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 1
push local 0
add
push local 0
push constant 2
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END1
label IF_FALSE1
push constant 1
push local 0
add
push constant 1
push local 1
add
pop pointer 1
push that 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_END1
label IF_END0
push constant 0
return
+1852
View File
File diff suppressed because it is too large Load Diff
+806
View File
@@ -0,0 +1,806 @@
function Screen.init 1
push constant 16384
pop static 1
push constant 0
not
pop static 2
push constant 17
call Array.new 1
pop static 0
push constant 0
push static 0
add
push constant 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
label WHILE_EXP0
push local 0
push constant 16
lt
not
if-goto WHILE_END0
push local 0
push constant 1
add
pop local 0
push local 0
push static 0
add
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.clearScreen 1
label WHILE_EXP0
push local 0
push constant 8192
lt
not
if-goto WHILE_END0
push local 0
push static 1
add
push constant 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.updateLocation 0
push static 2
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
push static 1
add
push argument 0
push static 1
add
pop pointer 1
push that 0
push argument 1
or
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END0
label IF_FALSE0
push argument 0
push static 1
add
push argument 0
push static 1
add
pop pointer 1
push that 0
push argument 1
not
and
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_END0
push constant 0
return
function Screen.setColor 0
push argument 0
pop static 2
push constant 0
return
function Screen.drawPixel 3
push argument 0
push constant 0
lt
push argument 0
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 1
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 7
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 16
call Math.divide 2
pop local 0
push argument 0
push local 0
push constant 16
call Math.multiply 2
sub
pop local 1
push argument 1
push constant 32
call Math.multiply 2
push local 0
add
pop local 2
push local 2
push local 1
push static 0
add
pop pointer 1
push that 0
call Screen.updateLocation 2
pop temp 0
push constant 0
return
function Screen.drawConditional 0
push argument 2
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 1
push argument 0
call Screen.drawPixel 2
pop temp 0
goto IF_END0
label IF_FALSE0
push argument 0
push argument 1
call Screen.drawPixel 2
pop temp 0
label IF_END0
push constant 0
return
function Screen.drawLine 11
push argument 0
push constant 0
lt
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 8
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 2
push argument 0
sub
call Math.abs 1
pop local 3
push argument 3
push argument 1
sub
call Math.abs 1
pop local 2
push local 3
push local 2
lt
pop local 6
push local 6
push argument 3
push argument 1
lt
and
push local 6
not
push argument 2
push argument 0
lt
and
or
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push argument 0
pop local 4
push argument 2
pop argument 0
push local 4
pop argument 2
push argument 1
pop local 4
push argument 3
pop argument 1
push local 4
pop argument 3
label IF_FALSE1
push local 6
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 3
pop local 4
push local 2
pop local 3
push local 4
pop local 2
push argument 1
pop local 1
push argument 0
pop local 0
push argument 3
pop local 8
push argument 0
push argument 2
gt
pop local 7
goto IF_END2
label IF_FALSE2
push argument 0
pop local 1
push argument 1
pop local 0
push argument 2
pop local 8
push argument 1
push argument 3
gt
pop local 7
label IF_END2
push constant 2
push local 2
call Math.multiply 2
push local 3
sub
pop local 5
push constant 2
push local 2
call Math.multiply 2
pop local 9
push constant 2
push local 2
push local 3
sub
call Math.multiply 2
pop local 10
push local 1
push local 0
push local 6
call Screen.drawConditional 3
pop temp 0
label WHILE_EXP0
push local 1
push local 8
lt
not
if-goto WHILE_END0
push local 5
push constant 0
lt
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push local 5
push local 9
add
pop local 5
goto IF_END3
label IF_FALSE3
push local 5
push local 10
add
pop local 5
push local 7
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push local 0
push constant 1
sub
pop local 0
goto IF_END4
label IF_FALSE4
push local 0
push constant 1
add
pop local 0
label IF_END4
label IF_END3
push local 1
push constant 1
add
pop local 1
push local 1
push local 0
push local 6
call Screen.drawConditional 3
pop temp 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.drawRectangle 9
push argument 0
push argument 2
gt
push argument 1
push argument 3
gt
or
push argument 0
push constant 0
lt
or
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 9
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 16
call Math.divide 2
pop local 3
push argument 0
push local 3
push constant 16
call Math.multiply 2
sub
pop local 7
push argument 2
push constant 16
call Math.divide 2
pop local 4
push argument 2
push local 4
push constant 16
call Math.multiply 2
sub
pop local 8
push local 7
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
not
pop local 6
push local 8
push constant 1
add
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
pop local 5
push argument 1
push constant 32
call Math.multiply 2
push local 3
add
pop local 0
push local 4
push local 3
sub
pop local 2
label WHILE_EXP0
push argument 1
push argument 3
gt
not
not
if-goto WHILE_END0
push local 0
push local 2
add
pop local 1
push local 2
push constant 0
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push local 5
push local 6
and
call Screen.updateLocation 2
pop temp 0
goto IF_END1
label IF_FALSE1
push local 0
push local 6
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
label WHILE_EXP1
push local 0
push local 1
lt
not
if-goto WHILE_END1
push local 0
push constant 1
neg
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP1
label WHILE_END1
push local 1
push local 5
call Screen.updateLocation 2
pop temp 0
label IF_END1
push argument 1
push constant 1
add
pop argument 1
push local 1
push constant 32
add
push local 2
sub
pop local 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.drawHorizontal 11
push argument 1
push argument 2
call Math.min 2
pop local 7
push argument 1
push argument 2
call Math.max 2
pop local 8
push argument 0
push constant 1
neg
gt
push argument 0
push constant 256
lt
and
push local 7
push constant 512
lt
and
push local 8
push constant 1
neg
gt
and
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 7
push constant 0
call Math.max 2
pop local 7
push local 8
push constant 511
call Math.min 2
pop local 8
push local 7
push constant 16
call Math.divide 2
pop local 1
push local 7
push local 1
push constant 16
call Math.multiply 2
sub
pop local 9
push local 8
push constant 16
call Math.divide 2
pop local 2
push local 8
push local 2
push constant 16
call Math.multiply 2
sub
pop local 10
push local 9
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
not
pop local 5
push local 10
push constant 1
add
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
pop local 4
push argument 0
push constant 32
call Math.multiply 2
push local 1
add
pop local 0
push local 2
push local 1
sub
pop local 6
push local 0
push local 6
add
pop local 3
push local 6
push constant 0
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push local 4
push local 5
and
call Screen.updateLocation 2
pop temp 0
goto IF_END1
label IF_FALSE1
push local 0
push local 5
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
label WHILE_EXP0
push local 0
push local 3
lt
not
if-goto WHILE_END0
push local 0
push constant 1
neg
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP0
label WHILE_END0
push local 3
push local 4
call Screen.updateLocation 2
pop temp 0
label IF_END1
label IF_FALSE0
push constant 0
return
function Screen.drawSymetric 0
push argument 1
push argument 3
sub
push argument 0
push argument 2
add
push argument 0
push argument 2
sub
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 3
add
push argument 0
push argument 2
add
push argument 0
push argument 2
sub
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 2
sub
push argument 0
push argument 3
sub
push argument 0
push argument 3
add
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 2
add
push argument 0
push argument 3
sub
push argument 0
push argument 3
add
call Screen.drawHorizontal 3
pop temp 0
push constant 0
return
function Screen.drawCircle 3
push argument 0
push constant 0
lt
push argument 0
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 1
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 12
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push argument 2
sub
push constant 0
lt
push argument 0
push argument 2
add
push constant 511
gt
or
push argument 1
push argument 2
sub
push constant 0
lt
or
push argument 1
push argument 2
add
push constant 255
gt
or
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 13
call Sys.error 1
pop temp 0
label IF_FALSE1
push argument 2
pop local 1
push constant 1
push argument 2
sub
pop local 2
push argument 0
push argument 1
push local 0
push local 1
call Screen.drawSymetric 4
pop temp 0
label WHILE_EXP0
push local 1
push local 0
gt
not
if-goto WHILE_END0
push local 2
push constant 0
lt
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 2
push constant 2
push local 0
call Math.multiply 2
add
push constant 3
add
pop local 2
goto IF_END2
label IF_FALSE2
push local 2
push constant 2
push local 0
push local 1
sub
call Math.multiply 2
add
push constant 5
add
pop local 2
push local 1
push constant 1
sub
pop local 1
label IF_END2
push local 0
push constant 1
add
pop local 0
push argument 0
push argument 1
push local 0
push local 1
call Screen.drawSymetric 4
pop temp 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
+393
View File
@@ -0,0 +1,393 @@
function String.new 0
push constant 3
call Memory.alloc 1
pop pointer 0
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 14
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 0
gt
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push argument 0
call Array.new 1
pop this 1
label IF_FALSE1
push argument 0
pop this 0
push constant 0
pop this 2
push pointer 0
return
function String.dispose 0
push argument 0
pop pointer 0
push this 0
push constant 0
gt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push this 1
call Array.dispose 1
pop temp 0
label IF_FALSE0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
function String.length 0
push argument 0
pop pointer 0
push this 2
return
function String.charAt 0
push argument 0
pop pointer 0
push argument 1
push constant 0
lt
push argument 1
push this 2
gt
or
push argument 1
push this 2
eq
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 15
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 1
push this 1
add
pop pointer 1
push that 0
return
function String.setCharAt 0
push argument 0
pop pointer 0
push argument 1
push constant 0
lt
push argument 1
push this 2
gt
or
push argument 1
push this 2
eq
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 16
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 1
push this 1
add
push argument 2
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 0
return
function String.appendChar 0
push argument 0
pop pointer 0
push this 2
push this 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 17
call Sys.error 1
pop temp 0
label IF_FALSE0
push this 2
push this 1
add
push argument 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
push this 2
push constant 1
add
pop this 2
push pointer 0
return
function String.eraseLastChar 0
push argument 0
pop pointer 0
push this 2
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 18
call Sys.error 1
pop temp 0
label IF_FALSE0
push this 2
push constant 1
sub
pop this 2
push constant 0
return
function String.intValue 5
push argument 0
pop pointer 0
push this 2
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 0
return
label IF_FALSE0
push constant 0
not
pop local 3
push constant 0
push this 1
add
pop pointer 1
push that 0
push constant 45
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 0
not
pop local 4
push constant 1
pop local 0
label IF_FALSE1
label WHILE_EXP0
push local 0
push this 2
lt
push local 3
and
not
if-goto WHILE_END0
push local 0
push this 1
add
pop pointer 1
push that 0
push constant 48
sub
pop local 2
push local 2
push constant 0
lt
push local 2
push constant 9
gt
or
not
pop local 3
push local 3
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 1
push constant 10
call Math.multiply 2
push local 2
add
pop local 1
push local 0
push constant 1
add
pop local 0
label IF_FALSE2
goto WHILE_EXP0
label WHILE_END0
push local 4
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push local 1
neg
pop local 1
label IF_FALSE3
push local 1
return
function String.setInt 4
push argument 0
pop pointer 0
push this 0
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 19
call Sys.error 1
pop temp 0
label IF_FALSE0
push constant 6
call Array.new 1
pop local 2
push argument 1
push constant 0
lt
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 0
not
pop local 3
push argument 1
neg
pop argument 1
label IF_FALSE1
push argument 1
pop local 1
label WHILE_EXP0
push local 1
push constant 0
gt
not
if-goto WHILE_END0
push argument 1
push constant 10
call Math.divide 2
pop local 1
push local 0
push local 2
add
push constant 48
push argument 1
push local 1
push constant 10
call Math.multiply 2
sub
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
push local 1
pop argument 1
goto WHILE_EXP0
label WHILE_END0
push local 3
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 0
push local 2
add
push constant 45
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
label IF_FALSE2
push this 0
push local 0
lt
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push constant 19
call Sys.error 1
pop temp 0
label IF_FALSE3
push local 0
push constant 0
eq
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push constant 0
push this 1
add
push constant 48
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 1
pop this 2
goto IF_END4
label IF_FALSE4
push constant 0
pop this 2
label WHILE_EXP1
push this 2
push local 0
lt
not
if-goto WHILE_END1
push this 2
push this 1
add
push local 0
push this 2
push constant 1
add
sub
push local 2
add
pop pointer 1
push that 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
push this 2
push constant 1
add
pop this 2
goto WHILE_EXP1
label WHILE_END1
label IF_END4
push local 2
call Array.dispose 1
pop temp 0
push constant 0
return
function String.newLine 0
push constant 128
return
function String.backSpace 0
push constant 129
return
function String.doubleQuote 0
push constant 34
return
+83
View File
@@ -0,0 +1,83 @@
function Sys.init 0
call Memory.init 0
pop temp 0
call Math.init 0
pop temp 0
call Screen.init 0
pop temp 0
call Output.init 0
pop temp 0
call Keyboard.init 0
pop temp 0
call Main.main 0
pop temp 0
call Sys.halt 0
pop temp 0
push constant 0
return
function Sys.halt 0
label WHILE_EXP0
push constant 0
not
not
if-goto WHILE_END0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Sys.wait 1
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 1
call Sys.error 1
pop temp 0
label IF_FALSE0
label WHILE_EXP0
push argument 0
push constant 0
gt
not
if-goto WHILE_END0
push constant 50
pop local 0
label WHILE_EXP1
push local 0
push constant 0
gt
not
if-goto WHILE_END1
push local 0
push constant 1
sub
pop local 0
goto WHILE_EXP1
label WHILE_END1
push argument 0
push constant 1
sub
pop argument 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Sys.error 0
push constant 69
call Output.printChar 1
pop temp 0
push constant 82
call Output.printChar 1
pop temp 0
push constant 82
call Output.printChar 1
pop temp 0
push argument 0
call Output.printInt 1
pop temp 0
call Sys.halt 0
pop temp 0
push constant 0
return
+63
View File
@@ -0,0 +1,63 @@
// 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/12/Memory.jack
/**
* This library provides two services: direct access to the computer's main
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
* consists of 32,768 words, each holding a 16-bit binary number.
*/
class Memory {
static Array mem;
/** Initializes the class. */
function void init() {
let mem = 0;
let mem[2048] = 14334;
let mem[2049] = -1;
return;
}
/** Returns the RAM value at the given address. */
function int peek(int address) {
return mem[address];
}
/** Sets the RAM value at the given address to the given value. */
function void poke(int address, int value) {
let mem[address] = value;
return;
}
/** Finds an available RAM block of the given size and returns
* a reference to its base address. */
function int alloc(int size) {
var Array current_block;
var int tmp;
let current_block = 2048;
if (size < 0){
do Sys.error(5);
}
if (size = 0){
let size = 1;
}
while (current_block[0] < (size + 2)) {
let current_block = current_block[1];
}
let current_block[0] = current_block[0] - size - 2;
let current_block = current_block + current_block[0] + 2;
let current_block[0] = size;
return current_block + 2;
}
/** De-allocates the given object (cast as an array) by making
* it available for future allocations. */
function void deAlloc(Array o) {
var Array current_block;
let current_block = 2048;
let o[1]= current_block[1];
let current_block[1] = o;
return;
}
}
+23
View File
@@ -0,0 +1,23 @@
function Array.new 0
push argument 0
push constant 0
gt
not
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 2
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
call Memory.alloc 1
return
function Array.dispose 0
push argument 0
pop pointer 0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
+102
View File
@@ -0,0 +1,102 @@
function Keyboard.init 0
push constant 0
return
function Keyboard.keyPressed 0
push constant 24576
call Memory.peek 1
return
function Keyboard.readChar 2
push constant 0
call Output.printChar 1
pop temp 0
label WHILE_EXP0
push local 1
push constant 0
eq
push local 0
push constant 0
gt
or
not
if-goto WHILE_END0
call Keyboard.keyPressed 0
pop local 0
push local 0
push constant 0
gt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 0
pop local 1
label IF_FALSE0
goto WHILE_EXP0
label WHILE_END0
call String.backSpace 0
call Output.printChar 1
pop temp 0
push local 1
call Output.printChar 1
pop temp 0
push local 1
return
function Keyboard.readLine 5
push constant 80
call String.new 1
pop local 3
push argument 0
call Output.printString 1
pop temp 0
call String.newLine 0
pop local 1
call String.backSpace 0
pop local 2
label WHILE_EXP0
push local 4
not
not
if-goto WHILE_END0
call Keyboard.readChar 0
pop local 0
push local 0
push local 1
eq
pop local 4
push local 4
not
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 0
push local 2
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 3
call String.eraseLastChar 1
pop temp 0
goto IF_END1
label IF_FALSE1
push local 3
push local 0
call String.appendChar 2
pop local 3
label IF_END1
label IF_FALSE0
goto WHILE_EXP0
label WHILE_END0
push local 3
return
function Keyboard.readInt 2
push argument 0
call Keyboard.readLine 1
pop local 0
push local 0
call String.intValue 1
pop local 1
push local 0
call String.dispose 1
pop temp 0
push local 1
return
+53
View File
@@ -0,0 +1,53 @@
// 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/12/MemoryTest/Main.jack
/** Test program for the OS Memory class. */
class Main {
/** Performs various memory manipulations. */
function void main() {
var int temp, err;
var Array a, b, c;
do Memory.poke(8000, 333); // RAM[8000] = 333
let temp = Memory.peek(8000);
do Memory.poke(8001, temp + 1); // RAM[8001] = 334
let a = Array.new(3); // uses Memory.alloc
let a[2] = 222;
do Memory.poke(8002, a[2]); // RAM[8002] = 222
let err = 0;
let b = Array.new(3);
let b[1] = a[2] - 100;
if (b = a) { // Fail compare if b = a
let err = 1; }
do Memory.poke(8003, b[1] + err); // RAM[8003] = 122
let err = 0;
let c = Array.new(500);
let c[499] = a[2] - b[1];
if (c = a) { // Fail compare if c = a
let err = 1; }
if (c = b) { // Fail compare if c = b
let err = err + 10; }
do Memory.poke(8004, c[499]+err); // RAM[8004] = 100
do a.dispose(); // uses Memory.deAlloc
do b.dispose();
let err = 0;
let b = Array.new(3);
let b[0] = c[499] - 90;
if (b = c) { // Fail compare if b = c
let err = 1; }
do Memory.poke(8005, b[0] + err); // RAM[8005] = 10
do c.dispose();
do b.dispose();
return;
}
}
+180
View File
@@ -0,0 +1,180 @@
function Main.main 5
push constant 8000
push constant 333
call Memory.poke 2
pop temp 0
push constant 8000
call Memory.peek 1
pop local 0
push constant 8001
push local 0
push constant 1
add
call Memory.poke 2
pop temp 0
push constant 3
call Array.new 1
pop local 2
push local 2
push constant 2
push constant 222
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 8002
push local 2
push constant 2
add
pop pointer 1
push that 0
call Memory.poke 2
pop temp 0
push constant 0
pop local 1
push constant 3
call Array.new 1
pop local 3
push local 3
push constant 1
push local 2
push constant 2
add
pop pointer 1
push that 0
push constant 100
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
push local 2
eq
not
if-goto L0
push constant 1
pop local 1
goto L1
label L0
label L1
push constant 8003
push local 3
push constant 1
add
pop pointer 1
push that 0
push local 1
add
call Memory.poke 2
pop temp 0
push constant 0
pop local 1
push constant 500
call Array.new 1
pop local 4
push local 4
push constant 499
push local 2
push constant 2
add
pop pointer 1
push that 0
push local 3
push constant 1
add
pop pointer 1
push that 0
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push local 2
eq
not
if-goto L2
push constant 1
pop local 1
goto L3
label L2
label L3
push local 4
push local 3
eq
not
if-goto L4
push local 1
push constant 10
add
pop local 1
goto L5
label L4
label L5
push constant 8004
push local 4
push constant 499
add
pop pointer 1
push that 0
push local 1
add
call Memory.poke 2
pop temp 0
push local 2
call Array.dispose 1
pop temp 0
push local 3
call Array.dispose 1
pop temp 0
push constant 0
pop local 1
push constant 3
call Array.new 1
pop local 3
push local 3
push constant 0
push local 4
push constant 499
add
pop pointer 1
push that 0
push constant 90
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
push local 4
eq
not
if-goto L6
push constant 1
pop local 1
goto L7
label L6
label L7
push constant 8005
push local 3
push constant 0
add
pop pointer 1
push that 0
push local 1
add
call Memory.poke 2
pop temp 0
push local 4
call Array.dispose 1
pop temp 0
push local 3
call Array.dispose 1
pop temp 0
push constant 0
return
+408
View File
@@ -0,0 +1,408 @@
function Math.init 1
push constant 16
call Array.new 1
pop static 1
push constant 16
call Array.new 1
pop static 0
push constant 0
push static 0
add
push constant 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
label WHILE_EXP0
push local 0
push constant 15
lt
not
if-goto WHILE_END0
push local 0
push constant 1
add
pop local 0
push local 0
push static 0
add
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Math.abs 0
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
neg
pop argument 0
label IF_FALSE0
push argument 0
return
function Math.multiply 5
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 4
push argument 0
call Math.abs 1
pop argument 0
push argument 1
call Math.abs 1
pop argument 1
push argument 0
push argument 1
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
pop local 1
push argument 1
pop argument 0
push local 1
pop argument 1
label IF_FALSE0
label WHILE_EXP0
push local 2
push constant 1
sub
push argument 1
push constant 1
sub
lt
not
if-goto WHILE_END0
push local 3
push static 0
add
pop pointer 1
push that 0
push argument 1
and
push constant 0
eq
not
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push argument 0
add
pop local 0
push local 2
push local 3
push static 0
add
pop pointer 1
push that 0
add
pop local 2
label IF_FALSE1
push argument 0
push argument 0
add
pop argument 0
push local 3
push constant 1
add
pop local 3
goto WHILE_EXP0
label WHILE_END0
push local 4
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 0
neg
pop local 0
label IF_FALSE2
push local 0
return
function Math.divide 4
push argument 1
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 3
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 2
push constant 0
push static 1
add
push argument 1
call Math.abs 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
push argument 0
call Math.abs 1
pop argument 0
label WHILE_EXP0
push local 0
push constant 15
lt
push local 3
not
and
not
if-goto WHILE_END0
push constant 32767
push local 0
push static 1
add
pop pointer 1
push that 0
push constant 1
sub
sub
push local 0
push static 1
add
pop pointer 1
push that 0
push constant 1
sub
lt
pop local 3
push local 3
not
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push constant 1
add
push static 1
add
push local 0
push static 1
add
pop pointer 1
push that 0
push local 0
push static 1
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
push static 1
add
pop pointer 1
push that 0
push constant 1
sub
push argument 0
push constant 1
sub
gt
pop local 3
push local 3
not
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 0
push constant 1
add
pop local 0
label IF_FALSE2
label IF_FALSE1
goto WHILE_EXP0
label WHILE_END0
label WHILE_EXP1
push local 0
push constant 1
neg
gt
not
if-goto WHILE_END1
push local 0
push static 1
add
pop pointer 1
push that 0
push constant 1
sub
push argument 0
push constant 1
sub
gt
not
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push local 1
push local 0
push static 0
add
pop pointer 1
push that 0
add
pop local 1
push argument 0
push local 0
push static 1
add
pop pointer 1
push that 0
sub
pop argument 0
label IF_FALSE3
push local 0
push constant 1
sub
pop local 0
goto WHILE_EXP1
label WHILE_END1
push local 2
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push local 1
neg
pop local 1
label IF_FALSE4
push local 1
return
function Math.sqrt 4
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 4
call Sys.error 1
pop temp 0
label IF_FALSE0
push constant 7
pop local 0
label WHILE_EXP0
push local 0
push constant 1
neg
gt
not
if-goto WHILE_END0
push local 3
push local 0
push static 0
add
pop pointer 1
push that 0
add
pop local 1
push local 1
push local 1
call Math.multiply 2
pop local 2
push local 2
push argument 0
gt
not
push local 2
push constant 0
lt
not
and
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 1
pop local 3
label IF_FALSE1
push local 0
push constant 1
sub
pop local 0
goto WHILE_EXP0
label WHILE_END0
push local 3
return
function Math.max 0
push argument 0
push argument 1
gt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
pop argument 1
label IF_FALSE0
push argument 1
return
function Math.min 0
push argument 0
push argument 1
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
pop argument 1
label IF_FALSE0
push argument 1
return
+63
View File
@@ -0,0 +1,63 @@
// 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/12/Memory.jack
/**
* This library provides two services: direct access to the computer's main
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
* consists of 32,768 words, each holding a 16-bit binary number.
*/
class Memory {
static Array mem;
/** Initializes the class. */
function void init() {
let mem = 0;
let mem[2048] = 14334;
let mem[2049] = -1;
return;
}
/** Returns the RAM value at the given address. */
function int peek(int address) {
return mem[address];
}
/** Sets the RAM value at the given address to the given value. */
function void poke(int address, int value) {
let mem[address] = value;
return;
}
/** Finds an available RAM block of the given size and returns
* a reference to its base address. */
function int alloc(int size) {
var Array current_block;
var int tmp;
let current_block = 2048;
if (size < 0){
do Sys.error(5);
}
if (size = 0){
let size = 1;
}
while (current_block[0] < (size + 2)) {
let current_block = current_block[1];
}
let current_block[0] = current_block[0] - size - 2;
let current_block = current_block + current_block[0] + 2;
let current_block[0] = size;
return current_block + 2;
}
/** De-allocates the given object (cast as an array) by making
* it available for future allocations. */
function void deAlloc(Array o) {
var Array current_block;
let current_block = 2048;
let o[1]= current_block[1];
let current_block[1] = o;
return;
}
}
+147
View File
@@ -0,0 +1,147 @@
function Memory.init 0
push constant 0
pop static 0
push static 0
push constant 2048
push constant 14334
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push static 0
push constant 2049
push constant 1
neg
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function Memory.peek 0
push static 0
push argument 0
add
pop pointer 1
push that 0
return
function Memory.poke 0
push static 0
push argument 0
push argument 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function Memory.alloc 2
push constant 2048
pop local 0
push argument 0
push constant 0
lt
not
if-goto L0
push constant 5
call Sys.error 1
pop temp 0
goto L1
label L0
label L1
push argument 0
push constant 0
eq
not
if-goto L2
push constant 1
pop argument 0
goto L3
label L2
label L3
label L4
push local 0
push constant 0
add
pop pointer 1
push that 0
push argument 0
push constant 2
add
lt
not
if-goto L5
push local 0
push constant 1
add
pop pointer 1
push that 0
pop local 0
goto L4
label L5
push local 0
push constant 0
push local 0
push constant 0
add
pop pointer 1
push that 0
push argument 0
sub
push constant 2
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push local 0
push constant 0
add
pop pointer 1
push that 0
add
push constant 2
add
pop local 0
push local 0
push constant 0
push argument 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 2
add
return
function Memory.deAlloc 1
push constant 2048
pop local 0
push argument 0
push constant 1
push local 0
push constant 1
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 1
push argument 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
+183
View File
@@ -0,0 +1,183 @@
// 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/12/MemoryTest/Main.jack
/** Test program for the OS Memory class. */
class Main {
/** Test Memory.peek(), poke(), alloc() and deAlloc().
*
* This test is also a diagnostic. RAM[17000] is incremented before and
* after every call so that the failure point can be accurately determined
* when using command line testing. Return values from all alloc() calls
* are also stored in the test results to aid debugging.
*/
function void main() {
var int temp;
var Array a, b, c, out;
let out = 17000; // Address where test results will be stored.
// Test poke() and peek().
let out[0] = 10; // poke test
do Memory.poke(out + 1, 333); // RAM[17001] = 333
let out[0] = 11; // peek test
let temp = Memory.peek(out + 1);
let out[2] = temp + 1; // RAM[17002] = 334
let out[0] = 12; // peek/poke test complete
// Allocate a memory block.
// Validate that the returned block is entirely within the heap,
// Test aborts if the block is not valid.
let out[0] = 20;
let a = Memory.alloc(20);
let out[3] = a; // RAM[17003] = block address
let out[0] = 21;
do Main.checkRange(a, 20);
let out[0] = 22;
// Allocate a SMALLER memory block.
// Validate that the returned block is entirely within the heap,
// and that it does not overlap block 'a'.
// Test aborts if the block is not valid or overlaps.
//
// Common failure: first block was not removed from free list so space
// for this block was found within the first block.
let out[0] = 30;
let b = Memory.alloc(3);
let out[4] = b; // RAM[17004] = block address
let out[0] = 31;
do Main.checkRange(b, 3);
let out[0] = 32;
do Main.checkOverlap(b, 3, a, 3);
let out[0] = 33;
// Allocate a memory block.
// Validate that the returned block is entirely within the heap,
// and that it does not overlap blocks 'a' or 'b'.
// Test aborts if the block is not valid or overlaps.
let out[0] = 40;
let c = Memory.alloc(500);
let out[5] = c; // RAM[17005] = block address
let out[0] = 41;
do Main.checkRange(c, 500);
let out[0] = 42;
do Main.checkOverlap(c, 500, a, 3);
let out[0] = 43;
do Main.checkOverlap(c, 500, b, 3);
let out[0] = 44;
// Deallocate blocks 'a' and 'b', retaining 'c'.
//
// Common failure: free list corrupted by deAlloc().
let out[0] = 50;
do Memory.deAlloc(a);
let out[0] = 51;
do Memory.deAlloc(b);
let out[0] = 52;
// Allocate a memory block.
// Validate that the returned block is entirely within the heap,
// and that it does not overlap blocks 'c'.
// Test aborts if the block is not valid or overlaps.
//
// Common failure: free list corrupted by deAlloc().
let out[0] = 60;
let b = Memory.alloc(3);
let out[6] = b; // RAM[17006] = block address
let out[0] = 61;
do Main.checkRange(b, 3);
let out[0] = 62;
do Main.checkOverlap(b, 3, c, 500);
let out[0] = 63;
// Deallocate blocks 'b' and 'c'.
let out[0] = 70;
do Memory.deAlloc(c);
let out[0] = 71;
do Memory.deAlloc(b);
let out[0] = 72;
// Test that deallocated blocks are placed on the free list and can
// be reused.
let out[0] = 70;
let a = Memory.alloc(8000);
let out[7] = a; // RAM[17007] = block address
let out[0] = 71;
do Main.checkRange(a, 8000);
let out[0] = 72;
do Memory.deAlloc(a);
let out[0] = 73;
let a = Memory.alloc(7000);
let out[0] = 74;
do Main.checkRange(a, 7000);
let out[0] = 75;
do Memory.deAlloc(a);
let out[8] = a; // RAM[17008] = block address
// Test complete.
let out[0] = 100;
// At this point all allocated blocks have been deallocated.
//
// You can inspect the free list and confirm that all of the heap is
// contained in the free segments.
//
// If you implemented defragmentation in dealloc(), the free list
// should contain only one segment, consisting of the entire heap.
return;
}
/** Check that block a(a_len) is in the heap.
*
* If the block begins or ends outside of the heap, calls Sys.halt()
*/
function void checkRange(int a, int a_len) {
var int a_high;
let a_high = (a + a_len)-1;
if ((a < 2048) | ((a_high) > 16383)) {
// Block is not entirely within heap.
do Sys.halt();
}
return;
}
/** Check that block a(a_len) does not overlap block b(b_len).
* Assumes that both blocks have been range checked.
*
* If the blocks overlap, calls Sys.halt()
*/
function void checkOverlap(int a, int a_len, int b, int b_len) {
var int a_high, b_high;
let a_high = (a + a_len)-1;
let b_high = (b + b_len)-1;
if ( ~ ((a > b_high) | (a_high < b))) {
// Block overlaps excluded range.
do Sys.halt();
}
return;
}
}
+467
View File
@@ -0,0 +1,467 @@
function Main.main 5
push constant 17000
pop local 4
push local 4
push constant 0
push constant 10
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 1
add
push constant 333
call Memory.poke 2
pop temp 0
push local 4
push constant 0
push constant 11
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 1
add
call Memory.peek 1
pop local 0
push local 4
push constant 2
push local 0
push constant 1
add
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 12
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 20
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 20
call Memory.alloc 1
pop local 1
push local 4
push constant 3
push local 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 21
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
push constant 20
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 22
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 30
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 3
call Memory.alloc 1
pop local 2
push local 4
push constant 4
push local 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 31
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
push constant 3
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 32
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
push constant 3
push local 1
push constant 3
call Main.checkOverlap 4
pop temp 0
push local 4
push constant 0
push constant 33
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 40
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 500
call Memory.alloc 1
pop local 3
push local 4
push constant 5
push local 3
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 41
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
push constant 500
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 42
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
push constant 500
push local 1
push constant 3
call Main.checkOverlap 4
pop temp 0
push local 4
push constant 0
push constant 43
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
push constant 500
push local 2
push constant 3
call Main.checkOverlap 4
pop temp 0
push local 4
push constant 0
push constant 44
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 50
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 0
push constant 51
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 0
push constant 52
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 60
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 3
call Memory.alloc 1
pop local 2
push local 4
push constant 6
push local 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 61
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
push constant 3
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 62
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
push constant 3
push local 3
push constant 500
call Main.checkOverlap 4
pop temp 0
push local 4
push constant 0
push constant 63
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 70
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 3
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 0
push constant 71
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 2
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 0
push constant 72
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 70
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 8000
call Memory.alloc 1
pop local 1
push local 4
push constant 7
push local 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 71
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
push constant 8000
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 72
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 0
push constant 73
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 7000
call Memory.alloc 1
pop local 1
push local 4
push constant 0
push constant 74
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
push constant 7000
call Main.checkRange 2
pop temp 0
push local 4
push constant 0
push constant 75
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 1
call Memory.deAlloc 1
pop temp 0
push local 4
push constant 8
push local 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 4
push constant 0
push constant 100
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function Main.checkRange 1
push argument 0
push argument 1
add
push constant 1
sub
pop local 0
push argument 0
push constant 2048
lt
push local 0
push constant 16383
gt
or
not
if-goto L0
call Sys.halt 0
pop temp 0
goto L1
label L0
label L1
push constant 0
return
function Main.checkOverlap 2
push argument 0
push argument 1
add
push constant 1
sub
pop local 0
push argument 2
push argument 3
add
push constant 1
sub
pop local 1
push argument 0
push local 1
gt
push local 0
push argument 2
lt
or
not
not
if-goto L2
call Sys.halt 0
pop temp 0
goto L3
label L2
label L3
push constant 0
return
+2
View File
@@ -0,0 +1,2 @@
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
| 100 | 333 | 334 |*********|*********|*********|*********|*********|*********|
+18
View File
@@ -0,0 +1,18 @@
// 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/12/MemoryTest/MemoryDiag/MemoryDiag.tst
echo "At the end of this test it is normal to see some pixels set on the screen";
load,
output-file MemoryDiag.out,
compare-to MemoryDiag.cmp,
output-list RAM[17000]%D2.6.1 RAM[17001]%D2.6.1 RAM[17002]%D2.6.1
RAM[17003]%D2.6.1 RAM[17004]%D2.6.1 RAM[17005]%D2.6.1 RAM[17006]%D2.6.1
RAM[17007]%D2.6.1 RAM[17008]%D2.6.1;
repeat 1000000 {
vmstep;
}
output;
+55
View File
@@ -0,0 +1,55 @@
<html>
<h4>MemoryDiag is both a pass/fail test and a diagnostic.</h4>
<p>
MemoryDiag tests the following:
<ol>
<li>Memory.peek() and Memory.poke() read from and write to the specified memory address.</li>
<li>Memory.alloc() returns RAM blocks that are fully contained within the heap address range 2048-16383.</li>
<li>Memory.alloc() does not return RAM blocks that overlap each other.</li>
<li>RAM blocks deallocated by Memory.deAlloc() are made available for Memory.alloc() to reuse.</li>
</ol>
The block reuse test allocates and deallocates an 8000 word block. It then tries to allocates a 7000 word block which must be allocated from the deallocated 8000 word block. If the 8000 word block is not available for reuse, there will only be about 6300 words available in the heap so you will get an ERR6.
<p>
<i>At the end of this test it is normal to see some pixels set on the screen.</i> This is because the results of the test are written to RAM[17000]&nbsp;&ndash; RAM[17008] which is in the Screen memory. MemoryDiag does not put its results in the first 16K of RAM because it must not interfere with the Memory.jack that is being tested.
<h4>Using MemoryDiag as a diagnostic</h4>
RAM[17000] is set to a unique value before every system call and address validation. This allows the exact failure location in the test to be identified when automated testing is used. At the end of the test, RAM[17000] is set to 100.
<p>
When the test fails to compare, look at the MemoryDiag.out file and note the RAM[17000] value. This is the test <i>step</i> that failed. Look through the Main.jack code and find the corresponding<br>
&emsp;&emsp;<tt>let out[0] = <i>step</i>;</tt><br>
statement. The function immediately following this statement is where the failure occurred.
<p>
For example, if RAM[17000] is 51, the<br>
&emsp;&emsp;<tt>do Memory.deAlloc(b);</tt><br>
call did not return. Either there was a simulation error like a bad address or deAlloc() got stuck in a loop.
<h4>Sample MemoryDiag output files</h4>
<i>Note that RAM[17003]&nbsp;&ndash; RAM[17008] are "don't care" values in the MemoryDiag.cmp file.</i>
<p>
Supplied Memory.vm passes:
<pre style="padding-left:2em;">
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
| 100 | 333 | 334 | 2050 | 2072 | 2077 | 2050 | 2050 | 2050 |
</pre>
Memory.Jack using the Coursera implementation passes:
<pre style="padding-left:2em;">
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
| 100 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 8850 |
</pre>
Broken Memory.jack fails (alloc() returns duplicate block address):
<pre style="padding-left:2em;">
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
| 32 | 333 | 334 | 2050 | 2050 | 0 | 0 | 0 | 0 |
</pre>
Broken Memory.jack fails (deAlloc() does not recycle memory blocks):
<pre style="padding-left:2em;">
|RAM[17000|RAM[17001|RAM[17002|RAM[17003|RAM[17004|RAM[17005|RAM[17006|RAM[17007|RAM[17008|
| 73 | 333 | 334 | 16364 | 16359 | 15857 | 15852 | 7850 | 0 |
</pre>
</html>
<p>
+2
View File
@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
| 333 | 334 | 222 | 122 | 100 | 10 |
+2
View File
@@ -0,0 +1,2 @@
|RAM[8000]|RAM[8001]|RAM[8002]|RAM[8003]|RAM[8004]|RAM[8005]|
| 333 | 334 | 222 | 122 | 100 | 10 |
+15
View File
@@ -0,0 +1,15 @@
// 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/12/MemoryTest/MemoryTest.tst
load,
output-file MemoryTest.out,
compare-to MemoryTest.cmp,
output-list RAM[8000]%D2.6.1 RAM[8001]%D2.6.1 RAM[8002]%D2.6.1 RAM[8003]%D2.6.1 RAM[8004]%D2.6.1 RAM[8005]%D2.6.1;
repeat 1000000 {
vmstep;
}
output;
+1852
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
There are some specific wrong values that indicate that your Memory.jack
returned identical pointers to allocated segments. Look at Main.jack to
see where the pointers a, b and c are used.
RAM[8003] = 123 b = a
RAM[8004] = 101 c = a
RAM[8004] = 110 c = b
RAM[8004] = 111 c = a and c = b
RAM[8005] = 11 new b = c
+806
View File
@@ -0,0 +1,806 @@
function Screen.init 1
push constant 16384
pop static 1
push constant 0
not
pop static 2
push constant 17
call Array.new 1
pop static 0
push constant 0
push static 0
add
push constant 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
label WHILE_EXP0
push local 0
push constant 16
lt
not
if-goto WHILE_END0
push local 0
push constant 1
add
pop local 0
push local 0
push static 0
add
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
push local 0
push constant 1
sub
push static 0
add
pop pointer 1
push that 0
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.clearScreen 1
label WHILE_EXP0
push local 0
push constant 8192
lt
not
if-goto WHILE_END0
push local 0
push static 1
add
push constant 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.updateLocation 0
push static 2
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 0
push static 1
add
push argument 0
push static 1
add
pop pointer 1
push that 0
push argument 1
or
pop temp 0
pop pointer 1
push temp 0
pop that 0
goto IF_END0
label IF_FALSE0
push argument 0
push static 1
add
push argument 0
push static 1
add
pop pointer 1
push that 0
push argument 1
not
and
pop temp 0
pop pointer 1
push temp 0
pop that 0
label IF_END0
push constant 0
return
function Screen.setColor 0
push argument 0
pop static 2
push constant 0
return
function Screen.drawPixel 3
push argument 0
push constant 0
lt
push argument 0
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 1
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 7
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 16
call Math.divide 2
pop local 0
push argument 0
push local 0
push constant 16
call Math.multiply 2
sub
pop local 1
push argument 1
push constant 32
call Math.multiply 2
push local 0
add
pop local 2
push local 2
push local 1
push static 0
add
pop pointer 1
push that 0
call Screen.updateLocation 2
pop temp 0
push constant 0
return
function Screen.drawConditional 0
push argument 2
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push argument 1
push argument 0
call Screen.drawPixel 2
pop temp 0
goto IF_END0
label IF_FALSE0
push argument 0
push argument 1
call Screen.drawPixel 2
pop temp 0
label IF_END0
push constant 0
return
function Screen.drawLine 11
push argument 0
push constant 0
lt
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 8
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 2
push argument 0
sub
call Math.abs 1
pop local 3
push argument 3
push argument 1
sub
call Math.abs 1
pop local 2
push local 3
push local 2
lt
pop local 6
push local 6
push argument 3
push argument 1
lt
and
push local 6
not
push argument 2
push argument 0
lt
and
or
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push argument 0
pop local 4
push argument 2
pop argument 0
push local 4
pop argument 2
push argument 1
pop local 4
push argument 3
pop argument 1
push local 4
pop argument 3
label IF_FALSE1
push local 6
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 3
pop local 4
push local 2
pop local 3
push local 4
pop local 2
push argument 1
pop local 1
push argument 0
pop local 0
push argument 3
pop local 8
push argument 0
push argument 2
gt
pop local 7
goto IF_END2
label IF_FALSE2
push argument 0
pop local 1
push argument 1
pop local 0
push argument 2
pop local 8
push argument 1
push argument 3
gt
pop local 7
label IF_END2
push constant 2
push local 2
call Math.multiply 2
push local 3
sub
pop local 5
push constant 2
push local 2
call Math.multiply 2
pop local 9
push constant 2
push local 2
push local 3
sub
call Math.multiply 2
pop local 10
push local 1
push local 0
push local 6
call Screen.drawConditional 3
pop temp 0
label WHILE_EXP0
push local 1
push local 8
lt
not
if-goto WHILE_END0
push local 5
push constant 0
lt
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push local 5
push local 9
add
pop local 5
goto IF_END3
label IF_FALSE3
push local 5
push local 10
add
pop local 5
push local 7
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push local 0
push constant 1
sub
pop local 0
goto IF_END4
label IF_FALSE4
push local 0
push constant 1
add
pop local 0
label IF_END4
label IF_END3
push local 1
push constant 1
add
pop local 1
push local 1
push local 0
push local 6
call Screen.drawConditional 3
pop temp 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.drawRectangle 9
push argument 0
push argument 2
gt
push argument 1
push argument 3
gt
or
push argument 0
push constant 0
lt
or
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 9
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 16
call Math.divide 2
pop local 3
push argument 0
push local 3
push constant 16
call Math.multiply 2
sub
pop local 7
push argument 2
push constant 16
call Math.divide 2
pop local 4
push argument 2
push local 4
push constant 16
call Math.multiply 2
sub
pop local 8
push local 7
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
not
pop local 6
push local 8
push constant 1
add
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
pop local 5
push argument 1
push constant 32
call Math.multiply 2
push local 3
add
pop local 0
push local 4
push local 3
sub
pop local 2
label WHILE_EXP0
push argument 1
push argument 3
gt
not
not
if-goto WHILE_END0
push local 0
push local 2
add
pop local 1
push local 2
push constant 0
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push local 5
push local 6
and
call Screen.updateLocation 2
pop temp 0
goto IF_END1
label IF_FALSE1
push local 0
push local 6
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
label WHILE_EXP1
push local 0
push local 1
lt
not
if-goto WHILE_END1
push local 0
push constant 1
neg
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP1
label WHILE_END1
push local 1
push local 5
call Screen.updateLocation 2
pop temp 0
label IF_END1
push argument 1
push constant 1
add
pop argument 1
push local 1
push constant 32
add
push local 2
sub
pop local 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Screen.drawHorizontal 11
push argument 1
push argument 2
call Math.min 2
pop local 7
push argument 1
push argument 2
call Math.max 2
pop local 8
push argument 0
push constant 1
neg
gt
push argument 0
push constant 256
lt
and
push local 7
push constant 512
lt
and
push local 8
push constant 1
neg
gt
and
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push local 7
push constant 0
call Math.max 2
pop local 7
push local 8
push constant 511
call Math.min 2
pop local 8
push local 7
push constant 16
call Math.divide 2
pop local 1
push local 7
push local 1
push constant 16
call Math.multiply 2
sub
pop local 9
push local 8
push constant 16
call Math.divide 2
pop local 2
push local 8
push local 2
push constant 16
call Math.multiply 2
sub
pop local 10
push local 9
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
not
pop local 5
push local 10
push constant 1
add
push static 0
add
pop pointer 1
push that 0
push constant 1
sub
pop local 4
push argument 0
push constant 32
call Math.multiply 2
push local 1
add
pop local 0
push local 2
push local 1
sub
pop local 6
push local 0
push local 6
add
pop local 3
push local 6
push constant 0
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push local 0
push local 4
push local 5
and
call Screen.updateLocation 2
pop temp 0
goto IF_END1
label IF_FALSE1
push local 0
push local 5
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
label WHILE_EXP0
push local 0
push local 3
lt
not
if-goto WHILE_END0
push local 0
push constant 1
neg
call Screen.updateLocation 2
pop temp 0
push local 0
push constant 1
add
pop local 0
goto WHILE_EXP0
label WHILE_END0
push local 3
push local 4
call Screen.updateLocation 2
pop temp 0
label IF_END1
label IF_FALSE0
push constant 0
return
function Screen.drawSymetric 0
push argument 1
push argument 3
sub
push argument 0
push argument 2
add
push argument 0
push argument 2
sub
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 3
add
push argument 0
push argument 2
add
push argument 0
push argument 2
sub
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 2
sub
push argument 0
push argument 3
sub
push argument 0
push argument 3
add
call Screen.drawHorizontal 3
pop temp 0
push argument 1
push argument 2
add
push argument 0
push argument 3
sub
push argument 0
push argument 3
add
call Screen.drawHorizontal 3
pop temp 0
push constant 0
return
function Screen.drawCircle 3
push argument 0
push constant 0
lt
push argument 0
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 1
push constant 255
gt
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 12
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push argument 2
sub
push constant 0
lt
push argument 0
push argument 2
add
push constant 511
gt
or
push argument 1
push argument 2
sub
push constant 0
lt
or
push argument 1
push argument 2
add
push constant 255
gt
or
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 13
call Sys.error 1
pop temp 0
label IF_FALSE1
push argument 2
pop local 1
push constant 1
push argument 2
sub
pop local 2
push argument 0
push argument 1
push local 0
push local 1
call Screen.drawSymetric 4
pop temp 0
label WHILE_EXP0
push local 1
push local 0
gt
not
if-goto WHILE_END0
push local 2
push constant 0
lt
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 2
push constant 2
push local 0
call Math.multiply 2
add
push constant 3
add
pop local 2
goto IF_END2
label IF_FALSE2
push local 2
push constant 2
push local 0
push local 1
sub
call Math.multiply 2
add
push constant 5
add
pop local 2
push local 1
push constant 1
sub
pop local 1
label IF_END2
push local 0
push constant 1
add
pop local 0
push argument 0
push argument 1
push local 0
push local 1
call Screen.drawSymetric 4
pop temp 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
+393
View File
@@ -0,0 +1,393 @@
function String.new 0
push constant 3
call Memory.alloc 1
pop pointer 0
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 14
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 0
push constant 0
gt
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push argument 0
call Array.new 1
pop this 1
label IF_FALSE1
push argument 0
pop this 0
push constant 0
pop this 2
push pointer 0
return
function String.dispose 0
push argument 0
pop pointer 0
push this 0
push constant 0
gt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push this 1
call Array.dispose 1
pop temp 0
label IF_FALSE0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
function String.length 0
push argument 0
pop pointer 0
push this 2
return
function String.charAt 0
push argument 0
pop pointer 0
push argument 1
push constant 0
lt
push argument 1
push this 2
gt
or
push argument 1
push this 2
eq
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 15
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 1
push this 1
add
pop pointer 1
push that 0
return
function String.setCharAt 0
push argument 0
pop pointer 0
push argument 1
push constant 0
lt
push argument 1
push this 2
gt
or
push argument 1
push this 2
eq
or
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 16
call Sys.error 1
pop temp 0
label IF_FALSE0
push argument 1
push this 1
add
push argument 2
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 0
return
function String.appendChar 0
push argument 0
pop pointer 0
push this 2
push this 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 17
call Sys.error 1
pop temp 0
label IF_FALSE0
push this 2
push this 1
add
push argument 1
pop temp 0
pop pointer 1
push temp 0
pop that 0
push this 2
push constant 1
add
pop this 2
push pointer 0
return
function String.eraseLastChar 0
push argument 0
pop pointer 0
push this 2
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 18
call Sys.error 1
pop temp 0
label IF_FALSE0
push this 2
push constant 1
sub
pop this 2
push constant 0
return
function String.intValue 5
push argument 0
pop pointer 0
push this 2
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 0
return
label IF_FALSE0
push constant 0
not
pop local 3
push constant 0
push this 1
add
pop pointer 1
push that 0
push constant 45
eq
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 0
not
pop local 4
push constant 1
pop local 0
label IF_FALSE1
label WHILE_EXP0
push local 0
push this 2
lt
push local 3
and
not
if-goto WHILE_END0
push local 0
push this 1
add
pop pointer 1
push that 0
push constant 48
sub
pop local 2
push local 2
push constant 0
lt
push local 2
push constant 9
gt
or
not
pop local 3
push local 3
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 1
push constant 10
call Math.multiply 2
push local 2
add
pop local 1
push local 0
push constant 1
add
pop local 0
label IF_FALSE2
goto WHILE_EXP0
label WHILE_END0
push local 4
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push local 1
neg
pop local 1
label IF_FALSE3
push local 1
return
function String.setInt 4
push argument 0
pop pointer 0
push this 0
push constant 0
eq
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 19
call Sys.error 1
pop temp 0
label IF_FALSE0
push constant 6
call Array.new 1
pop local 2
push argument 1
push constant 0
lt
if-goto IF_TRUE1
goto IF_FALSE1
label IF_TRUE1
push constant 0
not
pop local 3
push argument 1
neg
pop argument 1
label IF_FALSE1
push argument 1
pop local 1
label WHILE_EXP0
push local 1
push constant 0
gt
not
if-goto WHILE_END0
push argument 1
push constant 10
call Math.divide 2
pop local 1
push local 0
push local 2
add
push constant 48
push argument 1
push local 1
push constant 10
call Math.multiply 2
sub
add
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
push local 1
pop argument 1
goto WHILE_EXP0
label WHILE_END0
push local 3
if-goto IF_TRUE2
goto IF_FALSE2
label IF_TRUE2
push local 0
push local 2
add
push constant 45
pop temp 0
pop pointer 1
push temp 0
pop that 0
push local 0
push constant 1
add
pop local 0
label IF_FALSE2
push this 0
push local 0
lt
if-goto IF_TRUE3
goto IF_FALSE3
label IF_TRUE3
push constant 19
call Sys.error 1
pop temp 0
label IF_FALSE3
push local 0
push constant 0
eq
if-goto IF_TRUE4
goto IF_FALSE4
label IF_TRUE4
push constant 0
push this 1
add
push constant 48
pop temp 0
pop pointer 1
push temp 0
pop that 0
push constant 1
pop this 2
goto IF_END4
label IF_FALSE4
push constant 0
pop this 2
label WHILE_EXP1
push this 2
push local 0
lt
not
if-goto WHILE_END1
push this 2
push this 1
add
push local 0
push this 2
push constant 1
add
sub
push local 2
add
pop pointer 1
push that 0
pop temp 0
pop pointer 1
push temp 0
pop that 0
push this 2
push constant 1
add
pop this 2
goto WHILE_EXP1
label WHILE_END1
label IF_END4
push local 2
call Array.dispose 1
pop temp 0
push constant 0
return
function String.newLine 0
push constant 128
return
function String.backSpace 0
push constant 129
return
function String.doubleQuote 0
push constant 34
return
+83
View File
@@ -0,0 +1,83 @@
function Sys.init 0
call Memory.init 0
pop temp 0
call Math.init 0
pop temp 0
call Screen.init 0
pop temp 0
call Output.init 0
pop temp 0
call Keyboard.init 0
pop temp 0
call Main.main 0
pop temp 0
call Sys.halt 0
pop temp 0
push constant 0
return
function Sys.halt 0
label WHILE_EXP0
push constant 0
not
not
if-goto WHILE_END0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Sys.wait 1
push argument 0
push constant 0
lt
if-goto IF_TRUE0
goto IF_FALSE0
label IF_TRUE0
push constant 1
call Sys.error 1
pop temp 0
label IF_FALSE0
label WHILE_EXP0
push argument 0
push constant 0
gt
not
if-goto WHILE_END0
push constant 50
pop local 0
label WHILE_EXP1
push local 0
push constant 0
gt
not
if-goto WHILE_END1
push local 0
push constant 1
sub
pop local 0
goto WHILE_EXP1
label WHILE_END1
push argument 0
push constant 1
sub
pop argument 0
goto WHILE_EXP0
label WHILE_END0
push constant 0
return
function Sys.error 0
push constant 69
call Output.printChar 1
pop temp 0
push constant 82
call Output.printChar 1
pop temp 0
push constant 82
call Output.printChar 1
pop temp 0
push argument 0
call Output.printInt 1
pop temp 0
call Sys.halt 0
pop temp 0
push constant 0
return
Binary file not shown.
Binary file not shown.
Binary file not shown.
+301
View File
@@ -0,0 +1,301 @@
// 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/12/Output.jack
/**
* A library of functions for writing text on the screen.
* The Hack physical screen consists of 512 rows of 256 pixels each.
* The library uses a fixed font, in which each character is displayed
* within a frame which is 11 pixels high (including 1 pixel for inter-line
* spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
* The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
* of 64 characters each (indexed 0..63, left to right). The top left
* character position on the screen is indexed (0,0). A cursor, implemented
* as a small filled square, indicates where the next character will be displayed.
*/
class Output {
// Character map for displaying characters
static Array charMaps;
static int address;
static bool half;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void init() {
do Output.initMap();
do Output.moveCursor(0, 0);
return;
}
// Initializes the character map array
function void initMap() {
var int i;
let charMaps = Array.new(127);
// Black square, used for displaying non-printable characters.
do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
// Assigns the bitmap for each character in the charachter set.
// The first parameter is the character index, the next 11 numbers
// are the values of each row in the frame that represents this character.
do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
do Output.create(65,12,30,51,51,63,51,51,51,51,0,0); // A ** TO BE FILLED **
do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
return;
}
// Creates the character map array of the given character index, using the given values.
function void create(int index, int a, int b, int c, int d, int e,
int f, int g, int h, int i, int j, int k) {
var Array map;
let map = Array.new(11);
let charMaps[index] = map;
let map[0] = a;
let map[1] = b;
let map[2] = c;
let map[3] = d;
let map[4] = e;
let map[5] = f;
let map[6] = g;
let map[7] = h;
let map[8] = i;
let map[9] = j;
let map[10] = k;
return;
}
// Returns the character map (array of size 11) of the given character.
// If the given character is invalid or non-printable, returns the
// character map of a black square.
function Array getMap(char c) {
if ((c < 32) | (c > 126)) {
let c = 0;
}
return charMaps[c];
}
/** Moves the cursor to the j-th column of the i-th row,
* and erases the character displayed there. */
function void moveCursor(int i, int j) {
var int count;
var int display;
var Array r;
var Array char;
if (j = 0){
let half = true;
}
else{
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
}
let address = (352 * i) + (j / 2) + 16384;
let char = Output.getMap(32);
while (count < 11){
if (half){
let display = r[address] & (-256);
let r[address] = char[count] | display;
}
else{
let display = r[address] & 255;
let r[address] = (char[count]*256) | display;
}
let count = count + 1;
let address = address + 32;
}
let address = address - 352;
return;
}
/** Displays the given character at the cursor location,
* and advances the cursor one column forward. */
function void printChar(char c) {
var Array char;
var Array r;
var int count;
var int display;
let char = Output.getMap(c);
while (count < 11){
if (half){
let display = r[address] & (-256);
let r[address] = char[count] | display;
}
else{
let display = r[address] & 255;
let r[address] = (char[count]*256) | display;
}
let count = count + 1;
let address = address + 32;
}
if (half){
let address = address - 352;
let half = false;
}
else{
if (address > 24480){
let address = 16384;
let half = true;
}
else{
let address = address - 351;
let half = true;
}
}
return;
}
/** displays the given string starting at the cursor location,
* and advances the cursor appropriately. */
function void printString(String s) {
var int i, length;
let length = s.length();
while (i < length){
do Output.printChar(s[i+2]);
let i = i + 1;
}
return;
}
/** Displays the given integer starting at the cursor location,
* and advances the cursor appropriately. */
function void printInt(int i) {
var String s;
let s = String.new(6);
do s.setInt(i);
do Output.printString(s);
return;
}
/** Advances the cursor to the beginning of the next line. */
function void println() {
var int row;
let row = (((address - 16384) / 32)/11) + 1;
if (row > 32){
let row = 0;
}
do Output.moveCursor(row, 0);
return;
}
/** Moves the cursor one column back. */
function void backSpace() {
if (address = 16384){
let address = 24191;
let half = true;
return;
}
if (half){
let address = address - 1;
let half = false;
}
else{
let half = true;
}
return;
}
}
+42
View File
@@ -0,0 +1,42 @@
// 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/12/OutputTest/Main.jack
/** Test program for the OS Output class. */
class Main {
/** Outputs the entire character set to the screen using all the
* methods of the Output class. */
function void main() {
var String s;
let s = String.new(1);
do s.appendChar(String.doubleQuote());
do Output.moveCursor(0, 63);
do Output.printChar(66);
do Output.moveCursor(22, 0);
do Output.printChar(67);
do Output.moveCursor(22, 63);
do Output.printChar(68);
do Output.printChar(65);
do Output.moveCursor(2, 0);
do Output.printString("0123456789");
do Output.println();
do Output.printString("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz");
do Output.println();
do Output.printString("!#$%&'()*+,-./:;<=>?@[\]^_`{|}~");
do Output.printString(s);
do Output.println();
do Output.printInt(-12345);
do Output.backSpace();
do Output.printInt(6789);
return;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+206
View File
@@ -0,0 +1,206 @@
// 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/12/Screen.jack
/**
* A library of functions for displaying graphics on the screen.
* The Hack physical screen consists of 256 rows (indexed 0..255, top to bottom)
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
* the screen is indexed (0,0).
*/
class Screen {
static Array mem;
static Array st;
static boolean color;
/** Initializes the Screen. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
let color = true;
return;
}
/** Erases the entire screen. */
function void clearScreen() {
var int a;
let a = 16384;
while (a < 24575){
let mem[a] = 0;
let a = a + 1;
}
return;
}
/** Sets the current color, to be used for all subsequent drawXXX commands.
* Black is represented by true, white by false. */
function void setColor(boolean b) {
let color = b;
return;
}
/** Draws the (x,y) pixel, using the current color. */
function void drawPixel(int x, int y) {
var int value, address, bit, mem_block;
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
do Sys.error(7);
}
let mem_block = x / 16;
let address = (32 * y) + mem_block + 16384;
let value = mem[address];
let bit = x - (mem_block * 16);
if (color){
let mem[address] = st[bit] | value;
}
else{
let mem[address] = (~st[bit])& value;
}
return;
}
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
function void drawLine(int x1, int y1, int x2, int y2) {
var int diff, dx, dy, a, b;
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let dx = x2 - x1;
let dy = y2 - y1;
if (dx = 0){
if (dy > 0){
while(~(b > dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b + 1;
}
return;
}
else{
while(~(b < dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b - 1;
}
return;
}
}
if (dy = 0){
if (dx > 0){
while(~(a > dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a + 1;
}
return;
}
else{
while(~(a < dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a - 1;
}
return;
}
}
if (dx < 0){
if (dy < 0){
while ((~(a < dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff + dx;
}
}
}
else{
while ((~(a < dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff + dx;
}
}
}
}
else{
if (dy < 0){
while ((~(a > dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff - dx;
}
}
}
else{
while ((~(a > dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff - dx;
}
}
}
}
return;
}
/** Draws a filled rectangle whose top left corner is (x1, y1)
* and bottom right corner is (x2,y2), using the current color. */
function void drawRectangle(int x1, int y1, int x2, int y2) {
var int a, tmp;
if (x1 > x2){
let tmp = x1;
let x1 = x2;
let x2 = tmp;
}
if (y1 > y2){
let tmp = y1;
let y1 = y2;
let y2 = tmp;
}
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let tmp = y2 - y1;
while(a < tmp){
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
let a = a + 1;
}
return;
}
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
function void drawCircle(int x, int y, int r) {
var int dy, dx, tmp;
if(r > 181){
do Sys.error(7);
}
let dy = - r;
while (dy < r){
let tmp = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
let dy = dy + 1;
}
return;
}
}
+36
View File
@@ -0,0 +1,36 @@
// 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/12/ScreenTest/Main.jack
/** Test program for the OS Screen class. */
class Main {
/** Draws a sample pictue on the screen using lines and circles. */
function void main() {
do Screen.drawLine(0,220,511,220); // base line
do Screen.drawRectangle(280,90,410,220); // house
do Screen.setColor(false);
do Screen.drawRectangle(350,120,390,219); // door
do Screen.drawRectangle(292,120,332,150); // window
do Screen.setColor(true);
do Screen.drawCircle(360,170,3); // door handle
do Screen.drawLine(280,90,345,35); // roof
do Screen.drawLine(345,35,410,90); // roof
do Screen.drawCircle(140,60,30); // sun
do Screen.drawLine(140,26, 140, 6);
do Screen.drawLine(163,35,178,20);
do Screen.drawLine(174,60,194,60);
do Screen.drawLine(163,85,178,100);
do Screen.drawLine(140,94,140,114);
do Screen.drawLine(117,85,102,100);
do Screen.drawLine(106,60,86,60);
do Screen.drawLine(117,35,102,20);
return;
}
}
+104
View File
@@ -0,0 +1,104 @@
function Main.main 0
push constant 0
push constant 220
push constant 511
push constant 220
call Screen.drawLine 4
pop temp 0
push constant 280
push constant 90
push constant 410
push constant 220
call Screen.drawRectangle 4
pop temp 0
push constant 0
call Screen.setColor 1
pop temp 0
push constant 350
push constant 120
push constant 390
push constant 219
call Screen.drawRectangle 4
pop temp 0
push constant 292
push constant 120
push constant 332
push constant 150
call Screen.drawRectangle 4
pop temp 0
push constant 1
neg
call Screen.setColor 1
pop temp 0
push constant 360
push constant 170
push constant 3
call Screen.drawCircle 3
pop temp 0
push constant 280
push constant 90
push constant 345
push constant 35
call Screen.drawLine 4
pop temp 0
push constant 345
push constant 35
push constant 410
push constant 90
call Screen.drawLine 4
pop temp 0
push constant 140
push constant 60
push constant 30
call Screen.drawCircle 3
pop temp 0
push constant 140
push constant 26
push constant 140
push constant 6
call Screen.drawLine 4
pop temp 0
push constant 163
push constant 35
push constant 178
push constant 20
call Screen.drawLine 4
pop temp 0
push constant 174
push constant 60
push constant 194
push constant 60
call Screen.drawLine 4
pop temp 0
push constant 163
push constant 85
push constant 178
push constant 100
call Screen.drawLine 4
pop temp 0
push constant 140
push constant 94
push constant 140
push constant 114
call Screen.drawLine 4
pop temp 0
push constant 117
push constant 85
push constant 102
push constant 100
call Screen.drawLine 4
pop temp 0
push constant 106
push constant 60
push constant 86
push constant 60
call Screen.drawLine 4
pop temp 0
push constant 117
push constant 35
push constant 102
push constant 20
call Screen.drawLine 4
pop temp 0
push constant 0
return
+206
View File
@@ -0,0 +1,206 @@
// 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/12/Screen.jack
/**
* A library of functions for displaying graphics on the screen.
* The Hack physical screen consists of 256 rows (indexed 0..255, top to bottom)
* of 512 pixels each (indexed 0..511, left to right). The top left pixel on
* the screen is indexed (0,0).
*/
class Screen {
static Array mem;
static Array st;
static boolean color;
/** Initializes the Screen. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
let color = true;
return;
}
/** Erases the entire screen. */
function void clearScreen() {
var int a;
let a = 16384;
while (a < 24575){
let mem[a] = 0;
let a = a + 1;
}
return;
}
/** Sets the current color, to be used for all subsequent drawXXX commands.
* Black is represented by true, white by false. */
function void setColor(boolean b) {
let color = b;
return;
}
/** Draws the (x,y) pixel, using the current color. */
function void drawPixel(int x, int y) {
var int value, address, bit, mem_block;
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
do Sys.error(7);
}
let mem_block = x / 16;
let address = (32 * y) + mem_block + 16384;
let value = mem[address];
let bit = x - (mem_block * 16);
if (color){
let mem[address] = st[bit] | value;
}
else{
let mem[address] = (~st[bit])& value;
}
return;
}
/** Draws a line from pixel (x1,y1) to pixel (x2,y2), using the current color. */
function void drawLine(int x1, int y1, int x2, int y2) {
var int diff, dx, dy, a, b;
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let dx = x2 - x1;
let dy = y2 - y1;
if (dx = 0){
if (dy > 0){
while(~(b > dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b + 1;
}
return;
}
else{
while(~(b < dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b - 1;
}
return;
}
}
if (dy = 0){
if (dx > 0){
while(~(a > dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a + 1;
}
return;
}
else{
while(~(a < dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a - 1;
}
return;
}
}
if (dx < 0){
if (dy < 0){
while ((~(a < dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff + dx;
}
}
}
else{
while ((~(a < dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a - 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff + dx;
}
}
}
}
else{
if (dy < 0){
while ((~(a > dx)) & (~(b < dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff - dy;
}
else{
let b = b - 1;
let diff = diff - dx;
}
}
}
else{
while ((~(a > dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff - dx;
}
}
}
}
return;
}
/** Draws a filled rectangle whose top left corner is (x1, y1)
* and bottom right corner is (x2,y2), using the current color. */
function void drawRectangle(int x1, int y1, int x2, int y2) {
var int a, tmp;
if (x1 > x2){
let tmp = x1;
let x1 = x2;
let x2 = tmp;
}
if (y1 > y2){
let tmp = y1;
let y1 = y2;
let y2 = tmp;
}
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let tmp = y2 - y1;
while(a < tmp){
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
let a = a + 1;
}
return;
}
/** Draws a filled circle of radius r<=181 around (x,y), using the current color. */
function void drawCircle(int x, int y, int r) {
var int dy, dx, tmp;
if(r > 181){
do Sys.error(7);
}
let dy = - r;
while (dy < r){
let tmp = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
let dy = dy + 1;
}
return;
}
}
+656
View File
@@ -0,0 +1,656 @@
function Screen.init 1
push constant 16
call Array.new 1
pop static 1
push static 1
push constant 0
push constant 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
label L0
push local 0
push constant 15
lt
not
if-goto L1
push local 0
push constant 1
add
pop local 0
push static 1
push local 0
push static 1
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
push static 1
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
add
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
goto L0
label L1
push constant 1
neg
pop static 2
push constant 0
return
function Screen.clearScreen 1
push constant 16384
pop local 0
label L2
push local 0
push constant 24575
lt
not
if-goto L3
push static 0
push local 0
push constant 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 1
add
pop local 0
goto L2
label L3
push constant 0
return
function Screen.setColor 0
push argument 0
pop static 2
push constant 0
return
function Screen.drawPixel 4
push argument 0
push constant 511
gt
push argument 0
push constant 0
lt
or
push argument 1
push constant 255
gt
or
push argument 1
push constant 0
lt
or
not
if-goto L4
push constant 7
call Sys.error 1
pop temp 0
goto L5
label L4
label L5
push argument 0
push constant 16
call Math.divide 2
pop local 3
push constant 32
push argument 1
call Math.multiply 2
push local 3
add
push constant 16384
add
pop local 1
push static 0
push local 1
add
pop pointer 1
push that 0
pop local 0
push argument 0
push local 3
push constant 16
call Math.multiply 2
sub
pop local 2
push static 2
not
if-goto L6
push static 0
push local 1
push static 1
push local 2
add
pop pointer 1
push that 0
push local 0
or
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
goto L7
label L6
push static 0
push local 1
push static 1
push local 2
add
pop pointer 1
push that 0
not
push local 0
and
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
label L7
push constant 0
return
function Screen.drawLine 5
push argument 0
push constant 0
lt
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
not
if-goto L8
push constant 8
call Sys.error 1
pop temp 0
goto L9
label L8
label L9
push argument 2
push argument 0
sub
pop local 1
push argument 3
push argument 1
sub
pop local 2
push local 1
push constant 0
eq
not
if-goto L10
push local 2
push constant 0
gt
not
if-goto L11
label L12
push local 4
push local 2
gt
not
not
if-goto L13
push argument 0
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 4
push constant 1
add
pop local 4
goto L12
label L13
push constant 0
return
goto L14
label L11
label L15
push local 4
push local 2
lt
not
not
if-goto L16
push argument 0
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 4
push constant 1
sub
pop local 4
goto L15
label L16
push constant 0
return
label L14
goto L17
label L10
label L17
push local 2
push constant 0
eq
not
if-goto L18
push local 1
push constant 0
gt
not
if-goto L19
label L20
push local 3
push local 1
gt
not
not
if-goto L21
push argument 0
push local 3
add
push argument 1
call Screen.drawPixel 2
pop temp 0
push local 3
push constant 1
add
pop local 3
goto L20
label L21
push constant 0
return
goto L22
label L19
label L23
push local 3
push local 1
lt
not
not
if-goto L24
push argument 0
push local 3
add
push argument 1
call Screen.drawPixel 2
pop temp 0
push local 3
push constant 1
sub
pop local 3
goto L23
label L24
push constant 0
return
label L22
goto L25
label L18
label L25
push local 1
push constant 0
lt
not
if-goto L26
push local 2
push constant 0
lt
not
if-goto L27
label L28
push local 3
push local 1
lt
not
push local 4
push local 2
lt
not
and
not
if-goto L29
push argument 0
push local 3
add
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 0
push constant 0
lt
not
if-goto L30
push local 3
push constant 1
sub
pop local 3
push local 0
push local 2
sub
pop local 0
goto L31
label L30
push local 4
push constant 1
sub
pop local 4
push local 0
push local 1
add
pop local 0
label L31
goto L28
label L29
goto L32
label L27
label L33
push local 3
push local 1
lt
not
push local 4
push local 2
gt
not
and
not
if-goto L34
push argument 0
push local 3
add
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 0
push constant 0
lt
not
if-goto L35
push local 3
push constant 1
sub
pop local 3
push local 0
push local 2
add
pop local 0
goto L36
label L35
push local 4
push constant 1
add
pop local 4
push local 0
push local 1
add
pop local 0
label L36
goto L33
label L34
label L32
goto L37
label L26
push local 2
push constant 0
lt
not
if-goto L38
label L39
push local 3
push local 1
gt
not
push local 4
push local 2
lt
not
and
not
if-goto L40
push argument 0
push local 3
add
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 0
push constant 0
lt
not
if-goto L41
push local 3
push constant 1
add
pop local 3
push local 0
push local 2
sub
pop local 0
goto L42
label L41
push local 4
push constant 1
sub
pop local 4
push local 0
push local 1
sub
pop local 0
label L42
goto L39
label L40
goto L43
label L38
label L44
push local 3
push local 1
gt
not
push local 4
push local 2
gt
not
and
not
if-goto L45
push argument 0
push local 3
add
push argument 1
push local 4
add
call Screen.drawPixel 2
pop temp 0
push local 0
push constant 0
lt
not
if-goto L46
push local 3
push constant 1
add
pop local 3
push local 0
push local 2
add
pop local 0
goto L47
label L46
push local 4
push constant 1
add
pop local 4
push local 0
push local 1
sub
pop local 0
label L47
goto L44
label L45
label L43
label L37
push constant 0
return
function Screen.drawRectangle 2
push argument 0
push argument 2
gt
not
if-goto L48
push argument 0
pop local 1
push argument 2
pop argument 0
push local 1
pop argument 2
goto L49
label L48
label L49
push argument 1
push argument 3
gt
not
if-goto L50
push argument 1
pop local 1
push argument 3
pop argument 1
push local 1
pop argument 3
goto L51
label L50
label L51
push argument 0
push constant 0
lt
push argument 2
push constant 511
gt
or
push argument 1
push constant 0
lt
or
push argument 3
push constant 255
gt
or
not
if-goto L52
push constant 8
call Sys.error 1
pop temp 0
goto L53
label L52
label L53
push argument 3
push argument 1
sub
pop local 1
label L54
push local 0
push local 1
lt
not
if-goto L55
push argument 0
push argument 1
push local 0
add
push argument 2
push argument 1
push local 0
add
call Screen.drawLine 4
pop temp 0
push local 0
push constant 1
add
pop local 0
goto L54
label L55
push constant 0
return
function Screen.drawCircle 3
push argument 2
push constant 181
gt
not
if-goto L56
push constant 7
call Sys.error 1
pop temp 0
goto L57
label L56
label L57
push argument 2
neg
pop local 0
label L58
push local 0
push argument 2
lt
not
if-goto L59
push argument 2
push argument 2
call Math.multiply 2
push local 0
push local 0
call Math.multiply 2
sub
call Math.sqrt 1
pop local 2
push argument 0
push local 2
sub
push argument 1
push local 0
add
push argument 0
push local 2
add
push argument 1
push local 0
add
call Screen.drawLine 4
pop temp 0
push local 0
push constant 1
add
pop local 0
goto L58
label L59
push constant 0
return
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

+148
View File
@@ -0,0 +1,148 @@
// 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/12/String.jack
/**
* Represents character strings. In addition for constructing and disposing
* strings, the class features methods for getting and setting individual
* characters of the string, for erasing the string's last character,
* for appending a character to the string's end, and more typical
* string-oriented operations.
*/
class String {
field Array str;
field int length;
static bool neg;
/** constructs a new empty string with a maximum length of maxLength
* and initial length of 0. */
constructor String new(int maxLength) {
if (maxLength > 0){
let str = Array.new(maxLength);
}
let length = 0;
return this;
}
/** Disposes this string. */
method void dispose() {
if(length > 0){
do str.dispose();
}
do Memory.deAlloc(this);
return;
}
/** Returns the current length of this string. */
method int length() {
return length;
}
/** Returns the character at the j-th location of this string. */
method char charAt(int j) {
if(j > length){
do Sys.error(7);
}
return str[j];
}
/** Sets the character at the j-th location of this string to c. */
method void setCharAt(int j, char c) {
if(j > length){
do Sys.error(7);
}
let str[j] = c;
return;
}
/** Appends c to this string's end and returns this string. */
method String appendChar(char c) {
let str[length] = c;
let length = length + 1;
return this;
}
/** Erases the last character from this string. */
method void eraseLastChar() {
let str[length] = 0;
let length = length - 1;
return;
}
/** Returns the integer value of this string,
* until a non-digit character is detected. */
method int intValue() {
var int d, sum, i;
var bool f;
while(i < length){
let d = str[i]; // kak da go zavyrtq v realen int
if ((d > 47) & (d < 58)){
let sum = (sum * 10) + (d - 48);
}
else{
if((i = 0) & (d = 45)){
let f = true;
}
else{
let i = length;
}
}
let i = i + 1;
}
if (f){
return -sum;
}
return sum;
}
/** Sets this string to hold a representation of the given value. */
method void setInt(int val) {
var int lastDigit, a, i;
var char c;
if(val < 0){
let neg = true;
let val = -val;
}
let a = val / 10;
let lastDigit = val - (a * 10);
let i = 48;
while (i < 58){
if (i = (48 + lastDigit)){
let c = i;
let i = 59;
}
let i = i + 1;
}
if (val < 10){
let length = 0;
if (neg){
let neg = false;
do this.appendChar("-");
}
do this.appendChar(c);
return;
}
else{
do this.setInt(a);
do this.appendChar(c);
}
return;
}
/** Returns the new line character. */
function char newLine() {
return 128;
}
/** Returns the backspace character. */
function char backSpace() {
return 129;
}
/** Returns the double quote (") character. */
function char doubleQuote() {
return 34;
}
}
+350
View File
@@ -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()
+83
View File
@@ -0,0 +1,83 @@
// 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/12/StringTest/Main.jack
/** Test program for the OS String class. */
class Main {
/** Performs various string manipulations and displays their results. */
function void main() {
var String s;
var String i;
let s = String.new(0); // a zero-capacity string should be supported
do s.dispose();
let s = String.new(6); // capacity 6, make sure that length 5 is displayed
let s = s.appendChar(97);
let s = s.appendChar(98);
let s = s.appendChar(99);
let s = s.appendChar(100);
let s = s.appendChar(101);
do Output.printString("new: ");
do Output.printString(s); // new, appendChar: abcde
do Output.println();
let i = String.new(6);
do i.setInt(12345);
do Output.printString("setInt: ");
do Output.printString(i); // setInt: 12345
do Output.println();
do i.setInt(-32767);
do Output.printString("setInt: ");
do Output.printString(i); // setInt: -32767
do Output.println();
do Output.printString("length: ");
do Output.printInt(s.length()); // length: 5
do Output.println();
do Output.printString("charAt[2]: ");
do Output.printInt(s.charAt(2)); // charAt[2]: 99
do Output.println();
do s.setCharAt(2, 45);
do Output.printString("setCharAt(2,'-'): ");
do Output.printString(s); // setCharAt(2,'-'): ab-de
do Output.println();
do s.eraseLastChar();
do Output.printString("eraseLastChar: ");
do Output.printString(s); // eraseLastChar: ab-d
do Output.println();
let s = "456";
do Output.printString("intValue: ");
do Output.printInt(s.intValue()); // intValue: 456
do Output.println();
let s = "-32123";
do Output.printString("intValue: ");
do Output.printInt(s.intValue()); // intValue: -32123
do Output.println();
do Output.printString("backSpace: ");
do Output.printInt(String.backSpace()); // backSpace: 129
do Output.println();
do Output.printString("doubleQuote: ");
do Output.printInt(String.doubleQuote());// doubleQuote: 34
do Output.println();
do Output.printString("newLine: ");
do Output.printInt(String.newLine()); // newLine: 128
do Output.println();
do i.dispose();
do s.dispose();
return;
}
}
+447
View File
@@ -0,0 +1,447 @@
function Main.main 2
push constant 0
call String.new 1
pop local 0
push local 0
call String.dispose 1
pop temp 0
push constant 6
call String.new 1
pop local 0
push local 0
push constant 97
call String.appendChar 2
pop local 0
push local 0
push constant 98
call String.appendChar 2
pop local 0
push local 0
push constant 99
call String.appendChar 2
pop local 0
push local 0
push constant 100
call String.appendChar 2
pop local 0
push local 0
push constant 101
call String.appendChar 2
pop local 0
push constant 5
call String.new 1
push constant 110
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 119
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 6
call String.new 1
pop local 1
push local 1
push constant 12345
call String.setInt 2
pop temp 0
push constant 8
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 73
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push local 1
push constant 32767
neg
call String.setInt 2
pop temp 0
push constant 8
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 73
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 8
call String.new 1
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 103
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 104
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
call String.length 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 11
call String.new 1
push constant 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 91
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 93
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 2
call String.charAt 2
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push local 0
push constant 2
push constant 45
call String.setCharAt 3
pop temp 0
push constant 18
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 40
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 44
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 45
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 41
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push local 0
call String.eraseLastChar 1
pop temp 0
push constant 15
call String.new 1
push constant 101
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 76
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
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 Output.printString 1
pop temp 0
push local 0
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 3
call String.new 1
push constant 52
call String.appendChar 2
push constant 53
call String.appendChar 2
push constant 54
call String.appendChar 2
pop local 0
push constant 10
call String.new 1
push constant 105
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 117
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
call Output.printString 1
pop temp 0
push local 0
call String.intValue 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 6
call String.new 1
push constant 45
call String.appendChar 2
push constant 51
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 49
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 51
call String.appendChar 2
pop local 0
push constant 10
call String.new 1
push constant 105
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 117
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
call Output.printString 1
pop temp 0
push local 0
call String.intValue 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 11
call String.new 1
push constant 98
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 83
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
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
call Output.printString 1
pop temp 0
call String.backSpace 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 13
call String.new 1
push constant 100
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 98
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 81
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 116
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
call Output.printString 1
pop temp 0
call String.doubleQuote 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 9
call String.new 1
push constant 110
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 119
call String.appendChar 2
push constant 76
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call String.newLine 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push local 1
call String.dispose 1
pop temp 0
push local 0
call String.dispose 1
pop temp 0
push constant 0
return
+147
View File
@@ -0,0 +1,147 @@
// 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/12/String.jack
/**
* Represents character strings. In addition for constructing and disposing
* strings, the class features methods for getting and setting individual
* characters of the string, for erasing the string's last character,
* for appending a character to the string's end, and more typical
* string-oriented operations.
*/
class String {
field Array str;
field int length;
static bool neg;
/** constructs a new empty string with a maximum length of maxLength
* and initial length of 0. */
constructor String new(int maxLength) {
if (maxLength > 0){
let str = Array.new(maxLength);
}
let length = 0;
return this;
}
/** Disposes this string. */
method void dispose() {
if(length > 0){
do str.dispose();
}
do Memory.deAlloc(this);
return;
}
/** Returns the current length of this string. */
method int length() {
return length;
}
/** Returns the character at the j-th location of this string. */
method char charAt(int j) {
if(j > length){
do Sys.error(7);
}
return str[j];
}
/** Sets the character at the j-th location of this string to c. */
method void setCharAt(int j, char c) {
if(j > length){
do Sys.error(7);
}
let str[j] = c;
return;
}
/** Appends c to this string's end and returns this string. */
method String appendChar(char c) {
let str[length] = c;
let length = length + 1;
return this;
}
/** Erases the last character from this string. */
method void eraseLastChar() {
let str[length] = 0;
let length = length - 1;
return;
}
/** Returns the integer value of this string,
* until a non-digit character is detected. */
method int intValue() {
var int d, sum, i;
var bool f;
while(i < length){
let d = str[i]; // kak da go zavyrtq v realen int
if ((d > 47) & (d < 58)){
let sum = (sum * 10) + (d - 48);
}
else{
if((i = 0) & (d = 45)){
let f = true;
}
else{
let i = length;
}
}
let i = i + 1;
}
if (f){
return -sum;
}
return sum;
}
/** Sets this string to hold a representation of the given value. */
method void setInt(int val) {
var int lastDigit, a, i;
var char c;
if(val < 0){
let neg = true;
let val = -val;
}
let a = val / 10;
let lastDigit = val - (a * 10);
let i = 48;
while (i < 58){
if (i = (48 + lastDigit)){
let c = i;
let i = 59;
}
let i = i + 1;
}
if (val < 10){
let length = 0;
if (neg){
let neg = false;
do this.appendChar("-");
}
do this.appendChar(c);
return;
}
else{
do this.setInt(a);
do this.appendChar(c);
}
return;
}
/** Returns the new line character. */
function char newLine() {
return 128;
}
/** Returns the backspace character. */
function char backSpace() {
return 129;
}
/** Returns the double quote (") character. */
function char doubleQuote() {
return 34;
}
}
+295
View File
@@ -0,0 +1,295 @@
function String.new 0
push constant 2
call Memory.alloc 1
pop pointer 0
push argument 0
push constant 0
gt
not
if-goto L0
push argument 0
call Array.new 1
pop this 0
goto L1
label L0
label L1
push constant 0
pop this 1
push pointer 0
return
function String.dispose 0
push argument 0
pop pointer 0
push this 1
push constant 0
gt
not
if-goto L2
push this 0
call Array.dispose 1
pop temp 0
goto L3
label L2
label L3
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
function String.length 0
push argument 0
pop pointer 0
push this 1
return
function String.charAt 0
push argument 0
pop pointer 0
push argument 1
push this 1
gt
not
if-goto L4
push constant 7
call Sys.error 1
pop temp 0
goto L5
label L4
label L5
push this 0
push argument 1
add
pop pointer 1
push that 0
return
function String.setCharAt 0
push argument 0
pop pointer 0
push argument 1
push this 1
gt
not
if-goto L6
push constant 7
call Sys.error 1
pop temp 0
goto L7
label L6
label L7
push this 0
push argument 1
push argument 2
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function String.appendChar 0
push argument 0
pop pointer 0
push this 0
push this 1
push argument 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push this 1
push constant 1
add
pop this 1
push pointer 0
return
function String.eraseLastChar 0
push argument 0
pop pointer 0
push this 0
push this 1
push constant 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push this 1
push constant 1
sub
pop this 1
push constant 0
return
function String.intValue 4
push argument 0
pop pointer 0
label L8
push local 2
push this 1
lt
not
if-goto L9
push this 0
push local 2
add
pop pointer 1
push that 0
pop local 0
push local 0
push constant 47
gt
push local 0
push constant 58
lt
and
not
if-goto L10
push local 1
push constant 10
call Math.multiply 2
push local 0
push constant 48
sub
add
pop local 1
goto L11
label L10
push local 2
push constant 0
eq
push local 0
push constant 45
eq
and
not
if-goto L12
push constant 1
neg
pop local 3
goto L13
label L12
push this 1
pop local 2
label L13
label L11
push local 2
push constant 1
add
pop local 2
goto L8
label L9
push local 3
not
if-goto L14
push local 1
neg
return
goto L15
label L14
label L15
push local 1
return
function String.setInt 4
push argument 0
pop pointer 0
push argument 1
push constant 0
lt
not
if-goto L16
push constant 1
neg
pop static 0
push argument 1
neg
pop argument 1
goto L17
label L16
label L17
push argument 1
push constant 10
call Math.divide 2
pop local 1
push argument 1
push local 1
push constant 10
call Math.multiply 2
sub
pop local 0
push constant 48
pop local 2
label L18
push local 2
push constant 58
lt
not
if-goto L19
push local 2
push constant 48
push local 0
add
eq
not
if-goto L20
push local 2
pop local 3
push constant 59
pop local 2
goto L21
label L20
label L21
push local 2
push constant 1
add
pop local 2
goto L18
label L19
push argument 1
push constant 10
lt
not
if-goto L22
push constant 0
pop this 1
push static 0
not
if-goto L23
push constant 0
pop static 0
push argument 0
push constant 1
call String.new 1
push constant 45
call String.appendChar 2
call String.appendChar 2
pop temp 0
goto L24
label L23
label L24
push argument 0
push local 3
call String.appendChar 2
pop temp 0
push constant 0
return
goto L25
label L22
push argument 0
push local 1
call String.setInt 2
pop temp 0
push argument 0
push local 3
call String.appendChar 2
pop temp 0
label L25
push constant 0
return
function String.newLine 0
push constant 128
return
function String.backSpace 0
push constant 129
return
function String.doubleQuote 0
push constant 34
return
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+62
View File
@@ -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
+78
View File
@@ -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
+75
View File
@@ -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()
+53
View File
@@ -0,0 +1,53 @@
// 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/12/Sys.jack
/**
* A library that supports various program execution services.
*/
class Sys {
/** Performs all the initializations required by the OS. */
function void init() {
do Memory.init();
do Math.init();
do Output.init();
do Screen.init();
do Keyboard.init();
do Main.main();
do Sys.halt();
return;
}
/** Halts the program execution. */
function void halt() {
while(true){
}
return;
}
/** Waits approximately duration milliseconds and returns. */
function void wait(int duration) {
var int i;
while (duration > 0){
let i = 100;
while(i > 0){
let i = i -1;
}
let duration = duration - 1;
}
return;
}
/** Displays the given error code in the form "ERR<errorCode>",
* and halts the program's execution. */
function void error(int errorCode) {
var String s;
let s = String.new(3);
do s.setInt(errorCode);
do Output.printString("ERR");
do Output.printString(s);
return;
}
}
+31
View File
@@ -0,0 +1,31 @@
// 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/12/SysTest/Main.jack
/** Test program for the OS Sys class. */
class Main {
/** Tests the wait method of the Sys class. */
function void main() {
var char key;
do Output.printString("Wait test:");
do Output.println();
do Output.printString("Press any key. After 2 seconds, another message will be printed:");
while (key = 0) {
let key = Keyboard.keyPressed();
}
while (~(key = 0)) {
let key = Keyboard.keyPressed();
}
do Sys.wait(2000);
do Output.println();
do Output.printString("Time is up. Make sure that 2 seconds elapsed.");
return;
}
}
+281
View File
@@ -0,0 +1,281 @@
function Main.main 1
push constant 10
call String.new 1
push constant 87
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
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 58
call String.appendChar 2
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 64
call String.new 1
push constant 80
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 115
call String.appendChar 2
push constant 32
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 107
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 121
call String.appendChar 2
push constant 46
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 102
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 50
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 44
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 104
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 109
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 115
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 119
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 98
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 105
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 100
call String.appendChar 2
push constant 58
call String.appendChar 2
call Output.printString 1
pop temp 0
label L0
push local 0
push constant 0
eq
not
if-goto L1
call Keyboard.keyPressed 0
pop local 0
goto L0
label L1
label L2
push local 0
push constant 0
eq
not
not
if-goto L3
call Keyboard.keyPressed 0
pop local 0
goto L2
label L3
push constant 2000
call Sys.wait 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 105
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 105
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 46
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 77
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
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 32
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 32
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 100
call String.appendChar 2
push constant 46
call String.appendChar 2
call Output.printString 1
pop temp 0
push constant 0
return
+51
View File
@@ -0,0 +1,51 @@
// 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/12/Sys.jack
/**
* A library that supports various program execution services.
*/
class Sys {
/** Performs all the initializations required by the OS. */
function void init() {
do Math.init();
do Keyboard.init();
do Memory.init();
do Output.init();
do Screen.init();
do Main.main();
do Sys.halt();
}
/** Halts the program execution. */
function void halt() {
while(true){
}
}
/** Waits approximately duration milliseconds and returns. */
function void wait(int duration) {
var int i;
while (duration > 0){
let i = 100;
while(i > 0){
let i = i -1;
}
let duration = duration - 1;
}
return;
}
/** Displays the given error code in the form "ERR<errorCode>",
* and halts the program's execution. */
function void error(int errorCode) {
var String s;
let s = String.new(3);
do s.setInt(errorCode);
do Output.printString("ERR");
do Output.printString(s);
return;
}
}
+75
View File
@@ -0,0 +1,75 @@
function Sys.init 0
call Math.init 0
pop temp 0
call Keyboard.init 0
pop temp 0
call Memory.init 0
pop temp 0
call Output.init 0
pop temp 0
call Screen.init 0
pop temp 0
call Main.main 0
pop temp 0
call Sys.halt 0
pop temp 0
function Sys.halt 0
label L0
push constant 1
neg
not
if-goto L1
goto L0
label L1
function Sys.wait 1
label L2
push argument 0
push constant 0
gt
not
if-goto L3
push constant 100
pop local 0
label L4
push local 0
push constant 0
gt
not
if-goto L5
push local 0
push constant 1
sub
pop local 0
goto L4
label L5
push argument 0
push constant 1
sub
pop argument 0
goto L2
label L3
push constant 0
return
function Sys.error 1
push constant 3
call String.new 1
pop local 0
push local 0
push argument 0
call String.setInt 2
pop temp 0
push constant 3
call String.new 1
push constant 69
call String.appendChar 2
push constant 82
call String.appendChar 2
push constant 82
call String.appendChar 2
call Output.printString 1
pop temp 0
push local 0
call Output.printString 1
pop temp 0
push constant 0
return
+132
View File
@@ -0,0 +1,132 @@
class Main{
static Array mem;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void test_init() {
let mem = 0;
return;
}
function void main(){
var String s;
var int i;
let s = String.new(10);
do Main.test_init();
let s = Main.readLine("String: ");
let i = Main.readInt("INT: ");
do Output.printString(s);
do Output.printInt(i);
return;
}
function char keyPressed(){
return mem[24576];
}
function int readInt_stolen(String message){
var starting a;
var int b;
let a = Main.readLine_stolen(message);
let b = String.intValue(a);
do String.dispose(a);
return b;
}
function string readLine_stolen(String message){
var char a, b ,c;
var String d;
var bool e;
let d = String.new(80);
do Output.printString(message);
let b = String.newLine();
let c = String.backSpace();
while (~e){
let a = Main.readChar();
let e = a = b;
if (~e){
if (a = c){
do d.eraseLastChar();
}
else{
do d.appendChar(a);
}
}
}
return d;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its value. Also handles user backspaces.
*/
function String readLine(String message){
var String s, b;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Main.readChar();
if (c = 128){
return s;
}
else{
if (c = 129){
do s.eraseLastChar();
}
else{
do s.appendChar(c);
}
}
}
}
/**
* Waits until a key is pressed on the keyboard and released,
* then echoes the key to the screen, and returns the character
* of the pressed key.
*/
function char readChar(){
var char a, b;
do Output.printChar(0);
while ((b = 0) | (a > 0)){
let a = Main.keyPressed();
if (a > 0){
let b = a;
}
}
do Output.printChar(String.backSpace());
do Output.printChar(b);
return b;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its integer value (until the first non-digit character in the
* entered text is detected). Also handles user backspaces.
*/
function int readInt(String message) {
var String s;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Main.readChar(c);
if (c = 128){
return s.intValue();
}
else{
if (c = 129){
let s = s.eraseLastChar();
}
else{
if ((c > 47) & (c < 57)){
let s = s.appendChar(c);
}
}
}
}
}
}
+341
View File
@@ -0,0 +1,341 @@
class Main {
static int division_tmp;
static Array mem;
static Array st;
static int f;
static boolean color;
/** Initializes the library. */
function void init_test() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
let color = 1;
return;
}
function void main(){
do Main.init_test();
do Main.test_drawPixel(256,128);
do Main.test_drawPixel(255,128);
do Main.test_drawPixel(257,128);
do Main.test_changeColor(0);
do Main.test_drawPixel(256,128);
return;
}
function void test_changeColor(boolean x){
let color = x;
return;
}
function void test_clearScreen(){
var int a;
let a = 16384;
while (a < 24575){
let mem[a] = 0;
let a = a + 1;
}
return;
}
function void test_drawRectangle(int x1, int y1, int x2, int y2){
var int a, tmp;
if (x1 > x2){
let tmp = x1;
let x1 = x2;
let x2 = tmp;
}
if (y1 > y2){
let tmp = y1;
let y1 = y2;
let y2 = tmp;
}
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
while(a < y2){
do Screen.drawLine(x1, y1 + a, x2, y1 + a);
let a = a + 1;
}
return;
}
function void test_drawCicle(int x, int y, int r){
var int dy, dx, tmp;
if(r > 181){
do Sys.error(7);
}
let dy = - r;
while (dy < r){
let tmp = Math.sqrt((r * r) - (dy * dy));
do Screen.drawLine(x - tmp, y + dy, x + tmp, y + dy);
let dy = dy + 1;
}
return;
}
function void test_drawLine_optimize(int x1, int y1, int x2, int y2){
var int diff, dx, dy, a, b, tmp;
if (x1 > x2){
let tmp = x1;
let x1 = x2;
let x2 = tmp;
}
if (y1 > y2){
let tmp = y1;
let y1 = y2;
let y2 = tmp;
}
if((x1 < 0) | (x2 > 511) | (y1 < 0) | (y2 > 255)){
do Sys.error(8);
}
let dx = x2 - x1;
let dy = y2 - y1;
if (dx = 0){
while(~(b > dy)){
do Screen.drawPixel(x1, y1 + b);
let b = b + 1;
}
return;
}
if (dy = 0){
while(~(a > dx)){
do Screen.drawPixel(x1 + a, y1);
let a = a + 1;
}
return;
}
while ((~(a > dx)) & (~(b > dy))){
do Screen.drawPixel(x1 + a, y1 + b);
if (diff < 0){
let a = a + 1;
let diff = diff + dy;
}
else{
let b = b + 1;
let diff = diff - dx;
}
}
return;
}
function void test_drawPixel(int x, int y) {
var int value, address, bit, mem_block;
if ((x > 511) | (x < 0) | (y > 255) | (y < 0)){
do Sys.error(7);
}
let mem_block = x / 16;
let address = (32 * y) + mem_block + 16384;
let value = mem[address];
let bit = x - (mem_block * 16);
if (color = 1){
let mem[address] = st[bit] | value;
}
else{
let mem[address] = (~st[bit])& value;
}
return;
}
function int test_multiply(int x, int y){
var int sum, temp, y_comp, i, neg;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (x < y){
let temp = x;
let x = y;
let y = temp;
}
if (y = 1){
if(neg){
return -x;
}
return x;
}
while((y_comp - 1) < (y - 1)){
if ((st[i] & y) > 0) {
let sum = sum + x;
let y_comp = y_comp + st[i];
}
let x = x + x;
let i = i + 1;
}
if(neg){
let sum = -sum;
}
return sum;
}
function int test_max(int x, int y){
if (x > y){
return x;
}
return y;
}
function int test_min(int x, int y){
if (x < y){
return x;
}
return y;
}
function int test_sqrt(int x) {
var int j, b, d, y;
if (x < 0){
do Sys.error(4);
}
let j = 7;
while (j > -1){
let d = y + st[j];
let b = Main.test_multiply(d,d);
if ((~(b > x)) & (b > 0)){
let y = d;
}
let j = j - 1;
}
return y;
}
function int test_divide(int x, int y) {
var int q, neg;
if (f = 0){
let division_tmp = 0;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (y = 0){
do Sys.error(3);
}
let f = 1;
}
if ((y > x) | (y < 0)){
return 0;
}
let q = test_divide(x, y + y);
let f = 0;
let q = Math.abs(q);
if ((q & 1) = 1){
let division_tmp = division_tmp + y + y;
}
if (x - division_tmp < y){
if (neg){
return -(q + q);
}
return q + q;
}
else{
if (neg){
return -(q + q + 1);
}
return q + q + 1;
}
}
function int test_abs(int x) {
if (x > 0){
return x;
}
return -x;
}
function int test_peek(int x){
return mem[x];
}
function void test_poke(int x, int y){
let mem[x] = y;
return;
}
function int test_dealloc_stolen(Array x){
var int obj_add,b;
let obj_add = x - 2;
let b = obj_add[1];
if (b[0] = 0){
let obj_add[0] = obj_add[1] - obj_add -2;
}
else{
let obj_add[0] = obj_add[1] - obj_add + b[0];
if (b[1] = b +2){
let obj_add[1] = obj_add + 2;
}
else{
let obj_add[1] = b[1];
}
}
}
function void test_dealloc(Array o){
var Array current_block;
let current_block = 2048;
let o[1]= current_block[1];
let current_block[1] = o;
}
function int test_alloc(int size){
var Array current_block;
var int tmp;
let current_block = 2048;
if (size < 0){
do Sys.error(5);
}
if (size = 0){
let size = 1;
}
while (current_block[0] < (size + 2)) {
let current_block = current_block[1];
}
let current_block[0] = current_block[0] - size - 2;
let current_block = current_block + current_block[0] + 2;
let current_block[0] = size;
return current_block + 2;
}
function int test_alloc_stolen(int x){
var Array curret_block, next_block;
if (x < 0){
do Sys.error(5);
}
if (x = 0){
let x = 1;
}
let curret_block = 2048;
let curret_block[0] = 14334;
let curret_block[1] = 2050;
while ((curret_block < 16383) & (curret_block[0] < x)){
let next_block = curret_block[1];
if ((curret_block[0] = 0) | (next_block > 16382) | (next_block[0] = 0)){ // this sends directly out of while
let curret_block = next_block;
}
else {
let curret_block[0] = curret_block[1] - curret_block + next_block[0]; // cb size =
if (next_block[1] = next_block + 2){
let curret_block[1] = curret_block + 2;
}
else{
let curret_block[1] = next_block[1];
}
}
}
if ((curret_block + x) > 16379){
do Sys.error(6);
}
if (curret_block[0] > (x + 2)){ // if current block fills the desired size perfectly
let curret_block[x + 2] = curret_block[0] - x -2;
if (curret_block[1] = curret_block + 2){
let curret_block[x + 3] = curret_block + x + 4;
}
else{
let curret_block[x + 3] = curret_block[1];
}
}
let curret_block[0] = 0;
return (curret_block + 2);
}
}
+280
View File
@@ -0,0 +1,280 @@
class Main {
static Array charMaps;
static int address;
static bool half;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void test_init() {
do Main.initMap();
do Main.moveCursor(0, 0);
return;
}
function void main(){tInt(i);
return;
}
// Returns the character map (array of size 11) of the given character.
// If the given character is invalid or non-printable, returns the
// character map of a black square.
function Array getMap(char c) {
if ((c < 32) | (c > 126)) {
let c = 0;
}
return charMaps[c];
}
/** Moves the cursor to the j-th column of the i-th row,
* and erases the character displayed there. */
function void moveCursor(int i, int j) {
var int count, display;
var Array r, char;
if (j = 0){
let half = true;
}
else{
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
}
let address = (352 * i) + (j / 2) + 16384;
let char = Main.getMap(32);
while (count < 11){
if (half){
let display = r[address] & (-256);
let r[address] = char[count] | display;
}
else{
let display = r[address] & 255;
let r[address] = (char[count]*256) | display;
}
let count = count + 1;
let address = address + 32;
}
let address = address - 352;
return;
}
/** Displays the given character at the cursor location,
* and advances the cursor one column forward. */
function void printChar(char c) {
var Array char, r;
var int count, display;
let char = Main.getMap(c);
while (count < 11){
if (half){
let display = r[address] & (-256);
let r[address] = char[count] | display;
}
else{
let display = r[address] & 255;
let r[address] = (char[count]*256) | display;
}
let count = count + 1;
let address = address + 32;
}
if (half){
let address = address - 352;
let half = false;
}
else{
if (address > 24480){
let address = 16384;
let half = true;
}
else{
let address = address - 351;
let half = true;
}
}
return;
}
/** displays the given string starting at the cursor location,
* and advances the cursor appropriately. */
function void printString(String s) {
var int i, length;
let length = s.length();
while (i < length){
do Main.printChar(s[i+2]);
let i = i + 1;
}
return;
}
/** Displays the given integer starting at the cursor location,
* and advances the cursor appropriately. */
function void printInt(int i) {
var String s;
let s = String.new(6);
do s.setInt(i);
do Main.printString(s);
return;
}
/** Advances the cursor to the beginning of the next line. */
function void println() {
var int row;
let row = (((address - 16384) / 32)/11) + 1;
if (row > 32){
let row = 0;
}
do Main.moveCursor(row, 0);
return;
}
/** Moves the cursor one column back. */
function void backSpace() {
if (address = 16384){
let address = 24191;
let half = true;
return;
}
if (half){
let address = address - 1;
let half = false;
}
else{
let half = true;
}
return;
}
// Initializes the character map array
function void initMap() {
var int i;
let charMaps = Array.new(127);
// Black square, used for displaying non-printable characters.
do Main.create(0,63,63,63,63,63,63,63,63,63,0,0);
// Assigns the bitmap for each character in the charachter set.
// The first parameter is the character index, the next 11 numbers
// are the values of each row in the frame that represents this character.
do Main.create(32,0,0,0,0,0,0,0,0,0,0,0); //
do Main.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
do Main.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
do Main.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
do Main.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
do Main.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
do Main.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
do Main.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
do Main.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
do Main.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
do Main.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
do Main.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
do Main.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
do Main.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
do Main.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
do Main.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
do Main.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
do Main.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
do Main.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
do Main.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
do Main.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
do Main.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
do Main.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
do Main.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
do Main.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
do Main.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
do Main.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
do Main.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
do Main.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
do Main.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
do Main.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
do Main.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
do Main.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
do Main.create(65,12,30,51,51,63,51,51,51,51,0,0); // A
do Main.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
do Main.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
do Main.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
do Main.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
do Main.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
do Main.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
do Main.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
do Main.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
do Main.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
do Main.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
do Main.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
do Main.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
do Main.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
do Main.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
do Main.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
do Main.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
do Main.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
do Main.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
do Main.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
do Main.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
do Main.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
do Main.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
do Main.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
do Main.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
do Main.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
do Main.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
do Main.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
do Main.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
do Main.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
do Main.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
do Main.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
do Main.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
do Main.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
do Main.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
do Main.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
do Main.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
do Main.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
do Main.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
do Main.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
do Main.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
do Main.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
do Main.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
do Main.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
do Main.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
do Main.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
do Main.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
do Main.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
do Main.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
do Main.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
do Main.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
do Main.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
do Main.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
do Main.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
do Main.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
do Main.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
do Main.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
do Main.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
do Main.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
do Main.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
do Main.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
do Main.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
return;
}
// Creates the character map array of the given character index, using the given values.
function void create(int index, int a, int b, int c, int d, int e,
int f, int g, int h, int i, int j, int k) {
var Array map;
let map = Array.new(11);
let charMaps[index] = map;
let map[0] = a;
let map[1] = b;
let map[2] = c;
let map[3] = d;
let map[4] = e;
let map[5] = f;
let map[6] = g;
let map[7] = h;
let map[8] = i;
let map[9] = j;
let map[10] = k;
return;
}
}
+148
View File
@@ -0,0 +1,148 @@
// 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/12/String.jack
/**
* Represents character strings. In addition for constructing and disposing
* strings, the class features methods for getting and setting individual
* characters of the string, for erasing the string's last character,
* for appending a character to the string's end, and more typical
* string-oriented operations.
*/
class String {
field Array str;
field int length;
static bool neg;
/** constructs a new empty string with a maximum length of maxLength
* and initial length of 0. */
constructor String new(int maxLength) {
if (maxLength > 0){
let str = Array.new(maxLength);
}
let length = 0;
return this;
}
/** Disposes this string. */
method void dispose() {
if(length > 0){
do str.dispose();
}
do Memory.deAlloc(this);
return;
}
/** Returns the current length of this string. */
method int length() {
return length;
}
/** Returns the character at the j-th location of this string. */
method char charAt(int j) {
if(j > length){
do Sys.error(7);
}
return str[j];
}
/** Sets the character at the j-th location of this string to c. */
method void setCharAt(int j, char c) {
if(j > length){
do Sys.error(7);
}
let str[j] = c;
return;
}
/** Appends c to this string's end and returns this string. */
method String appendChar(char c) {
let str[length] = c;
let length = length + 1;
return this;
}
/** Erases the last character from this string. */
method void eraseLastChar() {
let str[length] = 0;
let length = length - 1;
return;
}
/** Returns the integer value of this string,
* until a non-digit character is detected. */
method int intValue() {
var int d, sum, i;
var bool f;
while(i < length){
let d = str[i]; // kak da go zavyrtq v realen int
if ((d > 47) & (d < 58)){
let sum = (sum * 10) + (d - 48);
}
else{
if((i = 0) & (d = 45)){
let f = true;
}
else{
let i = length;
}
}
let i = i + 1;
}
if (f){
return -sum;
}
return sum;
}
/** Sets this string to hold a representation of the given value. */
method void setInt(int val) {
var int lastDigit, a,i;
var char c;
if(val < 0){
let neg = true;
let val = -val;
}
let a = val / 10;
let lastDigit = val - (a * 10);
let i = 48;
while (i < 58){
if (i = (48 + lastDigit)){
let c = i;
let i = 59;
}
let i = i + 1;
}
if (val < 10){
let length = 0;
if (neg){
let neg = false;
do this.appendChar(45);
}
do this.appendChar(c);
return;
}
else{
do this.setInt(a);
do this.appendChar(c);
}
return;
}
/** Returns the new line character. */
function char newLine() {
return 128;
}
/** Returns the backspace character. */
function char backSpace() {
return 129;
}
/** Returns the double quote (") character. */
function char doubleQuote() {
return 34;
}
}
+29
View File
@@ -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/12/Array.jack
/**
* Represents an array.
* In the Jack language, arrays are instances of the Array class.
* Once declared, the array entries can be accessed using the usual
* syntax arr[i]. Each array entry can hold a primitive data type as
* well as any object type. Different array entries can have different
* data types.
*/
class Array {
/** Constructs a new Array of the given size. */
function Array new(int size) {
if(size < 0){
do Sys.error(7);
}
return Memory.alloc(size);
}
/** Disposes this array. */
method void dispose() {
do Memory.deAlloc(this);
return;
}
}
+23
View File
@@ -0,0 +1,23 @@
function Array.new 0
push argument 0
push constant 0
lt
not
if-goto L0
push constant 7
call Sys.error 1
pop temp 0
goto L1
label L0
label L1
push argument 0
call Memory.alloc 1
return
function Array.dispose 0
push argument 0
pop pointer 0
push pointer 0
call Memory.deAlloc 1
pop temp 0
push constant 0
return
+350
View File
@@ -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()
+102
View File
@@ -0,0 +1,102 @@
// 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/12/Keyboard.jack
/**
* A library for handling user input from the keyboard.
*/
class Keyboard {
static Array mem;
/** Initializes the keyboard. */
function void init() {
let mem = 0;
return;
}
/**
* Returns the character of the currently pressed key on the keyboard;
* if no key is currently pressed, returns 0.
*
* Recognizes all ASCII characters, as well as the following keys:
* new line = 128 = String.newline()
* backspace = 129 = String.backspace()
* left arrow = 130
* up arrow = 131
* right arrow = 132
* down arrow = 133
* home = 134
* End = 135
* page up = 136
* page down = 137
* insert = 138
* delete = 139
* ESC = 140
* F1 - F12 = 141 - 152
*/
function char keyPressed() {
return mem[24576];
}
/**
* Waits until a key is pressed on the keyboard and released,
* then echoes the key to the screen, and returns the character
* of the pressed key.
*/
function char readChar() {
var char a, b;
do Output.printChar(0);
while ((b = 0) | (a > 0)){
let a = Keyboard.keyPressed();
if (a > 0){
let b = a;
}
}
do Output.printChar(String.backSpace());
do Output.printChar(b);
return b;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its value. Also handles user backspaces.
*/
function String readLine(String message) {
var String s, b;
var char c;
let s = String.new(100);
do Output.printString(message);
while (true){
let c = Keyboard.readChar();
if (c = 128){
return s;
}
else{
if (c = 129){
do s.eraseLastChar();
}
else{
do s.appendChar(c);
}
}
}
return s;
}
/**
* Displays the message on the screen, reads from the keyboard the entered
* text until a newline character is detected, echoes the text to the screen,
* and returns its integer value (until the first non-digit character in the
* entered text is detected). Also handles user backspaces.
*/
function int readInt(String message) {
var starting a;
var int b;
let a = Keyboard.readLine(message);
let b = String.intValue(a);
do String.dispose(a);
return b;
}
}
+103
View File
@@ -0,0 +1,103 @@
function Keyboard.init 0
push constant 0
pop static 0
push constant 0
return
function Keyboard.keyPressed 0
push static 0
push constant 24576
add
pop pointer 1
push that 0
return
function Keyboard.readChar 2
push constant 0
call Output.printChar 1
pop temp 0
label L0
push local 1
push constant 0
eq
push local 0
push constant 0
gt
or
not
if-goto L1
call Keyboard.keyPressed 0
pop local 0
push local 0
push constant 0
gt
not
if-goto L2
push local 0
pop local 1
goto L3
label L2
label L3
goto L0
label L1
call String.backSpace 0
call Output.printChar 1
pop temp 0
push local 1
call Output.printChar 1
pop temp 0
push local 1
return
function Keyboard.readLine 3
push constant 100
call String.new 1
pop local 0
push argument 0
call Output.printString 1
pop temp 0
label L4
push constant 1
neg
not
if-goto L5
call Keyboard.readChar 0
pop local 2
push local 2
push constant 128
eq
not
if-goto L6
push local 0
return
goto L7
label L6
push local 2
push constant 129
eq
not
if-goto L8
push local 0
call String.eraseLastChar 1
pop temp 0
goto L9
label L8
push local 0
push local 2
call String.appendChar 2
pop temp 0
label L9
label L7
goto L4
label L5
push local 0
return
function Keyboard.readInt 2
push argument 0
call Keyboard.readLine 1
pop local 0
push local 0
call String.intValue 1
pop local 1
push local 0
call String.dispose 1
pop temp 0
push local 1
return
+83
View File
@@ -0,0 +1,83 @@
// 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/12/StringTest/Main.jack
/** Test program for the OS String class. */
class Main {
/** Performs various string manipulations and displays their results. */
function void main() {
var String s;
var String i;
let s = String.new(0); // a zero-capacity string should be supported
do s.dispose();
let s = String.new(6); // capacity 6, make sure that length 5 is displayed
let s = s.appendChar(97);
let s = s.appendChar(98);
let s = s.appendChar(99);
let s = s.appendChar(100);
let s = s.appendChar(101);
do Output.printString("new: ");
do Output.printString(s); // new, appendChar: abcde
do Output.println();
let i = String.new(6);
do i.setInt(12345);
do Output.printString("setInt: ");
do Output.printString(i); // setInt: 12345
do Output.println();
do i.setInt(-32767);
do Output.printString("setInt: ");
do Output.printString(i); // setInt: -32767
do Output.println();
do Output.printString("length: ");
do Output.printInt(s.length()); // length: 5
do Output.println();
do Output.printString("charAt[2]: ");
do Output.printInt(s.charAt(2)); // charAt[2]: 99
do Output.println();
do s.setCharAt(2, 45);
do Output.printString("setCharAt(2,'-'): ");
do Output.printString(s); // setCharAt(2,'-'): ab-de
do Output.println();
do s.eraseLastChar();
do Output.printString("eraseLastChar: ");
do Output.printString(s); // eraseLastChar: ab-d
do Output.println();
let s = "456";
do Output.printString("intValue: ");
do Output.printInt(s.intValue()); // intValue: 456
do Output.println();
let s = "-32123";
do Output.printString("intValue: ");
do Output.printInt(s.intValue()); // intValue: -32123
do Output.println();
do Output.printString("backSpace: ");
do Output.printInt(String.backSpace()); // backSpace: 129
do Output.println();
do Output.printString("doubleQuote: ");
do Output.printInt(String.doubleQuote());// doubleQuote: 34
do Output.println();
do Output.printString("newLine: ");
do Output.printInt(String.newLine()); // newLine: 128
do Output.println();
do i.dispose();
do s.dispose();
return;
}
}
+447
View File
@@ -0,0 +1,447 @@
function Main.main 2
push constant 0
call String.new 1
pop local 0
push local 0
call String.dispose 1
pop temp 0
push constant 6
call String.new 1
pop local 0
push local 0
push constant 97
call String.appendChar 2
pop local 0
push local 0
push constant 98
call String.appendChar 2
pop local 0
push local 0
push constant 99
call String.appendChar 2
pop local 0
push local 0
push constant 100
call String.appendChar 2
pop local 0
push local 0
push constant 101
call String.appendChar 2
pop local 0
push constant 5
call String.new 1
push constant 110
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 119
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 6
call String.new 1
pop local 1
push local 1
push constant 12345
call String.setInt 2
pop temp 0
push constant 8
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 73
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push local 1
push constant 32767
neg
call String.setInt 2
pop temp 0
push constant 8
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 73
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 8
call String.new 1
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 103
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 104
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
call String.length 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 11
call String.new 1
push constant 99
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 91
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 93
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 2
call String.charAt 2
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push local 0
push constant 2
push constant 45
call String.setCharAt 3
pop temp 0
push constant 18
call String.new 1
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 65
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 40
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 44
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 45
call String.appendChar 2
push constant 39
call String.appendChar 2
push constant 41
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
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push local 0
call String.eraseLastChar 1
pop temp 0
push constant 15
call String.new 1
push constant 101
call String.appendChar 2
push constant 114
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 76
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 115
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 67
call String.appendChar 2
push constant 104
call String.appendChar 2
push constant 97
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 Output.printString 1
pop temp 0
push local 0
call Output.printString 1
pop temp 0
call Output.println 0
pop temp 0
push constant 3
call String.new 1
push constant 52
call String.appendChar 2
push constant 53
call String.appendChar 2
push constant 54
call String.appendChar 2
pop local 0
push constant 10
call String.new 1
push constant 105
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 117
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
call Output.printString 1
pop temp 0
push local 0
call String.intValue 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 6
call String.new 1
push constant 45
call String.appendChar 2
push constant 51
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 49
call String.appendChar 2
push constant 50
call String.appendChar 2
push constant 51
call String.appendChar 2
pop local 0
push constant 10
call String.new 1
push constant 105
call String.appendChar 2
push constant 110
call String.appendChar 2
push constant 116
call String.appendChar 2
push constant 86
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 117
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
call Output.printString 1
pop temp 0
push local 0
call String.intValue 1
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 11
call String.new 1
push constant 98
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
call String.appendChar 2
push constant 107
call String.appendChar 2
push constant 83
call String.appendChar 2
push constant 112
call String.appendChar 2
push constant 97
call String.appendChar 2
push constant 99
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
call Output.printString 1
pop temp 0
call String.backSpace 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 13
call String.new 1
push constant 100
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 98
call String.appendChar 2
push constant 108
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 81
call String.appendChar 2
push constant 117
call String.appendChar 2
push constant 111
call String.appendChar 2
push constant 116
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
call Output.printString 1
pop temp 0
call String.doubleQuote 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push constant 9
call String.new 1
push constant 110
call String.appendChar 2
push constant 101
call String.appendChar 2
push constant 119
call String.appendChar 2
push constant 76
call String.appendChar 2
push constant 105
call String.appendChar 2
push constant 110
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
call Output.printString 1
pop temp 0
call String.newLine 0
call Output.printInt 1
pop temp 0
call Output.println 0
pop temp 0
push local 1
call String.dispose 1
pop temp 0
push local 0
call String.dispose 1
pop temp 0
push constant 0
return
+143
View File
@@ -0,0 +1,143 @@
// 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/12/Math.jack
/**
* A library of commonly used mathematical functions.
* Note: Jack compilers implement multiplication and division using OS method calls.
*/
class Math {
static Array st;
static int division_tmp, f;
/** Initializes the library. */
function void init() {
var int a;
let st = Array.new(16);
let st[0] = 1;
while (a < 15){
let a = a + 1;
let st[a] = st[a - 1] + st[a - 1];
}
return;
}
/** Returns the absolute value of x. */
function int abs(int x) {
if (x > 0){
return x;
}
return -x;
}
/** Returns the product of x and y.
* When a Jack compiler detects the multiplication operator '*' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x*y and multiply(x,y) return the same value.
*/
function int multiply(int x, int y) {
var int sum, temp, y_comp, i, neg;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (x < y){
let temp = x;
let x = y;
let y = temp;
}
if (y = 1){
if(neg){
return -x;
}
return x;
}
while((y_comp - 1) < (y - 1)){
if ((st[i] & y) > 0) {
let sum = sum + x;
let y_comp = y_comp + st[i];
}
let x = x + x;
let i = i + 1;
}
if(neg){
let sum = -sum;
}
return sum;
}
/** Returns the integer part of x/y.
* When a Jack compiler detects the multiplication operator '/' in the
* program's code, it handles it by invoking this method. In other words,
* the Jack expressions x/y and divide(x,y) return the same value.
*/
function int divide(int x, int y) {
var int q, neg;
if (f = 0){
let division_tmp = 0;
let neg = ((x < 0) & (y > 0)) | ((x > 0) & (y < 0));
let x = Math.abs(x);
let y = Math.abs(y);
if (y = 0){
do Sys.error(3);
}
let f = 1;
}
if ((y > x) | (y < 0)){
return 0;
}
let q = Math.divide(x, y + y);
let f = 0;
let q = Math.abs(q);
if ((q & 1) = 1){
let division_tmp = division_tmp + y + y;
}
if (x - division_tmp < y){
if (neg){
return -(q + q);
}
return q + q;
}
else{
if (neg){
return -(q + q + 1);
}
return q + q + 1;
}
}
/** Returns the integer part of the square root of x. */
function int sqrt(int x) {
var int j, b, d, y;
if (x < 0){
do Sys.error(4);
}
let j = 7;
while (j > -1){
let d = y + st[j];
let b = d * d;
if ((~(b > x)) & (b > 0)){
let y = d;
}
let j = j - 1;
}
return y;
}
/** Returns the greater number. */
function int max(int a, int b) {
if (a > b){
return a;
}
return b;
}
/** Returns the smaller number. */
function int min(int a, int b) {
if (a < b){
return a;
}
return b;
}
}
+388
View File
@@ -0,0 +1,388 @@
function Math.init 1
push constant 16
call Array.new 1
pop static 0
push static 0
push constant 0
push constant 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
label L0
push local 0
push constant 15
lt
not
if-goto L1
push local 0
push constant 1
add
pop local 0
push static 0
push local 0
push static 0
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
push static 0
push local 0
push constant 1
sub
add
pop pointer 1
push that 0
add
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
goto L0
label L1
push constant 0
return
function Math.abs 0
push argument 0
push constant 0
gt
not
if-goto L2
push argument 0
return
goto L3
label L2
label L3
push argument 0
neg
return
function Math.multiply 5
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 4
push argument 0
call Math.abs 1
pop argument 0
push argument 1
call Math.abs 1
pop argument 1
push argument 0
push argument 1
lt
not
if-goto L4
push argument 0
pop local 1
push argument 1
pop argument 0
push local 1
pop argument 1
goto L5
label L4
label L5
push argument 1
push constant 1
eq
not
if-goto L6
push local 4
not
if-goto L7
push argument 0
neg
return
goto L8
label L7
label L8
push argument 0
return
goto L9
label L6
label L9
label L10
push local 2
push constant 1
sub
push argument 1
push constant 1
sub
lt
not
if-goto L11
push static 0
push local 3
add
pop pointer 1
push that 0
push argument 1
and
push constant 0
gt
not
if-goto L12
push local 0
push argument 0
add
pop local 0
push local 2
push static 0
push local 3
add
pop pointer 1
push that 0
add
pop local 2
goto L13
label L12
label L13
push argument 0
push argument 0
add
pop argument 0
push local 3
push constant 1
add
pop local 3
goto L10
label L11
push local 4
not
if-goto L14
push local 0
neg
pop local 0
goto L15
label L14
label L15
push local 0
return
function Math.divide 2
push static 2
push constant 0
eq
not
if-goto L16
push constant 0
pop static 1
push argument 0
push constant 0
lt
push argument 1
push constant 0
gt
and
push argument 0
push constant 0
gt
push argument 1
push constant 0
lt
and
or
pop local 1
push argument 0
call Math.abs 1
pop argument 0
push argument 1
call Math.abs 1
pop argument 1
push argument 1
push constant 0
eq
not
if-goto L17
push constant 3
call Sys.error 1
pop temp 0
goto L18
label L17
label L18
push constant 1
pop static 2
goto L19
label L16
label L19
push argument 1
push argument 0
gt
push argument 1
push constant 0
lt
or
not
if-goto L20
push constant 0
return
goto L21
label L20
label L21
push argument 0
push argument 1
push argument 1
add
call Math.divide 2
pop local 0
push constant 0
pop static 2
push local 0
call Math.abs 1
pop local 0
push local 0
push constant 1
and
push constant 1
eq
not
if-goto L22
push static 1
push argument 1
add
push argument 1
add
pop static 1
goto L23
label L22
label L23
push argument 0
push static 1
sub
push argument 1
lt
not
if-goto L24
push local 1
not
if-goto L25
push local 0
push local 0
add
neg
return
goto L26
label L25
label L26
push local 0
push local 0
add
return
goto L27
label L24
push local 1
not
if-goto L28
push local 0
push local 0
add
push constant 1
add
neg
return
goto L29
label L28
label L29
push local 0
push local 0
add
push constant 1
add
return
label L27
function Math.sqrt 4
push argument 0
push constant 0
lt
not
if-goto L30
push constant 4
call Sys.error 1
pop temp 0
goto L31
label L30
label L31
push constant 7
pop local 0
label L32
push local 0
push constant 1
neg
gt
not
if-goto L33
push local 3
push static 0
push local 0
add
pop pointer 1
push that 0
add
pop local 2
push local 2
push local 2
call Math.multiply 2
pop local 1
push local 1
push argument 0
gt
not
push local 1
push constant 0
gt
and
not
if-goto L34
push local 2
pop local 3
goto L35
label L34
label L35
push local 0
push constant 1
sub
pop local 0
goto L32
label L33
push local 3
return
function Math.max 0
push argument 0
push argument 1
gt
not
if-goto L36
push argument 0
return
goto L37
label L36
label L37
push argument 1
return
function Math.min 0
push argument 0
push argument 1
lt
not
if-goto L38
push argument 0
return
goto L39
label L38
label L39
push argument 1
return
+63
View File
@@ -0,0 +1,63 @@
// 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/12/Memory.jack
/**
* This library provides two services: direct access to the computer's main
* memory (RAM), and allocation and recycling of memory blocks. The Hack RAM
* consists of 32,768 words, each holding a 16-bit binary number.
*/
class Memory {
static Array mem;
/** Initializes the class. */
function void init() {
let mem = 0;
let mem[2048] = 14334;
let mem[2049] = -1;
return;
}
/** Returns the RAM value at the given address. */
function int peek(int address) {
return mem[address];
}
/** Sets the RAM value at the given address to the given value. */
function void poke(int address, int value) {
let mem[address] = value;
return;
}
/** Finds an available RAM block of the given size and returns
* a reference to its base address. */
function int alloc(int size) {
var Array current_block;
var int tmp;
let current_block = 2048;
if (size < 0){
do Sys.error(5);
}
if (size = 0){
let size = 1;
}
while (current_block[0] < (size + 2)) {
let current_block = current_block[1];
}
let current_block[0] = current_block[0] - size - 2;
let current_block = current_block + current_block[0] + 2;
let current_block[0] = size;
return current_block + 2;
}
/** De-allocates the given object (cast as an array) by making
* it available for future allocations. */
function void deAlloc(Array o) {
var Array current_block;
let current_block = 2048;
let o[1]= current_block[1];
let current_block[1] = o;
return;
}
}
+147
View File
@@ -0,0 +1,147 @@
function Memory.init 0
push constant 0
pop static 0
push static 0
push constant 2048
push constant 14334
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push static 0
push constant 2049
push constant 1
neg
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function Memory.peek 0
push static 0
push argument 0
add
pop pointer 1
push that 0
return
function Memory.poke 0
push static 0
push argument 0
push argument 1
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
function Memory.alloc 2
push constant 2048
pop local 0
push argument 0
push constant 0
lt
not
if-goto L0
push constant 5
call Sys.error 1
pop temp 0
goto L1
label L0
label L1
push argument 0
push constant 0
eq
not
if-goto L2
push constant 1
pop argument 0
goto L3
label L2
label L3
label L4
push local 0
push constant 0
add
pop pointer 1
push that 0
push argument 0
push constant 2
add
lt
not
if-goto L5
push local 0
push constant 1
add
pop pointer 1
push that 0
pop local 0
goto L4
label L5
push local 0
push constant 0
push local 0
push constant 0
add
pop pointer 1
push that 0
push argument 0
sub
push constant 2
sub
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push local 0
push constant 0
add
pop pointer 1
push that 0
add
push constant 2
add
pop local 0
push local 0
push constant 0
push argument 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 2
add
return
function Memory.deAlloc 1
push constant 2048
pop local 0
push argument 0
push constant 1
push local 0
push constant 1
add
pop pointer 1
push that 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push local 0
push constant 1
push argument 0
pop temp 1
add
pop pointer 1
push temp 1
pop that 0
push constant 0
return
+299
View File
@@ -0,0 +1,299 @@
// 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/12/Output.jack
/**
* A library of functions for writing text on the screen.
* The Hack physical screen consists of 512 rows of 256 pixels each.
* The library uses a fixed font, in which each character is displayed
* within a frame which is 11 pixels high (including 1 pixel for inter-line
* spacing) and 8 pixels wide (including 2 pixels for inter-character spacing).
* The resulting grid accommodates 23 rows (indexed 0..22, top to bottom)
* of 64 characters each (indexed 0..63, left to right). The top left
* character position on the screen is indexed (0,0). A cursor, implemented
* as a small filled square, indicates where the next character will be displayed.
*/
class Output {
// Character map for displaying characters
static Array charMaps;
static int address;
static bool half;
/** Initializes the screen, and locates the cursor at the screen's top-left. */
function void init() {
do Output.initMap();
do Output.moveCursor(0, 0);
return;
}
// Initializes the character map array
function void initMap() {
var int i;
let charMaps = Array.new(127);
// Black square, used for displaying non-printable characters.
do Output.create(0,63,63,63,63,63,63,63,63,63,0,0);
// Assigns the bitmap for each character in the charachter set.
// The first parameter is the character index, the next 11 numbers
// are the values of each row in the frame that represents this character.
do Output.create(32,0,0,0,0,0,0,0,0,0,0,0); //
do Output.create(33,12,30,30,30,12,12,0,12,12,0,0); // !
do Output.create(34,54,54,20,0,0,0,0,0,0,0,0); // "
do Output.create(35,0,18,18,63,18,18,63,18,18,0,0); // #
do Output.create(36,12,30,51,3,30,48,51,30,12,12,0); // $
do Output.create(37,0,0,35,51,24,12,6,51,49,0,0); // %
do Output.create(38,12,30,30,12,54,27,27,27,54,0,0); // &
do Output.create(39,12,12,6,0,0,0,0,0,0,0,0); // '
do Output.create(40,24,12,6,6,6,6,6,12,24,0,0); // (
do Output.create(41,6,12,24,24,24,24,24,12,6,0,0); // )
do Output.create(42,0,0,0,51,30,63,30,51,0,0,0); // *
do Output.create(43,0,0,0,12,12,63,12,12,0,0,0); // +
do Output.create(44,0,0,0,0,0,0,0,12,12,6,0); // ,
do Output.create(45,0,0,0,0,0,63,0,0,0,0,0); // -
do Output.create(46,0,0,0,0,0,0,0,12,12,0,0); // .
do Output.create(47,0,0,32,48,24,12,6,3,1,0,0); // /
do Output.create(48,12,30,51,51,51,51,51,30,12,0,0); // 0
do Output.create(49,12,14,15,12,12,12,12,12,63,0,0); // 1
do Output.create(50,30,51,48,24,12,6,3,51,63,0,0); // 2
do Output.create(51,30,51,48,48,28,48,48,51,30,0,0); // 3
do Output.create(52,16,24,28,26,25,63,24,24,60,0,0); // 4
do Output.create(53,63,3,3,31,48,48,48,51,30,0,0); // 5
do Output.create(54,28,6,3,3,31,51,51,51,30,0,0); // 6
do Output.create(55,63,49,48,48,24,12,12,12,12,0,0); // 7
do Output.create(56,30,51,51,51,30,51,51,51,30,0,0); // 8
do Output.create(57,30,51,51,51,62,48,48,24,14,0,0); // 9
do Output.create(58,0,0,12,12,0,0,12,12,0,0,0); // :
do Output.create(59,0,0,12,12,0,0,12,12,6,0,0); // ;
do Output.create(60,0,0,24,12,6,3,6,12,24,0,0); // <
do Output.create(61,0,0,0,63,0,0,63,0,0,0,0); // =
do Output.create(62,0,0,3,6,12,24,12,6,3,0,0); // >
do Output.create(64,30,51,51,59,59,59,27,3,30,0,0); // @
do Output.create(63,30,51,51,24,12,12,0,12,12,0,0); // ?
do Output.create(65,12,30,51,51,63,51,51,51,51,0,0); // A ** TO BE FILLED **
do Output.create(66,31,51,51,51,31,51,51,51,31,0,0); // B
do Output.create(67,28,54,35,3,3,3,35,54,28,0,0); // C
do Output.create(68,15,27,51,51,51,51,51,27,15,0,0); // D
do Output.create(69,63,51,35,11,15,11,35,51,63,0,0); // E
do Output.create(70,63,51,35,11,15,11,3,3,3,0,0); // F
do Output.create(71,28,54,35,3,59,51,51,54,44,0,0); // G
do Output.create(72,51,51,51,51,63,51,51,51,51,0,0); // H
do Output.create(73,30,12,12,12,12,12,12,12,30,0,0); // I
do Output.create(74,60,24,24,24,24,24,27,27,14,0,0); // J
do Output.create(75,51,51,51,27,15,27,51,51,51,0,0); // K
do Output.create(76,3,3,3,3,3,3,35,51,63,0,0); // L
do Output.create(77,33,51,63,63,51,51,51,51,51,0,0); // M
do Output.create(78,51,51,55,55,63,59,59,51,51,0,0); // N
do Output.create(79,30,51,51,51,51,51,51,51,30,0,0); // O
do Output.create(80,31,51,51,51,31,3,3,3,3,0,0); // P
do Output.create(81,30,51,51,51,51,51,63,59,30,48,0);// Q
do Output.create(82,31,51,51,51,31,27,51,51,51,0,0); // R
do Output.create(83,30,51,51,6,28,48,51,51,30,0,0); // S
do Output.create(84,63,63,45,12,12,12,12,12,30,0,0); // T
do Output.create(85,51,51,51,51,51,51,51,51,30,0,0); // U
do Output.create(86,51,51,51,51,51,30,30,12,12,0,0); // V
do Output.create(87,51,51,51,51,51,63,63,63,18,0,0); // W
do Output.create(88,51,51,30,30,12,30,30,51,51,0,0); // X
do Output.create(89,51,51,51,51,30,12,12,12,30,0,0); // Y
do Output.create(90,63,51,49,24,12,6,35,51,63,0,0); // Z
do Output.create(91,30,6,6,6,6,6,6,6,30,0,0); // [
do Output.create(92,0,0,1,3,6,12,24,48,32,0,0); // \
do Output.create(93,30,24,24,24,24,24,24,24,30,0,0); // ]
do Output.create(94,8,28,54,0,0,0,0,0,0,0,0); // ^
do Output.create(95,0,0,0,0,0,0,0,0,0,63,0); // _
do Output.create(96,6,12,24,0,0,0,0,0,0,0,0); // `
do Output.create(97,0,0,0,14,24,30,27,27,54,0,0); // a
do Output.create(98,3,3,3,15,27,51,51,51,30,0,0); // b
do Output.create(99,0,0,0,30,51,3,3,51,30,0,0); // c
do Output.create(100,48,48,48,60,54,51,51,51,30,0,0); // d
do Output.create(101,0,0,0,30,51,63,3,51,30,0,0); // e
do Output.create(102,28,54,38,6,15,6,6,6,15,0,0); // f
do Output.create(103,0,0,30,51,51,51,62,48,51,30,0); // g
do Output.create(104,3,3,3,27,55,51,51,51,51,0,0); // h
do Output.create(105,12,12,0,14,12,12,12,12,30,0,0); // i
do Output.create(106,48,48,0,56,48,48,48,48,51,30,0); // j
do Output.create(107,3,3,3,51,27,15,15,27,51,0,0); // k
do Output.create(108,14,12,12,12,12,12,12,12,30,0,0); // l
do Output.create(109,0,0,0,29,63,43,43,43,43,0,0); // m
do Output.create(110,0,0,0,29,51,51,51,51,51,0,0); // n
do Output.create(111,0,0,0,30,51,51,51,51,30,0,0); // o
do Output.create(112,0,0,0,30,51,51,51,31,3,3,0); // p
do Output.create(113,0,0,0,30,51,51,51,62,48,48,0); // q
do Output.create(114,0,0,0,29,55,51,3,3,7,0,0); // r
do Output.create(115,0,0,0,30,51,6,24,51,30,0,0); // s
do Output.create(116,4,6,6,15,6,6,6,54,28,0,0); // t
do Output.create(117,0,0,0,27,27,27,27,27,54,0,0); // u
do Output.create(118,0,0,0,51,51,51,51,30,12,0,0); // v
do Output.create(119,0,0,0,51,51,51,63,63,18,0,0); // w
do Output.create(120,0,0,0,51,30,12,12,30,51,0,0); // x
do Output.create(121,0,0,0,51,51,51,62,48,24,15,0); // y
do Output.create(122,0,0,0,63,27,12,6,51,63,0,0); // z
do Output.create(123,56,12,12,12,7,12,12,12,56,0,0); // {
do Output.create(124,12,12,12,12,12,12,12,12,12,0,0); // |
do Output.create(125,7,12,12,12,56,12,12,12,7,0,0); // }
do Output.create(126,38,45,25,0,0,0,0,0,0,0,0); // ~
return;
}
// Creates the character map array of the given character index, using the given values.
function void create(int index, int a, int b, int c, int d, int e,
int f, int g, int h, int i, int j, int k) {
var Array map;
let map = Array.new(11);
let charMaps[index] = map;
let map[0] = a;
let map[1] = b;
let map[2] = c;
let map[3] = d;
let map[4] = e;
let map[5] = f;
let map[6] = g;
let map[7] = h;
let map[8] = i;
let map[9] = j;
let map[10] = k;
return;
}
// Returns the character map (array of size 11) of the given character.
// If the given character is invalid or non-printable, returns the
// character map of a black square.
function Array getMap(char c) {
if ((c < 32) | (c > 126)) {
let c = 0;
}
return charMaps[c];
}
/** Moves the cursor to the j-th column of the i-th row,
* and erases the character displayed there. */
function void moveCursor(int i, int j) {
var int co,display;
var Array r,ch;
if (j = 0){
let half = true;
}
else{
let half = (j / 2) * 2 = j; // chetno true, 1vaa chast
}
let address = (352 * i) + (j / 2) + 16384;
let ch = Output.getMap(32);
while (co < 11){
if (half){
let display = r[address] & (-256);
let r[address] = ch[co] | display;
}
else{
let display = r[address] & 255;
let r[address] = (ch[co]*256) | display;
}
let co = co + 1;
let address = address + 32;
}
let address = address - 352;
return;
}
/** Displays the given character at the cursor location,
* and advances the cursor one column forward. */
function void printChar(char c) {
var Array ch;
var Array r;
var int co;
var int ds;
let ch = Output.getMap(c);
while (co < 11){
if (half){
let ds = r[address] & (-256);
let r[address] = ch[co] | ds;
}
else{
let ds = r[address] & 255;
let r[address] = (ch[co]*256) | ds;
}
let co = co + 1;
let address = address + 32;
}
if (half){
let address = address - 352;
let half = false;
}
else{
if (address > 24480){
let address = 16384;
let half = true;
}
else{
let address = address - 351;
let half = true;
}
}
return;
}
/** displays the given string starting at the cursor location,
* and advances the cursor appropriately. */
function void printString(String s) {
var int i, length;
let length = s.length();
while (i < length){
do Output.printChar(s.charAt(i));
let i = i + 1;
}
return;
}
/** Displays the given integer starting at the cursor location,
* and advances the cursor appropriately. */
function void printInt(int i) {
var String s;
let s = String.new(6);
do s.setInt(i);
do Output.printString(s);
return;
}
/** Advances the cursor to the beginning of the next line. */
function void println() {
var int row;
let row = (((address - 16384) / 32)/11) + 1;
if (row > 32){
let row = 0;
}
do Output.moveCursor(row, 0);
return;
}
/** Moves the cursor one column back. */
function void backSpace() {
if (address = 16384){
let address = 24191;
let half = true;
return;
}
if (half){
let address = address - 1;
let half = false;
}
else{
let half = true;
}
return;
}
}
+1793
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More