mirror of
https://github.com/usatiuk/nand2tetris.git
synced 2025-10-29 00:27:49 +01:00
move interesting projects to the root
This commit is contained in:
0
VMTranslator/.asm
Normal file
0
VMTranslator/.asm
Normal file
6
VMTranslator/.clang-format
Normal file
6
VMTranslator/.clang-format
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
...
|
||||
|
||||
4
VMTranslator/.gitignore
vendored
Normal file
4
VMTranslator/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
build/
|
||||
*.kdev4
|
||||
.kdev4/
|
||||
.history
|
||||
18
VMTranslator/.vscode/c_cpp_properties.json
vendored
Normal file
18
VMTranslator/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"/usr/include/c++/9/**",
|
||||
"/usr/include/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "${default}"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
45
VMTranslator/.vscode/settings.json
vendored
Normal file
45
VMTranslator/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"utility": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"ctime": "cpp",
|
||||
"deque": "cpp",
|
||||
"functional": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ratio": "cpp",
|
||||
"filesystem": "cpp"
|
||||
}
|
||||
}
|
||||
8
VMTranslator/CMakeLists.txt
Normal file
8
VMTranslator/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(VMTranslator)
|
||||
add_executable(VMTranslator main.cpp Parser.cpp Writer.cpp Commands.cpp)
|
||||
|
||||
set_property(TARGET VMTranslator PROPERTY CXX_STANDARD 14)
|
||||
install(TARGETS VMTranslator RUNTIME DESTINATION bin)
|
||||
target_link_libraries(${PROJECT_NAME} stdc++fs)
|
||||
35
VMTranslator/Commands.cpp
Normal file
35
VMTranslator/Commands.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "Commands.h"
|
||||
|
||||
std::unordered_map<std::string, CommandType> CommandTypeDict = {
|
||||
{"", CommandType::Empty},
|
||||
{"push", CommandType::Push},
|
||||
{"pop", CommandType::Pop},
|
||||
{"add", CommandType::Add},
|
||||
{"sub", CommandType::Sub},
|
||||
{"neg", CommandType::Neg},
|
||||
{"eq", CommandType::Eq},
|
||||
{"gt", CommandType::Gt},
|
||||
{"lt", CommandType::Lt},
|
||||
{"and", CommandType::And},
|
||||
{"or", CommandType::Or},
|
||||
{"not", CommandType::Not},
|
||||
{"label", CommandType::Label},
|
||||
{"if-goto", CommandType::IfGoto},
|
||||
{"goto", CommandType::Goto},
|
||||
{"call", CommandType::Call},
|
||||
{"function", CommandType::Function},
|
||||
{"return", CommandType::Return},
|
||||
};
|
||||
|
||||
std::unordered_map<CommandType, std::string> TypeCommandDict = []() {
|
||||
std::unordered_map<CommandType, std::string> rev;
|
||||
for (auto &cmd : CommandTypeDict) {
|
||||
rev[cmd.second] = cmd.first;
|
||||
}
|
||||
return rev;
|
||||
}();
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Command &cmd) {
|
||||
os << TypeCommandDict[cmd.type] << " " << cmd.arg1 << " " << cmd.arg2;
|
||||
return os;
|
||||
}
|
||||
49
VMTranslator/Commands.h
Normal file
49
VMTranslator/Commands.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
enum class CommandType {
|
||||
Add,
|
||||
Sub,
|
||||
Neg,
|
||||
Eq,
|
||||
Gt,
|
||||
Lt,
|
||||
And,
|
||||
Or,
|
||||
Not,
|
||||
Push,
|
||||
Pop,
|
||||
Label,
|
||||
IfGoto,
|
||||
Goto,
|
||||
If,
|
||||
Function,
|
||||
Call,
|
||||
Return,
|
||||
All,
|
||||
Empty
|
||||
};
|
||||
|
||||
extern std::unordered_map<std::string, CommandType> CommandTypeDict;
|
||||
extern std::unordered_map<CommandType, std::string> TypeCommandDict;
|
||||
|
||||
struct Command {
|
||||
CommandType type = CommandType::Empty;
|
||||
std::string arg1 = "";
|
||||
int arg2 = 0;
|
||||
|
||||
Command() {}
|
||||
Command(CommandType type) : type(type) {}
|
||||
Command(CommandType type, std::string arg1, int arg2 = 0)
|
||||
: type(type), arg1(arg1), arg2(arg2) {}
|
||||
|
||||
inline bool isEmpty() { return type == CommandType::Empty; }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Command &cmd);
|
||||
};
|
||||
|
||||
#endif // COMMANDS_H
|
||||
54
VMTranslator/Parser.cpp
Normal file
54
VMTranslator/Parser.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "Parser.h"
|
||||
|
||||
Parser::Parser(std::string file) {
|
||||
infile.open(file);
|
||||
if (!infile.is_open()) {
|
||||
throw std::invalid_argument("Input file doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::close() { infile.close(); }
|
||||
|
||||
bool Parser::more() { return infile.good(); }
|
||||
|
||||
Command Parser::next() {
|
||||
std::string line;
|
||||
std::getline(infile, line);
|
||||
|
||||
while ((line.substr(0, 2) == "//" || line.empty() ||
|
||||
(line[line.length() - 1] == '\r' && line.length() <= 1)) &&
|
||||
infile.good()) {
|
||||
std::getline(infile, line);
|
||||
}
|
||||
|
||||
if (line.length() > 1 && line[line.length() - 1] == '\r') {
|
||||
line = line.substr(0, line.length() - 1);
|
||||
}
|
||||
|
||||
if (line.length() == 0) {
|
||||
return Command(CommandType::Empty);
|
||||
}
|
||||
|
||||
std::istringstream ss(line);
|
||||
std::string word;
|
||||
Command cmd;
|
||||
int n = 0;
|
||||
|
||||
while (ss >> word) {
|
||||
if(word == "//") {
|
||||
break;
|
||||
}
|
||||
if (n == 0) {
|
||||
cmd.type = CommandTypeDict[word];
|
||||
} else if (n == 1) {
|
||||
cmd.arg1 = word;
|
||||
} else if (n == 2) {
|
||||
cmd.arg2 = std::stoi(word);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
23
VMTranslator/Parser.h
Normal file
23
VMTranslator/Parser.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "Commands.h"
|
||||
|
||||
class Parser {
|
||||
private:
|
||||
std::ifstream infile;
|
||||
|
||||
public:
|
||||
Parser(std::string file);
|
||||
void close();
|
||||
bool more();
|
||||
Command next();
|
||||
};
|
||||
|
||||
#endif // PARSER_H
|
||||
BIN
VMTranslator/VMTranslator
Normal file
BIN
VMTranslator/VMTranslator
Normal file
Binary file not shown.
469
VMTranslator/Writer.cpp
Normal file
469
VMTranslator/Writer.cpp
Normal file
@@ -0,0 +1,469 @@
|
||||
#include "Writer.h"
|
||||
|
||||
Writer::Writer(std::string file) {
|
||||
filename = getFileName(file);
|
||||
classname = getClassName(filename);
|
||||
|
||||
outfile.open(file, std::ios::out | std::ios::trunc);
|
||||
if (!outfile.is_open()) {
|
||||
throw std::invalid_argument("Can't open output file");
|
||||
}
|
||||
}
|
||||
|
||||
std::string Writer::getFileName(std::string path) {
|
||||
int slashPos = path.rfind("/");
|
||||
return path.substr(slashPos + 1, path.length());
|
||||
}
|
||||
|
||||
std::string Writer::getClassName(std::string filename) {
|
||||
int dotPos = filename.rfind(".");
|
||||
return filename.substr(0, dotPos);
|
||||
}
|
||||
|
||||
void Writer::setFile(std::string path) {
|
||||
filename = getFileName(path);
|
||||
classname = getClassName(filename);
|
||||
}
|
||||
|
||||
void Writer::close() { outfile.close(); }
|
||||
|
||||
void Writer::writeFunction(Command cmd) {
|
||||
outfile << "(" << cmd.arg1 << ")" << std::endl;
|
||||
for (int i = 0; i < cmd.arg2; i++) {
|
||||
writeCmd(Command(CommandType::Push, "constant", 0));
|
||||
}
|
||||
|
||||
functionName = cmd.arg1;
|
||||
retCounter = 0;
|
||||
}
|
||||
|
||||
void Writer::writeCall(Command cmd) {
|
||||
std::string retLabel = functionName + "$ret." + std::to_string(retCounter);
|
||||
// push retAdress
|
||||
outfile << "@" << retLabel << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
|
||||
outfile << "@THIS" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
|
||||
outfile << "@THAT" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@" << 5 + cmd.arg2 << std::endl;
|
||||
outfile << "D=D-A" << std::endl;
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
outfile << "@" << cmd.arg1 << std::endl;
|
||||
outfile << "-1;JMP" << std::endl;
|
||||
|
||||
outfile << "(" << retLabel << ")" << std::endl;
|
||||
retCounter++;
|
||||
}
|
||||
|
||||
void Writer::writeReturn(Command cmd) {
|
||||
// endFrame(R13)=LCL
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// retAddr(R14)=*(endFrame-5)
|
||||
outfile << "@5" << std::endl;
|
||||
outfile << "A=D-A" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
//*ARG = pop()
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// SP = ARG+1
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "D=M+1" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// that =*(endFrame-1)
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@1" << std::endl;
|
||||
outfile << "A=D-A" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@THAT" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// this=*(endFrame-2)
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@2" << std::endl;
|
||||
outfile << "A=D-A" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@THIS" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// ARG=*(endFrame-3)
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@3" << std::endl;
|
||||
outfile << "A=D-A" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
// LCL=*(endFrame-4)
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@4" << std::endl;
|
||||
outfile << "A=D-A" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "0;JMP" << std::endl;
|
||||
}
|
||||
|
||||
void Writer::writeCmd(Command cmd) {
|
||||
outfile << "// " << cmd << std::endl;
|
||||
switch (cmd.type) {
|
||||
case CommandType::Empty:
|
||||
break;
|
||||
case CommandType::Add:
|
||||
case CommandType::Sub:
|
||||
case CommandType::Neg:
|
||||
case CommandType::Eq:
|
||||
case CommandType::Gt:
|
||||
case CommandType::Lt:
|
||||
case CommandType::And:
|
||||
case CommandType::Or:
|
||||
case CommandType::Not:
|
||||
writeArith(cmd);
|
||||
break;
|
||||
case CommandType::Push:
|
||||
case CommandType::Pop:
|
||||
writePushPop(cmd);
|
||||
break;
|
||||
case CommandType::IfGoto:
|
||||
case CommandType::Goto:
|
||||
case CommandType::Label:
|
||||
writeBranch(cmd);
|
||||
break;
|
||||
case CommandType::Function:
|
||||
writeFunction(cmd);
|
||||
break;
|
||||
case CommandType::Call:
|
||||
writeCall(cmd);
|
||||
break;
|
||||
case CommandType::Return:
|
||||
writeReturn(cmd);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Writer::writeBranch(Command cmd) {
|
||||
switch (cmd.type) {
|
||||
case CommandType::IfGoto:
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@" << functionName << "$" << cmd.arg1 << std::endl;
|
||||
outfile << "D;JNE" << std::endl;
|
||||
break;
|
||||
case CommandType::Goto:
|
||||
outfile << "@" << functionName << "$" << cmd.arg1 << std::endl;
|
||||
outfile << "-1;JMP" << std::endl;
|
||||
break;
|
||||
case CommandType::Label:
|
||||
outfile << "(" << functionName << "$" << cmd.arg1 << ")"
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Writer::writeInit() {
|
||||
outfile << "@256" << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
writeCmd(Command(CommandType::Call, "Sys.init", 0));
|
||||
}
|
||||
|
||||
void Writer::writeArith(Command cmd) {
|
||||
static int arithCounter = 0;
|
||||
if (cmd.type != CommandType::Neg && cmd.type != CommandType::Not) {
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "M=0" << std::endl;
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
}
|
||||
|
||||
switch (cmd.type) {
|
||||
case CommandType::Add:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M+D" << std::endl;
|
||||
break;
|
||||
case CommandType::Sub:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M-D" << std::endl;
|
||||
break;
|
||||
case CommandType::Neg:
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=-M" << std::endl;
|
||||
break;
|
||||
case CommandType::Not:
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=!M" << std::endl;
|
||||
break;
|
||||
|
||||
case CommandType::Eq:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M-D" << std::endl;
|
||||
outfile << "@T" << arithCounter << std::endl;
|
||||
outfile << "D;JEQ" << std::endl;
|
||||
outfile << "@END" << arithCounter << std::endl;
|
||||
outfile << "D=0;JMP" << std::endl;
|
||||
outfile << "(T" << arithCounter << ")" << std::endl;
|
||||
outfile << "D=-1" << std::endl;
|
||||
break;
|
||||
case CommandType::Gt:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M-D" << std::endl;
|
||||
outfile << "@T" << arithCounter << std::endl;
|
||||
outfile << "D;JGT" << std::endl;
|
||||
outfile << "@END" << arithCounter << std::endl;
|
||||
outfile << "D=0;JMP" << std::endl;
|
||||
outfile << "(T" << arithCounter << ")" << std::endl;
|
||||
outfile << "D=-1" << std::endl;
|
||||
break;
|
||||
case CommandType::Lt:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M-D" << std::endl;
|
||||
outfile << "@T" << arithCounter << std::endl;
|
||||
outfile << "D;JLT" << std::endl;
|
||||
outfile << "@END" << arithCounter << std::endl;
|
||||
outfile << "D=0;JMP" << std::endl;
|
||||
outfile << "(T" << arithCounter << ")" << std::endl;
|
||||
outfile << "D=-1" << std::endl;
|
||||
break;
|
||||
case CommandType::And:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M&D" << std::endl;
|
||||
break;
|
||||
case CommandType::Or:
|
||||
outfile << "@R13" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M|D" << std::endl;
|
||||
break;
|
||||
}
|
||||
outfile << "(END" << arithCounter << ")" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
arithCounter++;
|
||||
return;
|
||||
}
|
||||
|
||||
void Writer::writePushPop(Command cmd) {
|
||||
switch (cmd.type) {
|
||||
case CommandType::Push:
|
||||
if (cmd.arg1 == "constant") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
} else if (cmd.arg1 == "local") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "A=M+D" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "argument") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "A=M+D" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "this") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@THIS" << std::endl;
|
||||
outfile << "A=M+D" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "that") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@THAT" << std::endl;
|
||||
outfile << "A=M+D" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "static") {
|
||||
outfile << "@" << classname << "." << cmd.arg2 << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "temp") {
|
||||
outfile << "@R" << 5 + cmd.arg2 << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
} else if (cmd.arg1 == "pointer") {
|
||||
if (cmd.arg2 == 0) {
|
||||
outfile << "@THIS" << std::endl;
|
||||
} else if (cmd.arg2 == 1) {
|
||||
outfile << "@THAT" << std::endl;
|
||||
}
|
||||
outfile << "D=M" << std::endl;
|
||||
}
|
||||
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M+1" << std::endl;
|
||||
break;
|
||||
case CommandType::Pop:
|
||||
outfile << "@SP" << std::endl;
|
||||
outfile << "M=M-1" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
|
||||
if (cmd.arg1 == "local") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@LCL" << std::endl;
|
||||
outfile << "D=M+D" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "argument") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@ARG" << std::endl;
|
||||
outfile << "D=M+D" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "this") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@THIS" << std::endl;
|
||||
outfile << "D=M+D" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "that") {
|
||||
outfile << "@" << cmd.arg2 << std::endl;
|
||||
outfile << "D=A" << std::endl;
|
||||
outfile << "@THAT" << std::endl;
|
||||
outfile << "D=M+D" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
outfile << "@R14" << std::endl;
|
||||
outfile << "D=M" << std::endl;
|
||||
outfile << "@R15" << std::endl;
|
||||
outfile << "A=M" << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "static") {
|
||||
outfile << "@" << classname << "." << cmd.arg2 << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "temp") {
|
||||
outfile << "@R" << 5 + cmd.arg2 << std::endl;
|
||||
outfile << "M=D" << std::endl;
|
||||
} else if (cmd.arg1 == "pointer") {
|
||||
if (cmd.arg2 == 0) {
|
||||
outfile << "@THIS" << std::endl;
|
||||
} else if (cmd.arg2 == 1) {
|
||||
outfile << "@THAT" << std::endl;
|
||||
}
|
||||
outfile << "M=D" << std::endl;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
37
VMTranslator/Writer.h
Normal file
37
VMTranslator/Writer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef WRITER_H
|
||||
#define WRITER_H
|
||||
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <experimental/filesystem>
|
||||
|
||||
#include "Commands.h"
|
||||
class Writer {
|
||||
private:
|
||||
std::ofstream outfile;
|
||||
void writeArith(Command cmd);
|
||||
void writePushPop(Command cmd);
|
||||
void writeBranch(Command cmd);
|
||||
void writeCall(Command cmd);
|
||||
void writeFunction(Command cmd);
|
||||
void writeReturn(Command cmd);
|
||||
|
||||
std::string getFileName(std::string path);
|
||||
std::string getClassName(std::string filename);
|
||||
std::string filename;
|
||||
std::string classname;
|
||||
|
||||
std::string functionName;
|
||||
int retCounter = 0;
|
||||
|
||||
public:
|
||||
Writer(std::string file);
|
||||
void setFile(std::string filename);
|
||||
void close();
|
||||
void writeCmd(Command cmd);
|
||||
void writeInit();
|
||||
};
|
||||
|
||||
#endif // WRITER_H
|
||||
1
VMTranslator/lang.txt
Normal file
1
VMTranslator/lang.txt
Normal file
@@ -0,0 +1 @@
|
||||
debug
|
||||
79
VMTranslator/main.cpp
Normal file
79
VMTranslator/main.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <exception>
|
||||
#include <experimental/filesystem>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Parser.h"
|
||||
#include "Writer.h"
|
||||
|
||||
Parser *parser;
|
||||
Writer *writer;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2) {
|
||||
std::cout << "Not enough arguments" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string inpath(argv[1]);
|
||||
bool shouldWriteInit = false;
|
||||
std::string indir;
|
||||
std::vector<std::string> infiles;
|
||||
std::string outfile;
|
||||
|
||||
if (std::experimental::filesystem::is_directory(inpath)) {
|
||||
if (inpath[inpath.length()] == '/') {
|
||||
inpath = inpath.substr(0, inpath.length() - 1);
|
||||
}
|
||||
int slashPos = inpath.rfind("/");
|
||||
indir = inpath.substr(slashPos + 1, inpath.length());
|
||||
outfile = inpath + "/" + indir + ".asm";
|
||||
|
||||
for (auto &f :
|
||||
std::experimental::filesystem::directory_iterator(inpath)) {
|
||||
if (std::experimental::filesystem::is_regular_file(
|
||||
f.path().string())) {
|
||||
if (f.path().extension() == ".vm") {
|
||||
infiles.push_back(f.path().string());
|
||||
}
|
||||
}
|
||||
}
|
||||
shouldWriteInit = true;
|
||||
} else if (std::experimental::filesystem::is_regular_file(inpath)) {
|
||||
int dotPos = inpath.rfind(".");
|
||||
outfile = inpath.substr(0, dotPos);
|
||||
outfile += ".asm";
|
||||
|
||||
infiles.push_back(inpath);
|
||||
} else {
|
||||
std::cout << "Input file doesn't exist" << std::endl;
|
||||
}
|
||||
|
||||
try {
|
||||
writer = new Writer(outfile);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (shouldWriteInit) {
|
||||
writer->writeInit();
|
||||
}
|
||||
|
||||
for (auto &f : infiles) {
|
||||
parser = new Parser(f);
|
||||
writer->setFile(f);
|
||||
while (parser->more()) {
|
||||
Command cmd;
|
||||
cmd = parser->next();
|
||||
writer->writeCmd(cmd);
|
||||
}
|
||||
parser->close();
|
||||
delete parser;
|
||||
}
|
||||
|
||||
writer->close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
VMTranslator/project7.zip
Normal file
BIN
VMTranslator/project7.zip
Normal file
Binary file not shown.
BIN
VMTranslator/project8.zip
Normal file
BIN
VMTranslator/project8.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user