Skip to content

Commit

Permalink
vm code now outputs correctly for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
sc17ljth committed Apr 15, 2019
1 parent ca6607b commit 3c71370
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 22 deletions.
75 changes: 64 additions & 11 deletions in/Main.jack
Original file line number Diff line number Diff line change
@@ -1,17 +1,70 @@
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/09/List/Main.jack
// File name: projects/11/ComplexArrays/Main.jack

/** Demonstrates the use of the List abstraction. */
/**
* 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() {
// Creates and uses the list (2,3,5).
var List v;
let v = List.new(5,null);
let v = List.new(2,List.new(3,v));
do v.print(); // prints 2 3 5
do v.dispose(); // disposes the list
return;
}

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;
}
}
45 changes: 34 additions & 11 deletions src/com/CompilationEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ private boolean parseStatement() throws ParserException, SemanticException, IOEx
returnsOnAllCodePaths = true;
break;
default:
throw new ParserException(token.lineNumber + "Expected statement. Got: " + token.lexeme);
throw new ParserException(token.lineNumber, "Expected statement. Got: " + token.lexeme);
}

return returnsOnAllCodePaths;
Expand Down Expand Up @@ -321,12 +321,20 @@ private void parseLetStatement() throws ParserException, SemanticException, IOEx
if (this.t.peekNextToken().lexeme.equals("[")) {
isArrayIdentifier = true;
this.t.getNextToken();

returnType = parseExpression();

if (!returnType.equals("int"))
throw new SemanticException(identifier.getLineNumber(), "Expression in array indices must always evaluate to an integer.");
this.w.writeLater("push " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getKind().toString() +
" " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getIndex());
this.w.writeLater("add");

//if (!returnType.equals("int"))
// throw new SemanticException(identifier.getLineNumber(), "Expression in array indices must always evaluate to an integer.");

parseSymbol("]");

// VM CODE
//
}


Expand All @@ -345,7 +353,11 @@ private void parseLetStatement() throws ParserException, SemanticException, IOEx
this.w.writeLater("pop " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getKind().toString() +
" " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getIndex());
} else {
this.w.writeLater("ARRAY CODE GOES HERE");
// VM CODE
this.w.writeLater("pop temp 0");
this.w.writeLater("pop pointer 1");
this.w.writeLater("push temp 0");
this.w.writeLater("pop that 0");
}

// the variable has now been initialized
Expand Down Expand Up @@ -502,8 +514,9 @@ public void parseSubroutineCall(Identifier identifier) throws ParserException, S
// if method invocation in the same class
int offset = 0;
if (identifier.getClassIdentifier().equals(this.globalSymbolTable.getName()) || identifier.getClassIdentifier().equals("")) {
this.w.writeLater("push pointer 0");
offset = 1;
//this.w.writeLater("push pointer 0");
//offset = 1;
// TODO tidy this up once working
} else {
// check to see if the first identifier needs to be pushed
if (identifier.getClassIdentifierSymbol() != null && this.currentSymbolTable.hierarchyContains(identifier.getClassIdentifierSymbol().getName())) {
Expand Down Expand Up @@ -759,6 +772,7 @@ private String parseOperand() throws ParserException, SemanticException, IOExcep
Identifier identifier = parseIdentifier();
type = identifier.getType();
boolean isSubroutineCall = false;
boolean isArray = false;

// VM CODE - Push identifiers
// we need to determine if a function call has been made or just push the identifier
Expand All @@ -771,20 +785,30 @@ private String parseOperand() throws ParserException, SemanticException, IOExcep
if (this.t.peekNextToken().lexeme.equals("[")) {
String returnType;
Token arrayIndexStart = this.t.getNextToken();
isArray = true;
returnType = parseExpression();

if (!returnType.equals("int"))
throw new SemanticException(arrayIndexStart.lineNumber, "Expression in array indices must always evaluate to an integer.");
this.w.writeLater("push " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getKind().toString() +
" " + this.currentSymbolTable.findHierarchySymbol(identifier.getIdentifier()).getIndex());
this.w.writeLater("add");

//if (!returnType.equals("int"))
// throw new SemanticException(arrayIndexStart.lineNumber, "Expression in array indices must always evaluate to an integer.");

parseSymbol("]");

// VM CODE
this.w.writeLater("pop pointer 1");
this.w.writeLater("push that 0");

type = "Array";
} else if (this.t.peekNextToken().lexeme.equals("(")) {
isSubroutineCall = true;
parseSubroutineCall(identifier);
}

// VM CODE
if (!isSubroutineCall) {
if (!isSubroutineCall && !isArray) {
// try to resolve the symbol based on it already being in the symbol table
if ((identifier.getClassIdentifier().equals("") || identifier.getClassIdentifier().equals(this.globalSymbolTable.getName()))
&& this.currentSymbolTable.hierarchyContains(identifier.getIdentifier())) {
Expand Down Expand Up @@ -929,7 +953,7 @@ private Identifier parseIdentifier(boolean declaredCheck, boolean initializedChe
if (declaredCheck)
throw new SemanticException(newScopedToken.lineNumber, "Identifier " + newScopedToken.lexeme + " used without previously declaring.");
else {
Identifier unresolvedIdentifier = new Identifier(this.globalSymbolTable.getName(), newToken.lexeme, newToken.lineNumber);
Identifier unresolvedIdentifier = new Identifier(this.globalSymbolTable.getName(), newScopedToken.lexeme, newScopedToken.lineNumber);
this.unresolvedIdentifiers.add(unresolvedIdentifier);
return unresolvedIdentifier;
}
Expand All @@ -951,7 +975,6 @@ private Identifier parseIdentifier(boolean declaredCheck, boolean initializedChe
if (declaredCheck)
throw new SemanticException(newScopedToken.lineNumber, "Identifier " + newScopedToken.lexeme + " used without previously declaring.");
else {
System.out.println("WE FOUNG" + newToken);
Identifier unresolvedIdentifier = new Identifier(this.currentSymbolTable.findHierarchySymbol(newToken.lexeme).getType(), newScopedToken.lexeme, newToken.lineNumber, null, this.currentSymbolTable.findHierarchySymbol(newToken.lexeme));
this.unresolvedIdentifiers.add(unresolvedIdentifier);
return unresolvedIdentifier;
Expand Down

0 comments on commit 3c71370

Please sign in to comment.