From 9760124dc7815fb90cc2e703e4b6738e95433273 Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Tue, 16 Apr 2024 19:22:09 +0100 Subject: [PATCH] Operators wip --- src/main.cpp => main.cpp | 11 +- src/code.h | 212 ------------------------------------- src/include/arithmetic.h | 101 ++++++++++++++++++ src/include/code.h | 77 ++++++++++++++ src/include/logical.h | 0 src/include/memory.h | 149 ++++++++++++++++++++++++++ src/{ => include}/parser.h | 0 src/include/types.h | 28 +++++ 8 files changed, 363 insertions(+), 215 deletions(-) rename src/main.cpp => main.cpp (75%) delete mode 100644 src/code.h create mode 100644 src/include/arithmetic.h create mode 100644 src/include/code.h create mode 100644 src/include/logical.h create mode 100644 src/include/memory.h rename src/{ => include}/parser.h (100%) create mode 100644 src/include/types.h diff --git a/src/main.cpp b/main.cpp similarity index 75% rename from src/main.cpp rename to main.cpp index 5f7ea6d..43345b0 100644 --- a/src/main.cpp +++ b/main.cpp @@ -1,18 +1,23 @@ #include #include -#include -#include +#include "include/parser.h" +#include "include/code.h" using namespace std; string constructTranslatedPath(string path) { size_t position = path.rfind(".vm"); - return path.replace(position, 3, ".hack"); + return path.replace(position, 3, ".asm"); } int main(int argc, char* argv[]) { + if (!argv[1]) { + cout << "You must specify a vm file path!" << endl; + return 1; + } + string sourcePath = argv[1]; if (!regex_match(sourcePath, regex("^.+\\.vm"))) { diff --git a/src/code.h b/src/code.h deleted file mode 100644 index 8aa4c23..0000000 --- a/src/code.h +++ /dev/null @@ -1,212 +0,0 @@ -#include -#include -#include - -using namespace std; - -enum Segment -{ - LCL, - ARG, - THIS, - THAT, - STATIC, - CONSTANT, - TEMP, -}; - -// TODO: Complete implementing these -// Memory access commands: push, pop -// Arithmetic commands: add, sub, neg -// Logical commands: eq, gt, lt, and, or, not - -class Code -{ -private: - ofstream file; - string filename; - vector> commands; - - Segment determineSegment(string segment) - { - if (segment == "local") - return Segment::LCL; - if (segment == "argument") - return Segment::ARG; - if (segment == "this") - return Segment::THIS; - if (segment == "that") - return Segment::THAT; - if (segment == "static") - return Segment::STATIC; - if (segment == "temp") - return Segment::TEMP; - if (segment == "constant") - return Segment::CONSTANT; - - return Segment::CONSTANT; - } - - string translatePush(Segment segment, int index) - { - stringstream output; - - switch (segment) - { - case LCL: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@LCL" << endl; - output << "A=D+A" << endl; - output << "D=M" << endl; - break; - case ARG: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@ARG" << endl; - output << "A=D+A" << endl; - output << "D=M" << endl; - break; - case THIS: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@THIS" << endl; - output << "A=D+A" << endl; - output << "D=M" << endl; - break; - case THAT: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@THAT" << endl; - output << "A=D+A" << endl; - output << "D=M" << endl; - break; - case STATIC: - output << "@" << filename << "." << index << endl; - output << "D=M" << endl; - break; - case TEMP: - output << "@" << index + 5 << endl; - output << "D=M" << endl; - break; - case CONSTANT: - default: - output << '@' << index << endl; - output << "D=A" << endl; - break; - } - - output << "@SP" << endl; - output << "A=M" << endl; - output << "M=D" << endl; - output << "@SP" << endl; - output << "M=M+1" << endl; - - return output.str(); - }; - - string translatePop(Segment segment, int index) - { - stringstream output; - - switch (segment) - { - case LCL: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@LCL" << endl; - output << "D=D+A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - case ARG: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@ARG" << endl; - output << "D=D+A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - case THIS: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@THIS" << endl; - output << "D=D+A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - case THAT: - output << "@" << index << endl; - output << "D=A" << endl; - output << "@THAT" << endl; - output << "D=D+A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - case STATIC: - output << "@" << filename << "." << index << endl; - output << "D=A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - case TEMP: - output << "@" << index + 5 << endl; - output << "D=A" << endl; - output << "@ADDR" << endl; - output << "M=D" << endl; - break; - - default: - break; - } - - output << "@SP" << endl; - output << "M=M-1" << endl; - output << "A=M" << endl; - output << "D=M" << endl; - output << "@ADDR" << endl; - output << "A=M" << endl; - output << "M=D" << endl; - - return output.str(); - }; - -public: - Code(string path, vector> tokens) - { - size_t slashIndex = path.find_last_of('/'); - size_t dotIndex = path.find_last_of('.'); - - if (slashIndex != string::npos && dotIndex != string::npos) - { - filename = path.substr(slashIndex + 1, dotIndex - slashIndex - 1); - } - - file = ofstream(path); - commands = tokens; - } - - void translate() - { - for (const auto &vec : commands) - { - if (vec.size() > 1) - { - if (vec[0] == "push") - { - file << translatePush(determineSegment(vec[1]), stoi(vec[2])); - } - else - { - file << translatePop(determineSegment(vec[1]), stoi(vec[2])); - } - } - file << endl; - } - } - - void closeFile() - { - file.close(); - } -}; diff --git a/src/include/arithmetic.h b/src/include/arithmetic.h new file mode 100644 index 0000000..b8cc3ac --- /dev/null +++ b/src/include/arithmetic.h @@ -0,0 +1,101 @@ +#include +#include +#include + +using namespace std; + +ArithmeticOperator determineArithmeticOperator(string arithmeticOperator) +{ + if (arithmeticOperator == "add") + return ArithmeticOperator::ADD; + if (arithmeticOperator == "sub") + return ArithmeticOperator::SUB; + if (arithmeticOperator == "neg") + return ArithmeticOperator::NEG; + + return ArithmeticOperator::NEG; +} + +string translateAdd() +{ + stringstream output; + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + + output << "@R" << endl; + output << "M=D" << endl; + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + + output << "@R" << endl; + output << "M=D+M" << endl; + output << "D=M" << endl; + + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + + return output.str(); +} + +string translateSub() +{ + stringstream output; + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + + output << "@R" << endl; + output << "M=D" << endl; + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + + output << "@R" << endl; + output << "M=D-M" << endl; + output << "D=M" << endl; + + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + + return output.str(); +} + +string translateNeg() +{ + stringstream output; + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + + output << "@R" << endl; + output << "M=D" << endl; + output << "M=M-D" << endl; + output << "M=M-D" << endl; + output << "D=M" << endl; + + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + + return output.str(); +} \ No newline at end of file diff --git a/src/include/code.h b/src/include/code.h new file mode 100644 index 0000000..f820b86 --- /dev/null +++ b/src/include/code.h @@ -0,0 +1,77 @@ +#include +#include +#include +#include "types.h" +#include "memory.h" +#include "arithmetic.h" + +using namespace std; + +class Code +{ +private: + ofstream file; + string filename; + vector> commands; + +public: + Code(string path, vector> tokens) + { + size_t slashIndex = path.find_last_of('/'); + size_t dotIndex = path.find_last_of('.'); + + if (slashIndex != string::npos && dotIndex != string::npos) + { + filename = path.substr(slashIndex + 1, dotIndex - slashIndex - 1); + } + + file = ofstream(path); + commands = tokens; + } + + void translate() + { + for (const auto &vec : commands) + { + if (vec.size() > 1) + { + if (vec[0] == "push") + { + file << translatePush(filename, determineSegment(vec[1]), stoi(vec[2])); + } + else + { + file << translatePop(filename, determineSegment(vec[1]), stoi(vec[2])); + } + } + + if (vec.size() == 1) + { + int op = determineArithmeticOperator(vec[0]); + + cout << op << " " << vec[0] << endl; + + switch (determineArithmeticOperator(vec[0])) + { + case ArithmeticOperator::ADD: + file << translateAdd(); + break; + case ArithmeticOperator::SUB: + file << translateSub(); + break; + case ArithmeticOperator::NEG: + default: + file << translateNeg(); + break; + } + } + + file << endl; + } + } + + void closeFile() + { + file.close(); + } +}; diff --git a/src/include/logical.h b/src/include/logical.h new file mode 100644 index 0000000..e69de29 diff --git a/src/include/memory.h b/src/include/memory.h new file mode 100644 index 0000000..106862f --- /dev/null +++ b/src/include/memory.h @@ -0,0 +1,149 @@ +#include +#include +#include + +using namespace std; + +Segment determineSegment(string segment) +{ + if (segment == "local") + return Segment::LCL; + if (segment == "argument") + return Segment::ARG; + if (segment == "this") + return Segment::THIS; + if (segment == "that") + return Segment::THAT; + if (segment == "static") + return Segment::STATIC; + if (segment == "temp") + return Segment::TEMP; + if (segment == "constant") + return Segment::CONSTANT; + + return Segment::CONSTANT; +} + +string translatePush(string filename, Segment segment, int index) +{ + stringstream output; + + switch (segment) + { + case LCL: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@LCL" << endl; + output << "A=D+A" << endl; + output << "D=M" << endl; + break; + case ARG: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@ARG" << endl; + output << "A=D+A" << endl; + output << "D=M" << endl; + break; + case THIS: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@THIS" << endl; + output << "A=D+A" << endl; + output << "D=M" << endl; + break; + case THAT: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@THAT" << endl; + output << "A=D+A" << endl; + output << "D=M" << endl; + break; + case STATIC: + output << "@" << filename << "." << index << endl; + output << "D=M" << endl; + break; + case TEMP: + output << "@" << index + 5 << endl; + output << "D=M" << endl; + break; + case CONSTANT: + default: + output << '@' << index << endl; + output << "D=A" << endl; + break; + } + + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + + return output.str(); +}; + +string translatePop(string filename, Segment segment, int index) +{ + stringstream output; + + switch (segment) + { + case LCL: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@LCL" << endl; + output << "D=D+A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + case ARG: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@ARG" << endl; + output << "D=D+A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + case THIS: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@THIS" << endl; + output << "D=D+A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + case THAT: + output << "@" << index << endl; + output << "D=A" << endl; + output << "@THAT" << endl; + output << "D=D+A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + case STATIC: + output << "@" << filename << "." << index << endl; + output << "D=A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + case TEMP: + output << "@" << index + 5 << endl; + output << "D=A" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + break; + + default: + break; + } + + output << "@SP" << endl; + output << "M=M-1" << endl; + output << "A=M" << endl; + output << "D=M" << endl; + output << "@ADDR" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + + return output.str(); +}; \ No newline at end of file diff --git a/src/parser.h b/src/include/parser.h similarity index 100% rename from src/parser.h rename to src/include/parser.h diff --git a/src/include/types.h b/src/include/types.h new file mode 100644 index 0000000..48d15db --- /dev/null +++ b/src/include/types.h @@ -0,0 +1,28 @@ +enum Segment +{ + LCL, + ARG, + THIS, + THAT, + STATIC, + CONSTANT, + TEMP, +}; + +enum ArithmeticOperator { + ADD, + SUB, + NEG +}; + +enum ComparisonOperator { + EQ, + GT, + LT, +}; + +enum LogicalOperator { + AND, + OR, + NOT +}; \ No newline at end of file