nand2tetris/vm/VMTranslator.php

75 lines
1.8 KiB
PHP
Raw Normal View History

2020-06-01 14:19:55 +00:00
<?php
namespace captn3m0\NandToTetris;
require_once("CommandType.php");
require_once("CodeWriter.php");
require_once("Parser.php");
2020-06-01 14:19:55 +00:00
class VMTranslator {
function __construct(String $fileOrDir ) {
if (is_dir($fileOrDir)) {
$this->files = glob("$fileOrDir/*.vm");
} else {
$this->files = [$fileOrDir];
}
foreach ($this->files as $file) {
assert(is_readable($file));
}
$outputFile = $this->outputFile();
$this->writer = new CodeWriter($outputFile);
}
function translate() {
foreach ($this->files as $file) {
$parser = new Parser($file);
$this->writer->setInputFileName($file);
2020-06-01 14:19:55 +00:00
foreach ($parser->commands() as $command) {
2020-06-01 14:26:37 +00:00
$commandType = CommandType::fromName($command);
switch ($commandType) {
2020-06-01 14:19:55 +00:00
case CommandType::ARITHMETIC:
$this->writer->writeArithmetic($command);
break;
case CommandType::PUSH:
case CommandType::POP:
$segment = $parser->arg1();
2020-06-01 14:26:37 +00:00
$index = intval($parser->arg2());
$this->writer->writePushPop($commandType, $segment, $index);
2020-06-01 14:19:55 +00:00
break;
case CommandType::LABEL:
$label = $parser->arg1();
$this->writer->writeLabel($label);
break;
case CommandType::IF:
$label = $parser->arg1();
$this->writer->writeIf($label);
break;
2020-06-01 14:19:55 +00:00
default:
2020-06-01 14:26:37 +00:00
throw new \Exception("Not Implemented $command", 1);
2020-06-01 14:19:55 +00:00
break;
}
$this->writer->nextSourceLine();
2020-06-01 14:19:55 +00:00
}
}
2020-06-01 18:40:15 +00:00
$this->writer->close();
2020-06-01 14:19:55 +00:00
}
private function outputFile() {
$dir = dirname($this->files[0]);
$name = basename($dir);
return "$dir/$name.asm";
2020-06-01 14:19:55 +00:00
}
}
if(isset($argv[1])) {
$vmt = new VMTranslator($argv[1]);
$vmt->translate();
}