[08] Implement Return/Function/Init

Return isn't functional (yet)
Init isn't called (yet)
This commit is contained in:
Nemo 2020-06-03 23:50:34 +05:30
parent 2fbdba0cf2
commit b052ab617c
6 changed files with 181 additions and 2 deletions

View File

@ -0,0 +1,98 @@
(SimpleFunction.test) // function SimpleFunction.test 2
@SP
A=M
M=D
@SP
M=M+1
@SP
A=M
M=D
@SP
M=M+1
@LCL
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push local 0 (L1)
@LCL // local 1
D=M
@1 // write 1 to A
D=D+A // D = segment+index
@R13 // save it to R13
M=D // write @LCL+1 to R13
@R13
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push local 1 (L2)
@SP // ==== add ====
A=M-1
D=M
A=A-1
M=D+M
@SP
M=M-1 // end add (L3)
@SP // ==== not ====
A=M-1
D=M
M=!M // end not (L4)
@ARG
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 0 (L5)
@SP // ==== add ====
A=M-1
D=M
A=A-1
M=D+M
@SP
M=M-1 // end add (L6)
@ARG // argument 1
D=M
@1 // write 1 to A
D=D+A // D = segment+index
@R13 // save it to R13
M=D // write @ARG+1 to R13
@R13
A=M
D=M
@SP
A=M
M=D
@SP
M=M+1 // end push argument 1 (L7)
@SP // ==== sub ====
A=M-1
D=M
A=A-1
M=M-D
@SP
M=M-1 // end sub (L8)
@ARG
D=M+1
@SP
M=D // @SP = ARG+1
@LCL
D=M // D=@LCL
@THAT
MD=D-1 // THAT = LCL-1
@THIS
MD=D-1 // THIS = LCL-2
@ARG
MD=D-1 // ARG = LCL-3
@LCL
MD=D-1 // LCL = LCL-4
A=D-1 // A = LCL-5
0;JMP // Jump to *(LCL-5)
@97
0;JMP

View File

@ -0,0 +1 @@
| RAM[0] | RAM[1] | RAM[2] | RAM[3] | RAM[4] |RAM[310]|

View File

@ -1,2 +0,0 @@
|RAM[3000]|RAM[3001]|RAM[3002]|RAM[3003]|RAM[3004]|RAM[3005]|
| 0 | 1 | 1 | 2 | 3 | 5 |

View File

@ -12,6 +12,68 @@ class CodeWriter {
$this->fn = null;
}
public function writeReturn() {
$this->write([
// SP=ARG+1
"@ARG",
"D=M+1",
"@SP",
"M=D // @SP = ARG+1",
// THAT = LCL-1
"@LCL",
"D=M // D=@LCL",
"@THAT",
"MD=D-1 // THAT = LCL-1",
// THIS = LCL-2
"@THIS",
"MD=D-1 // THIS = LCL-2",
// ARG = LCL-3
"@ARG",
"MD=D-1 // ARG = LCL-3",
// LCL = LCL-4
"@LCL",
"MD=D-1 // LCL = LCL-4",
"A=D-1 // A = LCL-5",
"0;JMP // Jump to *(LCL-5)",
]);
}
public function writeFunction($name, $numArgs) {
$this->fn = $name;
$this->write([
"($name) // function $name $numArgs",
]);
for($i=0;$i<$numArgs;$i++) {
$this->write([
"@SP",
"A=M",
"M=D",
"@SP",
"M=M+1"
]);
}
}
/**
* Writes the preable to initialize the VM
*/
private function writeInit() {
$this->write([
"@256",
"D=A",
"@SP",
"M=D // initialized SP to 256",
"@16000",
"D=A",
"@LCL",
"M=D // initialized @LCL to 16000",
"@16500",
"D=A",
"@ARG",
"M=D // initialized @ARG to 16500",
]);
}
function setInputFileName($inputFileName) {
$this->vm = basename($inputFileName, ".vm");
}

View File

@ -5,10 +5,12 @@ namespace captn3m0\NandToTetris;
class CommandType {
const PUSH = 1;
const POP = 2;
// Program Flow Commands
const LABEL= 3;
const GOTO= 4;
const IF= 5;
// Function Calling Commands
const FUNC= 6;
const RETURN= 7;

View File

@ -21,6 +21,10 @@ class VMTranslator {
$this->writer = new CodeWriter($outputFile);
}
/**
* This is the main entry point for the VM Translator
* and starts the translate sequence
*/
function translate() {
foreach ($this->files as $file) {
$parser = new Parser($file);
@ -55,6 +59,16 @@ class VMTranslator {
$this->writer->writeGoto($label);
break;
case CommandType::FUNC:
$functionName = $parser->arg1();
$numberOfArgs = $parser->arg2();
$this->writer->writeFunction($functionName, $numberOfArgs);
break;
case CommandType::RETURN:
$this->writer->writeReturn();
break;
default:
throw new \Exception("Not Implemented $command", 1);
break;
@ -66,6 +80,10 @@ class VMTranslator {
$this->writer->close();
}
/**
* Generates an output file name
* for the VM. Same as the Directory.asm
*/
private function outputFile() {
$dir = dirname($this->files[0]);
$name = basename($dir);