mirror of
https://github.com/soconnor0919/eceg431.git
synced 2025-12-11 06:34:43 -05:00
project11 - template
This commit is contained in:
27
11/Average/Main.jack
Normal file
27
11/Average/Main.jack
Normal file
@@ -0,0 +1,27 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Average/Main.jack
|
||||
|
||||
// Inputs some numbers and computes their average
|
||||
class Main {
|
||||
function void main() {
|
||||
var Array a;
|
||||
var int length;
|
||||
var int i, sum;
|
||||
|
||||
let length = Keyboard.readInt("How many numbers? ");
|
||||
let a = Array.new(length); // constructs the array
|
||||
|
||||
let i = 0;
|
||||
while (i < length) {
|
||||
let a[i] = Keyboard.readInt("Enter a number: ");
|
||||
let sum = sum + a[i];
|
||||
let i = i + 1;
|
||||
}
|
||||
|
||||
do Output.printString("The average is ");
|
||||
do Output.printInt(sum / length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
69
11/ComplexArrays/Main.jack
Normal file
69
11/ComplexArrays/Main.jack
Normal file
@@ -0,0 +1,69 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/ComplexArrays/Main.jack
|
||||
/**
|
||||
* Performs several complex array processing tests.
|
||||
* For each test, the expected result is printed, along with the
|
||||
* actual result. In each test, the two results should be equal.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
function void main() {
|
||||
var Array a, b, c;
|
||||
|
||||
let a = Array.new(10);
|
||||
let b = Array.new(5);
|
||||
let c = Array.new(1);
|
||||
|
||||
let a[3] = 2;
|
||||
let a[4] = 8;
|
||||
let a[5] = 4;
|
||||
let b[a[3]] = a[3] + 3; // b[2] = 5
|
||||
let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40
|
||||
let c[0] = null;
|
||||
let c = c[0];
|
||||
|
||||
do Output.printString("Test 1: expected result: 5; actual result: ");
|
||||
do Output.printInt(b[2]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 2: expected result: 40; actual result: ");
|
||||
do Output.printInt(a[5]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 3: expected result: 0; actual result: ");
|
||||
do Output.printInt(c);
|
||||
do Output.println();
|
||||
|
||||
let c = null;
|
||||
|
||||
if (c = null) {
|
||||
do Main.fill(a, 10);
|
||||
let c = a[3];
|
||||
let c[1] = 33;
|
||||
let c = a[7];
|
||||
let c[1] = 77;
|
||||
let b = a[3];
|
||||
let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110;
|
||||
}
|
||||
|
||||
do Output.printString("Test 4: expected result: 77; actual result: ");
|
||||
do Output.printInt(c[1]);
|
||||
do Output.println();
|
||||
do Output.printString("Test 5: expected result: 110; actual result: ");
|
||||
do Output.printInt(b[1]);
|
||||
do Output.println();
|
||||
return;
|
||||
}
|
||||
|
||||
function int double(int a) {
|
||||
return a * 2;
|
||||
}
|
||||
|
||||
function void fill(Array a, int size) {
|
||||
while (size > 0) {
|
||||
let size = size - 1;
|
||||
let a[size] = Array.new(3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
81
11/ConvertToBin/Main.jack
Normal file
81
11/ConvertToBin/Main.jack
Normal file
@@ -0,0 +1,81 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/ConvertToBin/Main.jack
|
||||
/**
|
||||
* Unpacks a 16-bit number into its binary representation:
|
||||
* Takes the 16-bit number stored in RAM[8000] and stores its individual
|
||||
* bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1).
|
||||
* Before the conversion, RAM[8001]..RAM[8016] are initialized to -1.
|
||||
*
|
||||
* The program should be tested as follows:
|
||||
* 1) Load the program into the supplied VM emulator
|
||||
* 2) Put some value in RAM[8000]
|
||||
* 3) Switch to "no animation"
|
||||
* 4) Run the program (give it enough time to run)
|
||||
* 5) Stop the program
|
||||
* 6) Check that RAM[8001]..RAM[8016] contain the correct bits, and
|
||||
* that none of these memory locations contains -1.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
/**
|
||||
* Initializes RAM[8001]..RAM[8016] to -1,
|
||||
* and converts the value in RAM[8000] to binary.
|
||||
*/
|
||||
function void main() {
|
||||
var int value;
|
||||
do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1
|
||||
let value = Memory.peek(8000); // Uses an OS routine to read the input
|
||||
do Main.convert(value); // performs the conversion
|
||||
return;
|
||||
}
|
||||
|
||||
/** Converts the given decimal value to binary, and puts
|
||||
* the resulting bits in RAM[8001]..RAM[8016]. */
|
||||
function void convert(int value) {
|
||||
var int mask, position;
|
||||
var boolean loop;
|
||||
|
||||
let loop = true;
|
||||
while (loop) {
|
||||
let position = position + 1;
|
||||
let mask = Main.nextMask(mask);
|
||||
|
||||
if (~(position > 16)) {
|
||||
|
||||
if (~((value & mask) = 0)) {
|
||||
do Memory.poke(8000 + position, 1);
|
||||
}
|
||||
else {
|
||||
do Memory.poke(8000 + position, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let loop = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the next mask (the mask that should follow the given mask). */
|
||||
function int nextMask(int mask) {
|
||||
if (mask = 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return mask * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/** Fills 'length' consecutive memory locations with 'value',
|
||||
* starting at 'address'. */
|
||||
function void fillMemory(int address, int length, int value) {
|
||||
while (length > 0) {
|
||||
do Memory.poke(address, value);
|
||||
let length = length - 1;
|
||||
let address = address + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
203
11/Pong/Ball.jack
Normal file
203
11/Pong/Ball.jack
Normal file
@@ -0,0 +1,203 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Ball.jack
|
||||
// (Same as projects/9/Pong/Ball.jack)
|
||||
/**
|
||||
* A graphical ball in a Pong game. Characterized by a screen location and
|
||||
* distance of last destination. Has methods for drawing, erasing and moving
|
||||
* on the screen. The ball is displayed as a filled, 6-by-6 pixles rectangle.
|
||||
*/
|
||||
class Ball {
|
||||
|
||||
field int x, y; // the ball's screen location (in pixels)
|
||||
field int lengthx, lengthy; // distance of last destination (in pixels)
|
||||
|
||||
field int d, straightD, diagonalD; // used for straight line movement computation
|
||||
field boolean invert, positivex, positivey; // (same)
|
||||
|
||||
field int leftWall, rightWall, topWall, bottomWall; // wall locations
|
||||
|
||||
field int wall; // last wall that the ball was bounced off of
|
||||
|
||||
/** Constructs a new ball with the given initial location and wall locations. */
|
||||
constructor Ball new(int Ax, int Ay,
|
||||
int AleftWall, int ArightWall, int AtopWall, int AbottomWall) {
|
||||
let x = Ax;
|
||||
let y = Ay;
|
||||
let leftWall = AleftWall;
|
||||
let rightWall = ArightWall - 6; // -6 for ball size
|
||||
let topWall = AtopWall;
|
||||
let bottomWall = AbottomWall - 6; // -6 for ball size
|
||||
let wall = 0;
|
||||
do show();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the Ball's memory. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Shows the ball. */
|
||||
method void show() {
|
||||
do Screen.setColor(true);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Hides the ball. */
|
||||
method void hide() {
|
||||
do Screen.setColor(false);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the ball. */
|
||||
method void draw() {
|
||||
do Screen.drawRectangle(x, y, x + 5, y + 5);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the ball's left edge. */
|
||||
method int getLeft() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the ball's right edge. */
|
||||
method int getRight() {
|
||||
return x + 5;
|
||||
}
|
||||
|
||||
/** Computes and sets the ball's destination. */
|
||||
method void setDestination(int destx, int desty) {
|
||||
var int dx, dy, temp;
|
||||
let lengthx = destx - x;
|
||||
let lengthy = desty - y;
|
||||
let dx = Math.abs(lengthx);
|
||||
let dy = Math.abs(lengthy);
|
||||
let invert = (dx < dy);
|
||||
|
||||
if (invert) {
|
||||
let temp = dx; // swap dx, dy
|
||||
let dx = dy;
|
||||
let dy = temp;
|
||||
let positivex = (y < desty);
|
||||
let positivey = (x < destx);
|
||||
}
|
||||
else {
|
||||
let positivex = (x < destx);
|
||||
let positivey = (y < desty);
|
||||
}
|
||||
|
||||
let d = (2 * dy) - dx;
|
||||
let straightD = 2 * dy;
|
||||
let diagonalD = 2 * (dy - dx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the ball one step towards its destination.
|
||||
* If the ball has reached a wall, returns 0.
|
||||
* Else, returns a value according to the wall:
|
||||
* 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall).
|
||||
*/
|
||||
method int move() {
|
||||
|
||||
do hide();
|
||||
|
||||
if (d < 0) { let d = d + straightD; }
|
||||
else {
|
||||
let d = d + diagonalD;
|
||||
|
||||
if (positivey) {
|
||||
if (invert) { let x = x + 4; }
|
||||
else { let y = y + 4; }
|
||||
}
|
||||
else {
|
||||
if (invert) { let x = x - 4; }
|
||||
else { let y = y - 4; }
|
||||
}
|
||||
}
|
||||
|
||||
if (positivex) {
|
||||
if (invert) { let y = y + 4; }
|
||||
else { let x = x + 4; }
|
||||
}
|
||||
else {
|
||||
if (invert) { let y = y - 4; }
|
||||
else { let x = x - 4; }
|
||||
}
|
||||
|
||||
if (~(x > leftWall)) {
|
||||
let wall = 1;
|
||||
let x = leftWall;
|
||||
}
|
||||
if (~(x < rightWall)) {
|
||||
let wall = 2;
|
||||
let x = rightWall;
|
||||
}
|
||||
if (~(y > topWall)) {
|
||||
let wall = 3;
|
||||
let y = topWall;
|
||||
}
|
||||
if (~(y < bottomWall)) {
|
||||
let wall = 4;
|
||||
let y = bottomWall;
|
||||
}
|
||||
|
||||
do show();
|
||||
|
||||
return wall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounces off the current wall: sets the new destination
|
||||
* of the ball according to the ball's angle and the given
|
||||
* bouncing direction (-1/0/1=left/center/right or up/center/down).
|
||||
*/
|
||||
method void bounce(int bouncingDirection) {
|
||||
var int newx, newy, divLengthx, divLengthy, factor;
|
||||
|
||||
// Since results are too big, divides by 10
|
||||
let divLengthx = lengthx / 10;
|
||||
let divLengthy = lengthy / 10;
|
||||
if (bouncingDirection = 0) { let factor = 10; }
|
||||
else {
|
||||
if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) {
|
||||
let factor = 20; // bounce direction is in ball direction
|
||||
}
|
||||
else { let factor = 5; } // bounce direction is against ball direction
|
||||
}
|
||||
|
||||
if (wall = 1) {
|
||||
let newx = 506;
|
||||
let newy = (divLengthy * (-50)) / divLengthx;
|
||||
let newy = y + (newy * factor);
|
||||
}
|
||||
else {
|
||||
if (wall = 2) {
|
||||
let newx = 0;
|
||||
let newy = (divLengthy * 50) / divLengthx;
|
||||
let newy = y + (newy * factor);
|
||||
}
|
||||
else {
|
||||
if (wall = 3) {
|
||||
let newy = 250;
|
||||
let newx = (divLengthx * (-25)) / divLengthy;
|
||||
let newx = x + (newx * factor);
|
||||
}
|
||||
else { // assumes wall = 4
|
||||
let newy = 0;
|
||||
let newx = (divLengthx * 25) / divLengthy;
|
||||
let newx = x + (newx * factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do setDestination(newx, newy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
104
11/Pong/Bat.jack
Normal file
104
11/Pong/Bat.jack
Normal file
@@ -0,0 +1,104 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Bat.jack
|
||||
// (Same as projects/9/Pong/Bat.jack)
|
||||
/**
|
||||
* A graphical bat in a Pong game.
|
||||
* Displayed as a filled horizontal rectangle that has a screen location,
|
||||
* a width and a height.
|
||||
* Has methods for drawing, erasing, moving left and right, and changing
|
||||
* its width (to make the hitting action more challenging).
|
||||
* This class should have been called "Paddle", following the
|
||||
* standard Pong terminology. Unaware of this terminology,
|
||||
* we called it "bat", and the name stuck.
|
||||
*/
|
||||
class Bat {
|
||||
|
||||
field int x, y; // the bat's screen location
|
||||
field int width, height; // the bat's width and height
|
||||
field int direction; // direction of the bat's movement
|
||||
// (1 = left, 2 = right)
|
||||
|
||||
/** Constructs a new bat with the given location and width. */
|
||||
constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) {
|
||||
let x = Ax;
|
||||
let y = Ay;
|
||||
let width = Awidth;
|
||||
let height = Aheight;
|
||||
let direction = 2;
|
||||
do show();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the object's memory. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Shows the bat. */
|
||||
method void show() {
|
||||
do Screen.setColor(true);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Hides the bat. */
|
||||
method void hide() {
|
||||
do Screen.setColor(false);
|
||||
do draw();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws the bat. */
|
||||
method void draw() {
|
||||
do Screen.drawRectangle(x, y, x + width, y + height);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Sets the bat's direction (0=stop, 1=left, 2=right). */
|
||||
method void setDirection(int Adirection) {
|
||||
let direction = Adirection;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns the bat's left edge. */
|
||||
method int getLeft() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns the bat's right edge. */
|
||||
method int getRight() {
|
||||
return x + width;
|
||||
}
|
||||
|
||||
/** Sets the bat's width. */
|
||||
method void setWidth(int Awidth) {
|
||||
do hide();
|
||||
let width = Awidth;
|
||||
do show();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the bat one step in the bat's direction. */
|
||||
method void move() {
|
||||
if (direction = 1) {
|
||||
let x = x - 4;
|
||||
if (x < 0) { let x = 0; }
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height);
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + 3, y + height);
|
||||
}
|
||||
else {
|
||||
let x = x + 4;
|
||||
if ((x + width) > 511) { let x = 511 - width; }
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x - 4, y, x - 1, y + height);
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle((x + width) - 3, y, x + width, y + height);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
20
11/Pong/Main.jack
Normal file
20
11/Pong/Main.jack
Normal file
@@ -0,0 +1,20 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/Main.jack
|
||||
// (Same as projects/9/Pong/Main.jack)
|
||||
/**
|
||||
* Main class of the Pong game.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
/** Initializes a Pong game and starts running it. */
|
||||
function void main() {
|
||||
var PongGame game;
|
||||
do PongGame.newInstance();
|
||||
let game = PongGame.getInstance();
|
||||
do game.run();
|
||||
do game.dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
137
11/Pong/PongGame.jack
Normal file
137
11/Pong/PongGame.jack
Normal file
@@ -0,0 +1,137 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Pong/PongGame.jack
|
||||
// (Same as projects/9/Pong/PongGame.jack)
|
||||
/**
|
||||
* Represents a Pong game.
|
||||
*/
|
||||
class PongGame {
|
||||
|
||||
static PongGame instance; // A Pong game
|
||||
field Bat bat; // bat
|
||||
field Ball ball; // ball
|
||||
field int wall; // current wall that the ball is bouncing off of
|
||||
field boolean exit; // true when the game is over
|
||||
field int score; // current score
|
||||
field int lastWall; // last wall that the ball bounced off of
|
||||
|
||||
// The current width of the bat
|
||||
field int batWidth;
|
||||
|
||||
/** Constructs a new Pong game. */
|
||||
constructor PongGame new() {
|
||||
do Screen.clearScreen();
|
||||
let batWidth = 50; // initial bat size
|
||||
let bat = Bat.new(230, 229, batWidth, 7);
|
||||
let ball = Ball.new(253, 222, 0, 511, 0, 229);
|
||||
do ball.setDestination(400,0);
|
||||
do Screen.drawRectangle(0, 238, 511, 240);
|
||||
do Output.moveCursor(22,0);
|
||||
do Output.printString("Score: 0");
|
||||
|
||||
let exit = false;
|
||||
let score = 0;
|
||||
let wall = 0;
|
||||
let lastWall = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Deallocates the object's memory. */
|
||||
method void dispose() {
|
||||
do bat.dispose();
|
||||
do ball.dispose();
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Creates an instance of a Pong game. */
|
||||
function void newInstance() {
|
||||
let instance = PongGame.new();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Returns this Pong game. */
|
||||
function PongGame getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Starts the game, and handles inputs from the user that control
|
||||
* the bat's movement direction. */
|
||||
method void run() {
|
||||
var char key;
|
||||
|
||||
while (~exit) {
|
||||
// waits for a key to be pressed.
|
||||
while ((key = 0) & (~exit)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do bat.move();
|
||||
do moveBall();
|
||||
do Sys.wait(50);
|
||||
}
|
||||
|
||||
if (key = 130) { do bat.setDirection(1); }
|
||||
else {
|
||||
if (key = 132) { do bat.setDirection(2); }
|
||||
else {
|
||||
if (key = 140) { let exit = true; }
|
||||
}
|
||||
}
|
||||
|
||||
// Waits for the key to be released.
|
||||
while ((~(key = 0)) & (~exit)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do bat.move();
|
||||
do moveBall();
|
||||
do Sys.wait(50);
|
||||
}
|
||||
}
|
||||
|
||||
if (exit) {
|
||||
do Output.moveCursor(10,27);
|
||||
do Output.printString("Game Over");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles ball movement, including bouncing.
|
||||
* If the ball bounces off a wall, finds its new direction.
|
||||
* If the ball bounces off the bat, increases the score by one
|
||||
* and shrinks the bat's size, to make the game more challenging.
|
||||
*/
|
||||
method void moveBall() {
|
||||
var int bouncingDirection, batLeft, batRight, ballLeft, ballRight;
|
||||
|
||||
let wall = ball.move();
|
||||
|
||||
if ((wall > 0) & (~(wall = lastWall))) {
|
||||
let lastWall = wall;
|
||||
let bouncingDirection = 0;
|
||||
let batLeft = bat.getLeft();
|
||||
let batRight = bat.getRight();
|
||||
let ballLeft = ball.getLeft();
|
||||
let ballRight = ball.getRight();
|
||||
|
||||
if (wall = 4) {
|
||||
let exit = (batLeft > ballRight) | (batRight < ballLeft);
|
||||
if (~exit) {
|
||||
if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; }
|
||||
else {
|
||||
if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; }
|
||||
}
|
||||
|
||||
let batWidth = batWidth - 2;
|
||||
do bat.setWidth(batWidth);
|
||||
let score = score + 1;
|
||||
do Output.moveCursor(22,7);
|
||||
do Output.printInt(score);
|
||||
}
|
||||
}
|
||||
do ball.bounce(bouncingDirection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
16
11/Seven/Main.jack
Normal file
16
11/Seven/Main.jack
Normal file
@@ -0,0 +1,16 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Seven/Main.jack
|
||||
/**
|
||||
* Computes the value of 1 + (2 * 3) and prints the result
|
||||
* at the top-left of the screen.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
function void main() {
|
||||
do Output.printInt(1 + (2 * 3));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
15
11/Square/Main.jack
Normal file
15
11/Square/Main.jack
Normal 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/11/Square/Main.jack
|
||||
|
||||
/** Initializes a new Square game and starts running it. */
|
||||
class Main {
|
||||
function void main() {
|
||||
var SquareGame game;
|
||||
let game = SquareGame.new();
|
||||
do game.run();
|
||||
do game.dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
113
11/Square/Square.jack
Normal file
113
11/Square/Square.jack
Normal file
@@ -0,0 +1,113 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Square/Square.jack
|
||||
|
||||
/** Implements a graphical square.
|
||||
The square has top-left x and y coordinates, and a size. */
|
||||
class Square {
|
||||
|
||||
field int x, y; // screen location of the top-left corner of this square
|
||||
field int size; // length of this square, in pixels
|
||||
|
||||
/** Constructs and draws a new square with a given location and size. */
|
||||
constructor Square new(int ax, int ay, int asize) {
|
||||
let x = ax;
|
||||
let y = ay;
|
||||
let size = asize;
|
||||
do draw();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this square. */
|
||||
method void dispose() {
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Draws this square in its current (x,y) location */
|
||||
method void draw() {
|
||||
// Draws the square using the color black
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + size, y + size);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Erases this square. */
|
||||
method void erase() {
|
||||
// Draws the square using the color white (background color)
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + size, y + size);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Increments the square size by 2 pixels (if possible). */
|
||||
method void incSize() {
|
||||
if (((y + size) < 254) & ((x + size) < 510)) {
|
||||
do erase();
|
||||
let size = size + 2;
|
||||
do draw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Decrements the square size by 2 pixels (if possible). */
|
||||
method void decSize() {
|
||||
if (size > 2) {
|
||||
do erase();
|
||||
let size = size - 2;
|
||||
do draw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves this square up by 2 pixels (if possible). */
|
||||
method void moveUp() {
|
||||
if (y > 1) {
|
||||
// Erases the bottom two rows of this square in its current location
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
|
||||
let y = y - 2;
|
||||
// Draws the top two rows of this square in its new location
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + size, y + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square down by 2 pixels (if possible). */
|
||||
method void moveDown() {
|
||||
if ((y + size) < 254) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + size, y + 1);
|
||||
let y = y + 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square left by 2 pixels (if possible). */
|
||||
method void moveLeft() {
|
||||
if (x > 1) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
|
||||
let x = x - 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle(x, y, x + 1, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square right by 2 pixels (if possible). */
|
||||
method void moveRight() {
|
||||
if ((x + size) < 510) {
|
||||
do Screen.setColor(false);
|
||||
do Screen.drawRectangle(x, y, x + 1, y + size);
|
||||
let x = x + 2;
|
||||
do Screen.setColor(true);
|
||||
do Screen.drawRectangle((x + size) - 1, y, x + size, y + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
76
11/Square/SquareGame.jack
Normal file
76
11/Square/SquareGame.jack
Normal file
@@ -0,0 +1,76 @@
|
||||
// This file is part of www.nand2tetris.org
|
||||
// and the book "The Elements of Computing Systems"
|
||||
// by Nisan and Schocken, MIT Press.
|
||||
// File name: projects/11/Square/SquareGame.jack
|
||||
/**
|
||||
* Implements the Square game.
|
||||
* This simple game allows the user to move a black square around
|
||||
* the screen, and change the square's size during the movement.
|
||||
* When the game starts, a square of 30 by 30 pixels is shown at the
|
||||
* top-left corner of the screen. The user controls the square as follows.
|
||||
* The 4 arrow keys are used to move the square up, down, left, and right.
|
||||
* The 'z' and 'x' keys are used, respectively, to decrement and increment
|
||||
* the square's size. The 'q' key is used to quit the game.
|
||||
*/
|
||||
class SquareGame {
|
||||
field Square square; // the square of this game
|
||||
field int direction; // the square's current direction:
|
||||
// 0=none, 1=up, 2=down, 3=left, 4=right
|
||||
|
||||
/** Constructs a new square game. */
|
||||
constructor SquareGame new() {
|
||||
// The initial square is located in (0,0), has size 30, and is not moving.
|
||||
let square = Square.new(0, 0, 30);
|
||||
let direction = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Disposes this game. */
|
||||
method void dispose() {
|
||||
do square.dispose();
|
||||
do Memory.deAlloc(this);
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves the square in the current direction. */
|
||||
method void moveSquare() {
|
||||
if (direction = 1) { do square.moveUp(); }
|
||||
if (direction = 2) { do square.moveDown(); }
|
||||
if (direction = 3) { do square.moveLeft(); }
|
||||
if (direction = 4) { do square.moveRight(); }
|
||||
do Sys.wait(5); // delays the next movement
|
||||
return;
|
||||
}
|
||||
|
||||
/** Runs the game: handles the user's inputs and moves the square accordingly */
|
||||
method void run() {
|
||||
var char key; // the key currently pressed by the user
|
||||
var boolean exit;
|
||||
let exit = false;
|
||||
|
||||
while (~exit) {
|
||||
// waits for a key to be pressed
|
||||
while (key = 0) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do moveSquare();
|
||||
}
|
||||
if (key = 81) { let exit = true; } // q key
|
||||
if (key = 90) { do square.decSize(); } // z key
|
||||
if (key = 88) { do square.incSize(); } // x key
|
||||
if (key = 131) { let direction = 1; } // up arrow
|
||||
if (key = 133) { let direction = 2; } // down arrow
|
||||
if (key = 130) { let direction = 3; } // left arrow
|
||||
if (key = 132) { let direction = 4; } // right arrow
|
||||
|
||||
// waits for the key to be released
|
||||
while (~(key = 0)) {
|
||||
let key = Keyboard.keyPressed();
|
||||
do moveSquare();
|
||||
}
|
||||
} // while
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
109
11/readme.txt
Normal file
109
11/readme.txt
Normal file
@@ -0,0 +1,109 @@
|
||||
Project 11
|
||||
The compiler built in Nand to Tetris consists of two main modules: a Syntax Analyzer, built in
|
||||
project 10, and a Code Generator, built in this project. The former module is the point of departure
|
||||
for the latter module. In particular, in this project you will morph the Syntax Analyzer built in
|
||||
project 10 into a full-scale Jack compiler. You will do it by gradually replacing the routines that
|
||||
generate passive XML output with routines that generate executable VM code.
|
||||
Objective
|
||||
Extend the Syntax Analyzer built in chapter 10 into a full-scale Jack compiler. Apply your evolving
|
||||
compiler to all the test programs described below. Execute each translated program, and make
|
||||
sure that it operates according to its given documentation. This version of the compiler assumes
|
||||
that the source Jack code is error-free.
|
||||
Resources
|
||||
The main tool that you need is the programming language in which you will implement the
|
||||
compiler. You will also need the supplied VM emulator, for testing the VM code generated by your
|
||||
compiler. Since the compiler is implemented by extending the syntax analyzer built in project 10,
|
||||
you will also need the analyzer's source code.
|
||||
Implementation Stages
|
||||
We propose completing the compiler’s development in two main stages: Symbol Table, and Code
|
||||
Generation.
|
||||
Stage 0: Make a back-up copy of the syntax analyzer code developed in project 10.
|
||||
Stage 1: Symbol Table: Start by building the compiler’s SymbolTable module, and use it for
|
||||
extending the syntax analyzer built in Project 10, as follows. Presently, whenever an identifier is
|
||||
encountered in the source code, say foo, the syntax analyzer outputs the XML line <identifier> foo
|
||||
</identifier>. Extend your analyzer to output the following information about each identifier:
|
||||
name;
|
||||
category (field, static, local, arg, class, subroutine);
|
||||
index: if the identifier’s category is field, static, local, or arg,
|
||||
the running index assigned to the identifier by the symbol table;
|
||||
usage: whether the identifier is presently being declared (in a static / field / var variable declaration,
|
||||
or in a parameter list), or used (in an expression).
|
||||
|
||||
Have your syntax analyzer output this information as part of its XML output, using markup tags of
|
||||
your choice.
|
||||
Test your new SymbolTable module and the new functionality just described by running your
|
||||
extended syntax analyzer on the test Jack programs supplied in project 10. If your extended syntax
|
||||
analyzer is capable of outputting the information described above, it means that you've developed
|
||||
a complete executable capability to understand the semantics of Jack programs. At this stage you
|
||||
www.nand2tetris.org / Copyright © Noam Nisan and Shimon Schocken
|
||||
|
||||
can make the switch to developing the full-scale compiler, and start generating VM code instead of
|
||||
XML output. This can be done gradually, as we now turn to describe.
|
||||
Stage 1.5: Make a back-up copy of the extended syntax analyzer code.
|
||||
Stage 2: Code Generation: We provide six Jack programs, designed to gradually unit-test the code
|
||||
generation capabilities of your compiler. We advise to develop, and test, your evolving compiler on
|
||||
the test programs in the order given below. This way, you will be implicitly guided to build the
|
||||
compiler’s code generation capabilities in sensible stages, according to the demands presented by
|
||||
each test program.
|
||||
Normally, when one compiles a high-level program and runs into some difficulties, one concludes
|
||||
that the program is screwed up. In this project the setting is exactly the opposite. All the supplied
|
||||
test programs are error-free. Therefore, if their compilation yields any errors, it’s the compiler that
|
||||
you have to fix, not the programs. Specifically, for each test program, we recommend going
|
||||
through the following routine:
|
||||
1. Compile the program folder using the compiler that you are developing. This action should
|
||||
generate one .vm file for each source .jack file in the given folder.
|
||||
2. Inspect the generated VM files. If there are visible problems, fix your compiler and go to step 1.
|
||||
Remember: All the supplied test programs are error-free.
|
||||
3. Load the program folder into the emulator, and run the loaded code. Note that each one of the
|
||||
six supplied test programs contains specific execution guidelines; test the compiled program
|
||||
(translated VM code) according to these guidelines.
|
||||
4. If the program behaves unexpectedly, or some error message is displayed by the VM emulator,
|
||||
fix your compiler and go to step 1.
|
||||
Test Programs
|
||||
Seven: Tests how the compiler handles a simple program containing an arithmetic expression with
|
||||
integer constants but without variables, a do statement, and a return statement. Specifically, the
|
||||
program computes the expression 1 + (3 * 2) and prints its value at the top left of the screen. To
|
||||
test that your compiler has translated the program correctly, run the translated code in the VM
|
||||
emulator and verify that it displays 7 correctly.
|
||||
ConvertToBin: Tests how the compiler handles all the procedural elements of the Jack language:
|
||||
expressions (without arrays or method calls), functions, and the statements if, while, do, let and
|
||||
return. The program does not test the handling of methods, constructors, arrays, strings, static
|
||||
variables, and field variables. Specifically, the program gets a 16-bit decimal value from RAM[8000],
|
||||
converts it to binary, and stores the individual bits in RAM[8001],...,RAM[8016] (each location will
|
||||
contain 0 or 1). Before the conversion starts, the program initializes RAM[8001],...,RAM[8016] to
|
||||
-1. To test that your compiler has translated the program correctly, load the translated code into
|
||||
the VM emulator, and proceed as follows:
|
||||
Enter (interactively, using the simulator’s GUI) some decimal value in RAM[8000];
|
||||
www.nand2tetris.org / Copyright © Noam Nisan and Shimon Schocken
|
||||
|
||||
Run the program for a few seconds, then stop its execution;
|
||||
Check (by visual inspection) that memory locations RAM[8001],...,RAM[8016] contain the correct
|
||||
bits, and that none of them contains -1.
|
||||
Square (same as projects/9/Square): Tests how the compiler handles the object-based features of
|
||||
the Jack language: constructors, methods, fields, and expressions that include method calls. Does
|
||||
not test the handling of static variables. Specifically, the program launches a simple interactive
|
||||
"game" that enables moving a black square around the screen, using the keyboard’s four arrow
|
||||
keys. While moving, the size of the square can be increased and decreased anytime by pressing the
|
||||
'z' and 'x' keys, respectively. To quit the game, press the 'q' key. To test that your compiler has
|
||||
translated the program correctly, run the translated code in the VM emulator and verify that the
|
||||
game unfolds as expected (to play the game, select “no animation” and set the speed slider as
|
||||
needed).
|
||||
Average (same as projects/9/Average and projects/10/ArrayTest): : Tests how the compiler handles
|
||||
arrays, and strings. This is done by computing the average of a user-supplied sequence of integers.
|
||||
To test that your compiler has translated the program correctly, run the translated code in the VM
|
||||
emulator and follow the instructions displayed on the screen.
|
||||
Pong: A complete test of how the compiler handles an object-based application, including the
|
||||
handling of objects and static variables. In the classical Pong game, a ball is moving randomly,
|
||||
bouncing off the screen "walls." The user tries to hit the ball with a small paddle which can be
|
||||
moved by pressing the keyboard’s left and right arrow keys. Each time the paddle hits the ball, the
|
||||
user scores a point and the paddle shrinks a little, making the game increasingly more challenging.
|
||||
If the user misses and the ball hits the “floor”, the game is over. To test that your compiler has
|
||||
translated this program correctly, run the translated code in the VM emulator and play the game.
|
||||
Make sure to score some points, to test the part of the program that displays the score on the
|
||||
screen (to play the game, select “no animation” and set the speed slider as needed).
|
||||
ComplexArrays: Tests how the compiler handles complex array references, and expressions. To
|
||||
that end, the program performs five complex calculations using arrays. For each such calculation,
|
||||
the program prints on the screen the expected result, along with the actual result, as performed by
|
||||
the compiled program. To test that your compiler has translated the program correctly, run the
|
||||
translated code in the VM emulator and make sure that the expected and actual results are
|
||||
identical.
|
||||
Reference in New Issue
Block a user