From e0ef0a98503569849a70ace2b5a9bbc82fbc168a Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Mon, 6 May 2024 18:36:25 +0100 Subject: [PATCH] Handle function commands --- include/code.h | 1 + include/functions.h | 139 +++++++++++++++++++++++++++++++++++++++++++ include/memory.h | 22 ------- include/operations.h | 6 +- include/types.h | 7 ++- include/utils.h | 32 +++++++++- 6 files changed, 178 insertions(+), 29 deletions(-) create mode 100644 include/functions.h diff --git a/include/code.h b/include/code.h index 55ded5f..7c0c924 100644 --- a/include/code.h +++ b/include/code.h @@ -6,6 +6,7 @@ #include "operations.h" #include "memory.h" #include "branching.h" +#include "functions.h" using namespace std; diff --git a/include/functions.h b/include/functions.h new file mode 100644 index 0000000..94afaa0 --- /dev/null +++ b/include/functions.h @@ -0,0 +1,139 @@ +#include +#include +#include + +using namespace std; + +string translateFunction(string name, int args) { + stringstream output; + + output << "(" << name << ")" << endl; + + for (int i = 0; i < args; ++i) { + output << "@0" << endl; + output << "D=A" << endl; + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + } + + return output.str(); +} + +string translateCall(string name, int args) { + stringstream output; + string label = name + "$ret" + generateRandomLabel(3); + vector frame = { "LCL", "ARG", "THIS", "THAT" }; + + output << "@" << label << endl; + output << "D=A" << endl; + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + + for (const string &segment : frame) { + output << "@" << segment << endl; + output << "D=M" << endl; + output << "@SP" << endl; + output << "A=M" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "M=M+1" << endl; + } + + output << "@SP" << endl; + output << "D=M" << endl; + output << "@LCL" << endl; + output << "M=D" << endl; + output << "@SP" << endl; + output << "D=M" << endl; + output << "@R" << endl; + output << "M=D" << endl; + output << "@5" << endl; + output << "D=A" << endl; + output << "@R" << endl; + output << "M=M-D" << endl; + output << "@" << args << endl; + output << "D=A" << endl; + output << "@R" << endl; + output << "M=M-D" << endl; + output << "D=M" << endl; + output << "@ARG" << endl; + output << "M=D" << endl; + output << "@R" << endl; + + output << "@" << name << endl; + output << "0;JMP" << endl; + output << "(" << label << ")" << endl; + + return output.str(); +} + +string translateReturn() { + stringstream output; + + output << "@LCL" << endl; + output << "D=A" << endl; + output << "@END_FRAME" << endl; + output << "M=D" << endl; + output << "@RETURN_ADDR" << endl; + output << "M=D" << endl; + output << "@5" << endl; + output << "D=A" << endl; + output << "@RETURN_ADDR" << endl; + output << "M=M-D" << endl; + + output << "@ARG" << endl; + output << "D=M" << endl; + output << "@ADDR" << endl; + output << "M=D" << endl; + 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; + + output << "@ARG" << endl; + output << "D=M+1" << endl; + output << "@SP" << endl; + output << "M=D" << endl; + + output << "@END_FRAME" << endl; + output << "D=M" << endl; + output << "@1" << endl; + output << "D=D-A" << endl; + output << "@THAT" << endl; + output << "M=D" << endl; + + output << "@END_FRAME" << endl; + output << "D=M" << endl; + output << "@2" << endl; + output << "D=D-A" << endl; + output << "@THIS" << endl; + output << "M=D" << endl; + + output << "@END_FRAME" << endl; + output << "D=M" << endl; + output << "@3" << endl; + output << "D=D-A" << endl; + output << "@ARG" << endl; + output << "M=D" << endl; + + output << "@END_FRAME" << endl; + output << "D=M" << endl; + output << "@4" << endl; + output << "D=D-A" << endl; + output << "@LCL" << endl; + output << "M=D" << endl; + + output << "@RETURN_ADDR" << endl; + output << "0;JMP" << endl; + + return output.str(); +} \ No newline at end of file diff --git a/include/memory.h b/include/memory.h index 6dd6bb7..50845ca 100644 --- a/include/memory.h +++ b/include/memory.h @@ -4,28 +4,6 @@ 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 == "pointer") - return Segment::POINTER; - 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; diff --git a/include/operations.h b/include/operations.h index acd70e4..0d3a9dd 100644 --- a/include/operations.h +++ b/include/operations.h @@ -95,7 +95,7 @@ string translateEq() srand(static_cast(time(nullptr))); - string LABEL = generateRandomLabel(); + string LABEL = generateRandomLabel(8); output << "@SP" << endl; output << "M=M-1" << endl; @@ -147,7 +147,7 @@ string translateGt() srand(static_cast(time(nullptr))); - string LABEL = generateRandomLabel(); + string LABEL = generateRandomLabel(8); output << "@SP" << endl; output << "M=M-1" << endl; @@ -201,7 +201,7 @@ string translateLt() srand(static_cast(time(nullptr))); - string LABEL = generateRandomLabel(); + string LABEL = generateRandomLabel(8); output << "@SP" << endl; output << "M=M-1" << endl; diff --git a/include/types.h b/include/types.h index 205f2a5..7c613f8 100644 --- a/include/types.h +++ b/include/types.h @@ -21,7 +21,8 @@ enum NoArgumentCommand { LT, AND, OR, - NOT + NOT, + RETURN, }; enum OneArgumentCommand { @@ -32,5 +33,7 @@ enum OneArgumentCommand { enum TwoArgumentCommand { PUSH, - POP + POP, + FUNCTION, + CALL }; diff --git a/include/utils.h b/include/utils.h index bddcd6d..8c9cacc 100644 --- a/include/utils.h +++ b/include/utils.h @@ -24,13 +24,35 @@ inline void trim(string &str) { ltrim(str); } -string generateRandomLabel() { +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 == "pointer") + return Segment::POINTER; + if (segment == "static") + return Segment::STATIC; + if (segment == "temp") + return Segment::TEMP; + if (segment == "constant") + return Segment::CONSTANT; + + return Segment::CONSTANT; +} + +string generateRandomLabel(int length) { random_device rd; mt19937 gen(rd()); uniform_int_distribution<> dis('A', 'Z'); string label; - for (int i = 0; i < 8; ++i) { + for (int i = 0; i < length; ++i) { label += static_cast(dis(gen)); } @@ -57,6 +79,8 @@ NoArgumentCommand determineNoArgumentCommand(string command) return NoArgumentCommand::OR; if (command == "not") return NoArgumentCommand::NOT; + if (command == "return") + return NoArgumentCommand::RETURN; return NoArgumentCommand::NEG; } @@ -79,6 +103,10 @@ TwoArgumentCommand determineTwoArgumentCommand(string command) return TwoArgumentCommand::PUSH; if (command == "pop") return TwoArgumentCommand::POP; + if (command == "function") + return TwoArgumentCommand::FUNCTION; + if (command == "call") + return TwoArgumentCommand::CALL; return TwoArgumentCommand::POP; }