Re: how to print vm commands in correct order
Posted by
cadet1620 on
URL: http://nand2tetris-questions-and-answers-forum.52.s1.nabble.com/how-to-print-vm-commands-in-correct-order-tp4030962p4030963.html
kraftwerk1611 wrote
A problem that I am having when writing to a vm file is that in order to write 'function x nLocals' command, you need to know the number of local variables for that function.
However by the time I have this information the vm code for subroutine body has already been written to the vm file. If I print the 'function x nLocals' now then it ends up at the end of file.
What you need to so is write the
function VM command immediately after compiling the <u>
varDec</u>, before compiling the <u>
statements</u>. At this point, the functions variables have been added to the aymbol table and SymbolTable.varCount(VAR) will return the required argument for the
function VM command.
void compileSubroutine() {
...
compileParameterList();
...
vmWriter.writeFunction(name, localsize);
compileSubroutineBody();
}
Same happens with other vm commands of seven.jack file, which are appearing in reverse order for me like the following
This sounds strange. compileStatements() should be something very simple like
void compileStatements () {
// Compiles <statement-list> := <statement> *
//
// ENTRY: Tokenizer positioned on the first statement.
// EXIT: Tokenizer positioned after the final statement.
//
// All commands start with a keyword
while (tokenizer.tokenType() == TK_KEYWORD) {
compileStatement();
}
}
void compileStatement () {
// Compiles <statement> := <let-statement> | <if-statement> |
// <while-statement> | <do-statement> | <return-statement>
//
// ENTRY: Tokenizer positioned on the statement.
// EXIT: Tokenizer positioned after the statement.
switch (tokenizer.keyword()) {
case TK_LET:
compileLet();
break;
...
}
}
}
Also to generate vm code for expressions like (1+(2*3)), is it so that one has to know about two or three next tokens?
This sort of expression will be handled without any lookahead required by compileExpression() calling compileTerm() which will recursively call compileExpression(), which will ...
There is no lookahead required except for in compileSubroutineCall() which needs to look ahead one token to differentiate between
identifier(...)
and
identifier.identifier(...)
--Mark