summaryrefslogtreecommitdiffhomepage
path: root/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc')
-rw-r--r--dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc1854
1 files changed, 856 insertions, 998 deletions
diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
index c053920..66cf859 100644
--- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
+++ b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc
@@ -14,8 +14,10 @@
#define kExitOK (EXIT_SUCCESS)
#define kExitNO (EXIT_FAILURE)
-#define kSplashCxx() \
- kPrintF(kWhite "%s\n", "NeKernel Optimized C++ Compiler Driver, (c) 2024-2025 Amlal El Mahrouss, All rights reserved.")
+#define kSplashCxx() \
+ kPrintF(kWhite "%s\n", \
+ "NeKernel Optimized C++ Compiler Driver, (c) 2024-2025 Amlal El Mahrouss, All rights " \
+ "reserved.")
// extern_segment, @autodelete { ... }, fn foo() -> auto { ... }
@@ -42,7 +44,7 @@
///////////////////////
#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
+#define kRed "\e[0;31m"
#define kWhite "\e[0;97m"
/////////////////////////////////////
@@ -52,80 +54,68 @@
/////////////////////////////////////
/// @internal
-namespace Detail
-{
- std::filesystem::path expand_home(const std::filesystem::path& p)
- {
- if (!p.empty() && p.string()[0] == '~')
- {
- const char* home = std::getenv("HOME"); // For Unix-like systems
- if (!home)
- {
- home = std::getenv("USERPROFILE"); // For Windows
- }
- if (home)
- {
- return std::filesystem::path(home) / p.relative_path().string().substr(1);
- }
- else
- {
- throw std::runtime_error("Home directory not found in environment variables");
- }
- }
- return p;
- }
-
- struct CompilerRegisterMap final
- {
- std::string fName;
- std::string fReg;
- };
-
- // \brief Offset based struct/class
- struct CompilerStructMap final
- {
- std::string fName;
- std::string fReg;
-
- // offset counter
- std::size_t fOffsetsCnt;
-
- // offset array
- std::vector<std::pair<Int32, std::string>> fOffsets;
- };
-
- struct CompilerState final
- {
- std::vector<CompilerRegisterMap> fStackMapVector;
- std::vector<CompilerStructMap> fStructMapVector;
- LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
- std::unique_ptr<std::ofstream> fOutputAssembly;
- std::string fLastFile;
- std::string fLastError;
- Boolean fVerbose;
- };
-} // namespace Detail
+namespace Detail {
+std::filesystem::path expand_home(const std::filesystem::path& p) {
+ if (!p.empty() && p.string()[0] == '~') {
+ const char* home = std::getenv("HOME"); // For Unix-like systems
+ if (!home) {
+ home = std::getenv("USERPROFILE"); // For Windows
+ }
+ if (home) {
+ return std::filesystem::path(home) / p.relative_path().string().substr(1);
+ } else {
+ throw std::runtime_error("Home directory not found in environment variables");
+ }
+ }
+ return p;
+}
+
+struct CompilerRegisterMap final {
+ std::string fName;
+ std::string fReg;
+};
+
+// \brief Offset based struct/class
+struct CompilerStructMap final {
+ std::string fName;
+ std::string fReg;
+
+ // offset counter
+ std::size_t fOffsetsCnt;
+
+ // offset array
+ std::vector<std::pair<Int32, std::string>> fOffsets;
+};
+
+struct CompilerState final {
+ std::vector<CompilerRegisterMap> fStackMapVector;
+ std::vector<CompilerStructMap> fStructMapVector;
+ LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ Boolean fVerbose;
+};
+} // namespace Detail
static Detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
+static SizeType kErrorLimit = 100;
static Int32 kOnClassScope = 0;
static Int32 kAcceptableErrors = 0;
-namespace Detail
-{
- /// @brief prints an error into stdout.
- /// @param reason the reason of the error.
- /// @param file where does it originate from?
- void print_error(std::string reason, std::string file) noexcept;
+namespace Detail {
+/// @brief prints an error into stdout.
+/// @param reason the reason of the error.
+/// @param file where does it originate from?
+void print_error(std::string reason, std::string file) noexcept;
- struct CompilerType final
- {
- std::string fName;
- std::string fValue;
- };
-} // namespace Detail
+struct CompilerType final {
+ std::string fName;
+ std::string fValue;
+};
+} // namespace Detail
/////////////////////////////////////////////////////////////////////////////////////////
@@ -138,10 +128,10 @@ static int kMachine = LibCompiler::AssemblyFactory::kArchAMD64;
/////////////////////////////////////////
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 8;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 8;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
static std::vector<LibCompiler::CompilerKeyword> kKeywords;
/////////////////////////////////////////
@@ -150,26 +140,25 @@ static std::vector<LibCompiler::CompilerKeyword> kKeywords;
/////////////////////////////////////////
-static std::vector<std::string> kFileList;
+static std::vector<std::string> kFileList;
static LibCompiler::AssemblyFactory kFactory;
-static Boolean kInStruct = false;
-static Boolean kOnWhileLoop = false;
-static Boolean kOnForLoop = false;
-static Boolean kInBraces = false;
-static size_t kBracesCount = 0UL;
+static Boolean kInStruct = false;
+static Boolean kOnWhileLoop = false;
+static Boolean kOnForLoop = false;
+static Boolean kInBraces = false;
+static size_t kBracesCount = 0UL;
/* @brief C++ compiler backend for the NE C++ driver */
-class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend
-{
-public:
- explicit CompilerFrontendCPlusPlus() = default;
- ~CompilerFrontendCPlusPlus() override = default;
+class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend {
+ public:
+ explicit CompilerFrontendCPlusPlus() = default;
+ ~CompilerFrontendCPlusPlus() override = default;
- LIBCOMPILER_COPY_DEFAULT(CompilerFrontendCPlusPlus);
+ LIBCOMPILER_COPY_DEFAULT(CompilerFrontendCPlusPlus);
- Boolean Compile(const std::string text, const std::string file) override;
+ Boolean Compile(const std::string text, const std::string file) override;
- const char* Language() override;
+ const char* Language() override;
};
/// @internal compiler variables
@@ -179,40 +168,21 @@ static CompilerFrontendCPlusPlus* kCompilerFrontend = nullptr;
static std::vector<std::string> kRegisterMap;
static std::vector<std::string> kRegisterList = {
- "rbx",
- "rsi",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
- "xmm12",
- "xmm13",
- "xmm14",
- "xmm15",
+ "rbx", "rsi", "r10", "r11", "r12", "r13", "r14", "r15", "xmm12", "xmm13", "xmm14", "xmm15",
};
/// @brief The PEF calling convention (caller must save rax, rbp)
/// @note callee must return via **rax**.
static std::vector<std::string> kRegisterConventionCallList = {
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
};
static std::size_t kFunctionEmbedLevel = 0UL;
/// detail namespaces
-const char* CompilerFrontendCPlusPlus::Language()
-{
- return "NeKernel C++";
+const char* CompilerFrontendCPlusPlus::Language() {
+ return "NeKernel C++";
}
static std::uintptr_t kOrigin = 0x1000000;
@@ -226,645 +196,553 @@ std::vector<std::pair<std::string, std::uintptr_t>> kOriginMap;
/////////////////////////////////////////////////////////////////////////////////////////
-Boolean CompilerFrontendCPlusPlus::Compile(std::string text,
- const std::string file)
-{
- if (text.empty())
- return true;
-
- // Clean whitespace and tabs
- std::string cleanLine = text;
- cleanLine.erase(std::remove(cleanLine.begin(), cleanLine.end(), '\t'), cleanLine.end());
- cleanLine.erase(0, cleanLine.find_first_not_of(" \r\n"));
- cleanLine.erase(cleanLine.find_last_not_of(" \r\n") + 1);
-
- // Skip empty, doc, or block comment lines
- if (cleanLine.empty() || cleanLine.starts_with("///") || cleanLine.starts_with("//") || cleanLine.starts_with("/*"))
- return true;
-
- std::size_t index = 0UL;
- std::vector<std::pair<LibCompiler::CompilerKeyword, std::size_t>> keywords_list;
-
- Boolean found = false;
- static Boolean commentBlock = false;
-
- for (auto& keyword : kKeywords)
- {
- if (text.find(keyword.keyword_name) != std::string::npos)
- {
- switch (keyword.keyword_kind)
- {
- case LibCompiler::kKeywordKindCommentMultiLineStart: {
- commentBlock = true;
- return true;
- }
- case LibCompiler::kKeywordKindCommentMultiLineEnd: {
- commentBlock = false;
- break;
- }
- case LibCompiler::kKeywordKindCommentInline: {
- break;
- }
- default:
- break;
- }
-
- if (text[text.find(keyword.keyword_name) - 1] == '+' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- if (text[text.find(keyword.keyword_name) - 1] == '-' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- if (text[text.find(keyword.keyword_name) + 1] == '=' &&
- keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- continue;
-
- keywords_list.emplace_back(std::make_pair(keyword, index));
- ++index;
-
- found = true;
- }
- }
-
- if (!found && !commentBlock)
- {
- for (size_t i = 0; i < text.size(); i++)
- {
- if (isalnum(text[i]))
- {
- Detail::print_error("syntax error: " + text, file);
- return false;
- }
- }
- }
-
- for (auto& keyword : keywords_list)
- {
- auto syntax_tree = LibCompiler::SyntaxLeafList::SyntaxLeaf();
-
- switch (keyword.first.keyword_kind)
- {
- case LibCompiler::KeywordKind::kKeywordKindClass: {
- ++kOnClassScope;
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindIf: {
- auto expr = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1, text.find(")") - 1);
-
- if (expr.find(">=") != std::string::npos)
- {
- auto left = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2, expr.find("<=") + strlen("<="));
- auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1);
-
- size_t i = right.size() - 1;
-
- try
- {
- while (!std::isalnum(right[i]))
- {
- right.erase(i, 1);
- --i;
- }
-
- right.erase(0, i);
- }
- catch (...)
- {
- right.erase(0, i);
- }
-
- i = left.size() - 1;
- try
- {
- while (!std::isalnum(left[i]))
- {
- left.erase(i, 1);
- --i;
- }
-
- left.erase(0, i);
- }
- catch (...)
- {
- left.erase(0, i);
- }
-
- if (!isdigit(left[0]) ||
- !isdigit(right[0]))
- {
- auto indexRight = 0UL;
-
- auto& valueOfVar = !isdigit(left[0]) ? left : right;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != valueOfVar)
- {
-
- auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
-
- syntax_tree.fUserValue += "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
- syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + "," + kRegisterList[indexRight + 1] + "\n";
-
- goto done_iterarting_on_if;
- }
-
- auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
-
- syntax_tree.fUserValue += "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
- syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " + kRegisterList[indexRight + 1] + "\n";
-
- break;
- }
- }
-
- done_iterarting_on_if:
-
- std::string fnName = text;
- fnName.erase(fnName.find(keyword.first.keyword_name));
-
- for (auto& ch : fnName)
- {
- if (ch == ' ')
- ch = '_';
- }
-
- syntax_tree.fUserValue += "jge __OFFSET_ON_TRUE_LC\nsegment .code64 __OFFSET_ON_TRUE_LC:\n";
- }
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindFunctionStart: {
- for (auto& ch : text)
- {
- if (isdigit(ch))
- {
- goto dont_accept;
- }
- }
-
- goto accept;
-
- dont_accept:
- return false;
-
- accept:
- std::string fnName = text;
- size_t indexFnName = 0;
-
- // this one is for the type.
- for (auto& ch : text)
- {
- ++indexFnName;
-
- if (ch == '\t')
- break;
-
- if (ch == ' ')
- break;
- }
-
- fnName = text.substr(indexFnName);
-
- if (text.find("return ") != std::string::npos)
- {
- text.erase(0, text.find("return "));
- break;
- }
-
- if (text.ends_with(";") && text.find("return") == std::string::npos)
- goto LC_write_assembly;
- else if (text.size() <= indexFnName)
- Detail::print_error("Invalid function name: " + fnName, file);
-
- indexFnName = 0;
-
- for (auto& ch : fnName)
- {
- if (ch == ' ' ||
- ch == '\t')
- {
- if (fnName[indexFnName - 1] != ')')
- Detail::print_error("Invalid function name: " + fnName, file);
-
- if ((indexFnName + 1) != fnName.size())
- Detail::print_error("Extra characters after function name: " + fnName, file);
- }
-
- ++indexFnName;
- }
-
- syntax_tree.fUserValue = "public_segment .code64 __LIBCOMPILER_" + fnName + "\n";
- ++kFunctionEmbedLevel;
-
- kOriginMap.push_back({"__LIBCOMPILER_" + fnName, kOrigin});
-
- break;
-
- LC_write_assembly:
- auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(), [&fnName](std::pair<std::string, std::uintptr_t> pair) -> bool {
- return fnName == pair.first;
- });
-
- std::stringstream ss;
- ss << std::hex << it->second;
-
- if (it != kOriginMap.end())
- {
- syntax_tree.fUserValue = "jmp " + ss.str() + "\n";
- kOrigin += 1UL;
- }
- }
- case LibCompiler::KeywordKind::kKeywordKindFunctionEnd: {
- if (kOnClassScope)
- --kOnClassScope;
-
- if (text.ends_with(";"))
- break;
-
- --kFunctionEmbedLevel;
-
- if (kRegisterMap.size() > kRegisterList.size())
- {
- --kFunctionEmbedLevel;
- }
-
- if (kFunctionEmbedLevel < 1)
- kRegisterMap.clear();
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindEndInstr:
- case LibCompiler::KeywordKind::kKeywordKindVariableInc:
- case LibCompiler::KeywordKind::kKeywordKindVariableDec:
- case LibCompiler::KeywordKind::kKeywordKindVariableAssign: {
- std::string valueOfVar = "";
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- valueOfVar = text.substr(text.find("+=") + 2);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- valueOfVar = text.substr(text.find("-=") + 2);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- {
- valueOfVar = text.substr(text.find("=") + 1);
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- break;
- }
-
- while (valueOfVar.find(";") != std::string::npos &&
- keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- valueOfVar.erase(valueOfVar.find(";"));
- }
-
- std::string varName = text;
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- varName.erase(varName.find("+="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- varName.erase(varName.find("-="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
- {
- varName.erase(varName.find("="));
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- varName.erase(varName.find(";"));
- }
-
- static Boolean typeFound = false;
-
- for (auto& keyword : kKeywords)
- {
- if (keyword.keyword_kind == LibCompiler::kKeywordKindType)
- {
- if (text.find(keyword.keyword_name) != std::string::npos)
- {
- if (text[text.find(keyword.keyword_name)] == ' ')
- {
- typeFound = false;
- continue;
- }
-
- typeFound = true;
- }
- }
- }
-
- std::string instr = "mov ";
-
- if (typeFound && keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc &&
- keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- if (kRegisterMap.size() > kRegisterList.size())
- {
- ++kFunctionEmbedLevel;
- }
-
- while (varName.find(" ") != std::string::npos)
- {
- varName.erase(varName.find(" "), 1);
- }
-
- while (varName.find("\t") != std::string::npos)
- {
- varName.erase(varName.find("\t"), 1);
- }
-
- for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
- {
- if (i > valueOfVar.size())
- break;
-
- valueOfVar.erase(i, 1);
- }
-
- constexpr auto cTrueVal = "true";
- constexpr auto cFalseVal = "false";
-
- if (valueOfVar == cTrueVal)
- {
- valueOfVar = "1";
- }
- else if (valueOfVar == cFalseVal)
- {
- valueOfVar = "0";
- }
-
- std::size_t indexRight = 0UL;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != valueOfVar)
- {
- if (valueOfVar[0] == '\"')
- {
-
- syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + ": db " + valueOfVar + ", 0\n\n";
- syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size() - 1] + ", " + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
- kOrigin += 1UL;
- }
- else
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- }
-
- goto done;
- }
- }
-
- if (((int)indexRight - 1) < 0)
- {
- if (valueOfVar[0] == '\"')
- {
-
- syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + ": db " + valueOfVar + ", 0\n";
- syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size()] + ", " + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
- kOrigin += 1UL;
- }
- else
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- }
-
- goto done;
- }
-
- if (valueOfVar[0] != '\"' &&
- valueOfVar[0] != '\'' &&
- !isdigit(valueOfVar[0]))
- {
- for (auto pair : kRegisterMap)
- {
- if (pair == valueOfVar)
- goto done;
- }
-
- Detail::print_error("Variable not declared: " + varName, file);
- return false;
- }
-
- done:
- for (auto& keyword : kKeywords)
- {
- if (keyword.keyword_kind == LibCompiler::kKeywordKindType &&
- varName.find(keyword.keyword_name) != std::string::npos)
- {
- varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size());
- break;
- }
- }
-
- kRegisterMap.push_back(varName);
-
- break;
- }
-
- if (kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType ||
- kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindTypePtr)
- {
- syntax_tree.fUserValue = "\n";
- continue;
- }
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr)
- {
- syntax_tree.fUserValue = "\n";
- continue;
- }
-
- if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc)
- {
- instr = "add ";
- }
- else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableDec)
- {
- instr = "sub ";
- }
-
- std::string varErrCpy = varName;
-
- while (varName.find(" ") != std::string::npos)
- {
- varName.erase(varName.find(" "), 1);
- }
-
- while (varName.find("\t") != std::string::npos)
- {
- varName.erase(varName.find("\t"), 1);
- }
-
- std::size_t indxReg = 0UL;
-
- for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
- {
- if (i > valueOfVar.size())
- break;
-
- valueOfVar.erase(i, 1);
- }
-
- while (valueOfVar.find(" ") != std::string::npos)
- {
- valueOfVar.erase(valueOfVar.find(" "), 1);
- }
-
- while (valueOfVar.find("\t") != std::string::npos)
- {
- valueOfVar.erase(valueOfVar.find("\t"), 1);
- }
-
- constexpr auto cTrueVal = "true";
- constexpr auto cFalseVal = "false";
-
- /// interpet boolean values, since we're on C++
-
- if (valueOfVar == cTrueVal)
- {
- valueOfVar = "1";
- }
- else if (valueOfVar == cFalseVal)
- {
- valueOfVar = "0";
- }
-
- for (auto pair : kRegisterMap)
- {
- ++indxReg;
-
- if (pair != varName)
- continue;
-
- std::size_t indexRight = 0ul;
-
- for (auto pairRight : kRegisterMap)
- {
- ++indexRight;
-
- if (pairRight != varName)
- {
- syntax_tree.fUserValue = instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- continue;
- }
-
- syntax_tree.fUserValue = instr + kRegisterList[indexRight - 1] + ", " + valueOfVar + "\n";
- kOrigin += 1UL;
- break;
- }
-
- break;
- }
-
- if (syntax_tree.fUserValue.empty())
- {
- Detail::print_error("Variable not declared: " + varName, file);
- }
-
- break;
- }
- case LibCompiler::KeywordKind::kKeywordKindReturn: {
- try
- {
- auto pos = text.find("return") + strlen("return") + 1;
- std::string subText = text.substr(pos);
- subText = subText.erase(subText.find(";"));
- size_t indxReg = 0UL;
-
- if (subText[0] != '\"' &&
- subText[0] != '\'')
- {
- if (!isdigit(subText[0]))
- {
- for (auto pair : kRegisterMap)
- {
- ++indxReg;
-
- if (pair != subText)
- continue;
-
- syntax_tree.fUserValue = "mov rax, " + kRegisterList[indxReg - 1] + "\nret\n";
- kOrigin += 1UL;
-
- break;
- }
- }
- else
- {
- syntax_tree.fUserValue = "mov rax, " + subText + "\nret\n";
- kOrigin += 1UL;
-
- break;
- }
- }
- else
- {
- syntax_tree.fUserValue = "__LIBCOMPILER_LOCAL_RETURN_STRING: db " + subText + ", 0\nmov rcx, __LIBCOMPILER_LOCAL_RETURN_STRING\n";
- syntax_tree.fUserValue += "mov rax, rcx\nret\n";
- kOrigin += 1UL;
-
- break;
- }
-
- if (syntax_tree.fUserValue.empty())
- {
- if (subText.find("(") != std::string::npos)
- {
- subText.erase(subText.find("("));
-
- auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(), [&subText](std::pair<std::string, std::uintptr_t> pair) -> bool {
- return pair.first.find(subText) != std::string::npos;
- });
-
- if (it == kOriginMap.end())
- Detail::print_error("Invalid return value: " + subText, file);
-
- std::stringstream ss;
- ss << it->second;
-
- syntax_tree.fUserValue = "jmp " + ss.str() + "\nret\n";
- kOrigin += 1UL;
- break;
- }
- }
-
- break;
- }
- catch (...)
- {
- syntax_tree.fUserValue = "ret\n";
- kOrigin += 1UL;
- }
- }
- default: {
- break;
- }
- }
-
- syntax_tree.fUserData = keyword.first;
- kState.fSyntaxTree->fLeafList.push_back(syntax_tree);
- }
+Boolean CompilerFrontendCPlusPlus::Compile(std::string text, const std::string file) {
+ if (text.empty()) return true;
+
+ // Clean whitespace and tabs
+ std::string cleanLine = text;
+ cleanLine.erase(std::remove(cleanLine.begin(), cleanLine.end(), '\t'), cleanLine.end());
+ cleanLine.erase(0, cleanLine.find_first_not_of(" \r\n"));
+ cleanLine.erase(cleanLine.find_last_not_of(" \r\n") + 1);
+
+ // Skip empty, doc, or block comment lines
+ if (cleanLine.empty() || cleanLine.starts_with("///") || cleanLine.starts_with("//") ||
+ cleanLine.starts_with("/*"))
+ return true;
+
+ std::size_t index = 0UL;
+ std::vector<std::pair<LibCompiler::CompilerKeyword, std::size_t>> keywords_list;
+
+ Boolean found = false;
+ static Boolean commentBlock = false;
+
+ for (auto& keyword : kKeywords) {
+ if (text.find(keyword.keyword_name) != std::string::npos) {
+ switch (keyword.keyword_kind) {
+ case LibCompiler::kKeywordKindCommentMultiLineStart: {
+ commentBlock = true;
+ return true;
+ }
+ case LibCompiler::kKeywordKindCommentMultiLineEnd: {
+ commentBlock = false;
+ break;
+ }
+ case LibCompiler::kKeywordKindCommentInline: {
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (text[text.find(keyword.keyword_name) - 1] == '+' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) - 1] == '-' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) + 1] == '=' &&
+ keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign)
+ continue;
+
+ keywords_list.emplace_back(std::make_pair(keyword, index));
+ ++index;
+
+ found = true;
+ }
+ }
+
+ if (!found && !commentBlock) {
+ for (size_t i = 0; i < text.size(); i++) {
+ if (isalnum(text[i])) {
+ Detail::print_error("syntax error: " + text, file);
+ return false;
+ }
+ }
+ }
+
+ for (auto& keyword : keywords_list) {
+ auto syntax_tree = LibCompiler::SyntaxLeafList::SyntaxLeaf();
+
+ switch (keyword.first.keyword_kind) {
+ case LibCompiler::KeywordKind::kKeywordKindClass: {
+ ++kOnClassScope;
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindIf: {
+ auto expr = text.substr(
+ text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1,
+ text.find(")") - 1);
+
+ if (expr.find(">=") != std::string::npos) {
+ auto left = text.substr(
+ text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2,
+ expr.find("<=") + strlen("<="));
+ auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1);
+
+ size_t i = right.size() - 1;
+
+ try {
+ while (!std::isalnum(right[i])) {
+ right.erase(i, 1);
+ --i;
+ }
+
+ right.erase(0, i);
+ } catch (...) {
+ right.erase(0, i);
+ }
+
+ i = left.size() - 1;
+ try {
+ while (!std::isalnum(left[i])) {
+ left.erase(i, 1);
+ --i;
+ }
+
+ left.erase(0, i);
+ } catch (...) {
+ left.erase(0, i);
+ }
+
+ if (!isdigit(left[0]) || !isdigit(right[0])) {
+ auto indexRight = 0UL;
+
+ auto& valueOfVar = !isdigit(left[0]) ? left : right;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != valueOfVar) {
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue +=
+ "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+ syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + "," +
+ kRegisterList[indexRight + 1] + "\n";
+
+ goto done_iterarting_on_if;
+ }
+
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue +=
+ "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+ syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " +
+ kRegisterList[indexRight + 1] + "\n";
+
+ break;
+ }
+ }
+
+ done_iterarting_on_if:
+
+ std::string fnName = text;
+ fnName.erase(fnName.find(keyword.first.keyword_name));
+
+ for (auto& ch : fnName) {
+ if (ch == ' ') ch = '_';
+ }
+
+ syntax_tree.fUserValue +=
+ "jge __OFFSET_ON_TRUE_LC\nsegment .code64 __OFFSET_ON_TRUE_LC:\n";
+ }
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindFunctionStart: {
+ for (auto& ch : text) {
+ if (isdigit(ch)) {
+ goto dont_accept;
+ }
+ }
+
+ goto accept;
+
+ dont_accept:
+ return false;
+
+ accept:
+ std::string fnName = text;
+ size_t indexFnName = 0;
+
+ // this one is for the type.
+ for (auto& ch : text) {
+ ++indexFnName;
+
+ if (ch == '\t') break;
+
+ if (ch == ' ') break;
+ }
+
+ fnName = text.substr(indexFnName);
+
+ if (text.find("return ") != std::string::npos) {
+ text.erase(0, text.find("return "));
+ break;
+ }
+
+ if (text.ends_with(";") && text.find("return") == std::string::npos)
+ goto LC_write_assembly;
+ else if (text.size() <= indexFnName)
+ Detail::print_error("Invalid function name: " + fnName, file);
+
+ indexFnName = 0;
+
+ for (auto& ch : fnName) {
+ if (ch == ' ' || ch == '\t') {
+ if (fnName[indexFnName - 1] != ')')
+ Detail::print_error("Invalid function name: " + fnName, file);
+
+ if ((indexFnName + 1) != fnName.size())
+ Detail::print_error("Extra characters after function name: " + fnName, file);
+ }
+
+ ++indexFnName;
+ }
+
+ syntax_tree.fUserValue = "public_segment .code64 __LIBCOMPILER_" + fnName + "\n";
+ ++kFunctionEmbedLevel;
+
+ kOriginMap.push_back({"__LIBCOMPILER_" + fnName, kOrigin});
+
+ break;
+
+ LC_write_assembly:
+ auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(),
+ [&fnName](std::pair<std::string, std::uintptr_t> pair) -> bool {
+ return fnName == pair.first;
+ });
+
+ std::stringstream ss;
+ ss << std::hex << it->second;
+
+ if (it != kOriginMap.end()) {
+ syntax_tree.fUserValue = "jmp " + ss.str() + "\n";
+ kOrigin += 1UL;
+ }
+ }
+ case LibCompiler::KeywordKind::kKeywordKindFunctionEnd: {
+ if (kOnClassScope) --kOnClassScope;
+
+ if (text.ends_with(";")) break;
+
+ --kFunctionEmbedLevel;
+
+ if (kRegisterMap.size() > kRegisterList.size()) {
+ --kFunctionEmbedLevel;
+ }
+
+ if (kFunctionEmbedLevel < 1) kRegisterMap.clear();
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindEndInstr:
+ case LibCompiler::KeywordKind::kKeywordKindVariableInc:
+ case LibCompiler::KeywordKind::kKeywordKindVariableDec:
+ case LibCompiler::KeywordKind::kKeywordKindVariableAssign: {
+ std::string valueOfVar = "";
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ valueOfVar = text.substr(text.find("+=") + 2);
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ valueOfVar = text.substr(text.find("-=") + 2);
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableAssign) {
+ valueOfVar = text.substr(text.find("=") + 1);
+ } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ break;
+ }
+
+ while (valueOfVar.find(";") != std::string::npos &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ valueOfVar.erase(valueOfVar.find(";"));
+ }
+
+ std::string varName = text;
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ varName.erase(varName.find("+="));
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ varName.erase(varName.find("-="));
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableAssign) {
+ varName.erase(varName.find("="));
+ } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ varName.erase(varName.find(";"));
+ }
+
+ static Boolean typeFound = false;
+
+ for (auto& keyword : kKeywords) {
+ if (keyword.keyword_kind == LibCompiler::kKeywordKindType) {
+ if (text.find(keyword.keyword_name) != std::string::npos) {
+ if (text[text.find(keyword.keyword_name)] == ' ') {
+ typeFound = false;
+ continue;
+ }
+
+ typeFound = true;
+ }
+ }
+ }
+
+ std::string instr = "mov ";
+
+ if (typeFound &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc &&
+ keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ if (kRegisterMap.size() > kRegisterList.size()) {
+ ++kFunctionEmbedLevel;
+ }
+
+ while (varName.find(" ") != std::string::npos) {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos) {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++) {
+ if (i > valueOfVar.size()) break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ if (valueOfVar == cTrueVal) {
+ valueOfVar = "1";
+ } else if (valueOfVar == cFalseVal) {
+ valueOfVar = "0";
+ }
+
+ std::size_t indexRight = 0UL;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != valueOfVar) {
+ if (valueOfVar[0] == '\"') {
+ syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName +
+ ": db " + valueOfVar + ", 0\n\n";
+ syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size() - 1] + ", " +
+ "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
+ kOrigin += 1UL;
+ } else {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ }
+
+ goto done;
+ }
+ }
+
+ if (((int) indexRight - 1) < 0) {
+ if (valueOfVar[0] == '\"') {
+ syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName +
+ ": db " + valueOfVar + ", 0\n";
+ syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size()] + ", " +
+ "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n";
+ kOrigin += 1UL;
+ } else {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ }
+
+ goto done;
+ }
+
+ if (valueOfVar[0] != '\"' && valueOfVar[0] != '\'' && !isdigit(valueOfVar[0])) {
+ for (auto pair : kRegisterMap) {
+ if (pair == valueOfVar) goto done;
+ }
+
+ Detail::print_error("Variable not declared: " + varName, file);
+ return false;
+ }
+
+ done:
+ for (auto& keyword : kKeywords) {
+ if (keyword.keyword_kind == LibCompiler::kKeywordKindType &&
+ varName.find(keyword.keyword_name) != std::string::npos) {
+ varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size());
+ break;
+ }
+ }
+
+ kRegisterMap.push_back(varName);
+
+ break;
+ }
+
+ if (kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType ||
+ kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindTypePtr) {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) {
+ instr = "add ";
+ } else if (keyword.first.keyword_kind ==
+ LibCompiler::KeywordKind::kKeywordKindVariableDec) {
+ instr = "sub ";
+ }
+
+ std::string varErrCpy = varName;
+
+ while (varName.find(" ") != std::string::npos) {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos) {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ std::size_t indxReg = 0UL;
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++) {
+ if (i > valueOfVar.size()) break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ while (valueOfVar.find(" ") != std::string::npos) {
+ valueOfVar.erase(valueOfVar.find(" "), 1);
+ }
+
+ while (valueOfVar.find("\t") != std::string::npos) {
+ valueOfVar.erase(valueOfVar.find("\t"), 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ /// interpet boolean values, since we're on C++
+
+ if (valueOfVar == cTrueVal) {
+ valueOfVar = "1";
+ } else if (valueOfVar == cFalseVal) {
+ valueOfVar = "0";
+ }
+
+ for (auto pair : kRegisterMap) {
+ ++indxReg;
+
+ if (pair != varName) continue;
+
+ std::size_t indexRight = 0ul;
+
+ for (auto pairRight : kRegisterMap) {
+ ++indexRight;
+
+ if (pairRight != varName) {
+ syntax_tree.fUserValue =
+ instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ continue;
+ }
+
+ syntax_tree.fUserValue =
+ instr + kRegisterList[indexRight - 1] + ", " + valueOfVar + "\n";
+ kOrigin += 1UL;
+ break;
+ }
+
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty()) {
+ Detail::print_error("Variable not declared: " + varName, file);
+ }
+
+ break;
+ }
+ case LibCompiler::KeywordKind::kKeywordKindReturn: {
+ try {
+ auto pos = text.find("return") + strlen("return") + 1;
+ std::string subText = text.substr(pos);
+ subText = subText.erase(subText.find(";"));
+ size_t indxReg = 0UL;
+
+ if (subText[0] != '\"' && subText[0] != '\'') {
+ if (!isdigit(subText[0])) {
+ for (auto pair : kRegisterMap) {
+ ++indxReg;
+
+ if (pair != subText) continue;
+
+ syntax_tree.fUserValue = "mov rax, " + kRegisterList[indxReg - 1] + "\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+ } else {
+ syntax_tree.fUserValue = "mov rax, " + subText + "\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+ } else {
+ syntax_tree.fUserValue = "__LIBCOMPILER_LOCAL_RETURN_STRING: db " + subText +
+ ", 0\nmov rcx, __LIBCOMPILER_LOCAL_RETURN_STRING\n";
+ syntax_tree.fUserValue += "mov rax, rcx\nret\n";
+ kOrigin += 1UL;
+
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty()) {
+ if (subText.find("(") != std::string::npos) {
+ subText.erase(subText.find("("));
+
+ auto it =
+ std::find_if(kOriginMap.begin(), kOriginMap.end(),
+ [&subText](std::pair<std::string, std::uintptr_t> pair) -> bool {
+ return pair.first.find(subText) != std::string::npos;
+ });
+
+ if (it == kOriginMap.end())
+ Detail::print_error("Invalid return value: " + subText, file);
+
+ std::stringstream ss;
+ ss << it->second;
+
+ syntax_tree.fUserValue = "jmp " + ss.str() + "\nret\n";
+ kOrigin += 1UL;
+ break;
+ }
+ }
+
+ break;
+ } catch (...) {
+ syntax_tree.fUserValue = "ret\n";
+ kOrigin += 1UL;
+ }
+ }
+ default: {
+ break;
+ }
+ }
+
+ syntax_tree.fUserData = keyword.first;
+ kState.fSyntaxTree->fLeafList.push_back(syntax_tree);
+ }
lc_compile_ok:
- return true;
+ return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -875,295 +753,275 @@ lc_compile_ok:
/////////////////////////////////////////////////////////////////////////////////////////
-class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE
-{
-public:
- explicit AssemblyCPlusPlusInterface() = default;
- ~AssemblyCPlusPlusInterface() override = default;
+class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE {
+ public:
+ explicit AssemblyCPlusPlusInterface() = default;
+ ~AssemblyCPlusPlusInterface() override = default;
- LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface);
+ LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface);
- [[maybe_unused]] static Int32 Arch() noexcept
- {
- return LibCompiler::AssemblyFactory::kArchAMD64;
- }
+ [[maybe_unused]] static Int32 Arch() noexcept { return LibCompiler::AssemblyFactory::kArchAMD64; }
- Int32 CompileToFormat(std::string& src, Int32 arch) override
- {
- if (arch != AssemblyCPlusPlusInterface::Arch())
- return 1;
+ Int32 CompileToFormat(std::string& src, Int32 arch) override {
+ if (arch != AssemblyCPlusPlusInterface::Arch()) return 1;
- if (kCompilerFrontend == nullptr)
- return 1;
+ if (kCompilerFrontend == nullptr) return 1;
- /* @brief copy contents wihtout extension */
- std::string src_file = src;
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src;
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- const char* cExts[] = kAsmFileExts;
+ const char* cExts[] = kAsmFileExts;
- std::string dest = src_file;
- dest += cExts[2];
+ std::string dest = src_file;
+ dest += cExts[2];
- if (dest.empty())
- {
- dest = "CXX-LibCompiler-";
+ if (dest.empty()) {
+ dest = "CXX-LibCompiler-";
- std::random_device rd;
- auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::random_device rd;
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
- auto gen = uuids::uuid_random_generator(generator);
+ auto gen = uuids::uuid_random_generator(generator);
- auto id = gen();
- dest += uuids::to_string(id);
- }
+ auto id = gen();
+ dest += uuids::to_string(id);
+ }
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
- auto fmt = LibCompiler::current_date();
+ auto fmt = LibCompiler::current_date();
- (*kState.fOutputAssembly) << "; Repository Path: /" << src_file << "\n";
+ (*kState.fOutputAssembly) << "; Repository Path: /" << src_file << "\n";
- std::filesystem::path path = std::filesystem::path("./");
+ std::filesystem::path path = std::filesystem::path("./");
- while (path != Detail::expand_home(std::filesystem::path("~")))
- {
- for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{path})
- {
- if (dir_entry.is_directory() &&
- dir_entry.path().string().find(".git") != std::string::npos)
- goto break_loop;
- }
+ while (path != Detail::expand_home(std::filesystem::path("~"))) {
+ for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{path}) {
+ if (dir_entry.is_directory() && dir_entry.path().string().find(".git") != std::string::npos)
+ goto break_loop;
+ }
- path = path.parent_path();
- break_loop:
- (*kState.fOutputAssembly) << "; Repository Style: Git\n";
- break;
- }
+ path = path.parent_path();
+ break_loop:
+ (*kState.fOutputAssembly) << "; Repository Style: Git\n";
+ break;
+ }
- std::stringstream stream;
- stream << kOrigin;
- std::string result(stream.str());
+ std::stringstream stream;
+ stream << kOrigin;
+ std::string result(stream.str());
- (*kState.fOutputAssembly)
- << "; Assembler Dialect: AMD64 LibCompiler Assembler. (Generated from C++)\n";
- (*kState.fOutputAssembly) << "; Date: " << fmt << "\n";
- (*kState.fOutputAssembly) << "#bits 64\n#org " + result
- << "\n";
+ (*kState.fOutputAssembly)
+ << "; Assembler Dialect: AMD64 LibCompiler Assembler. (Generated from C++)\n";
+ (*kState.fOutputAssembly) << "; Date: " << fmt << "\n";
+ (*kState.fOutputAssembly) << "#bits 64\n#org " + result << "\n";
- kState.fSyntaxTree = new LibCompiler::SyntaxLeafList();
+ kState.fSyntaxTree = new LibCompiler::SyntaxLeafList();
- // ===================================
- // Parse source file.
- // ===================================
+ // ===================================
+ // Parse source file.
+ // ===================================
- std::string line_source;
+ std::string line_source;
- while (std::getline(src_fp, line_source))
- {
- kCompilerFrontend->Compile(line_source, src);
- }
+ while (std::getline(src_fp, line_source)) {
+ kCompilerFrontend->Compile(line_source, src);
+ }
- for (auto& ast_generated : kState.fSyntaxTree->fLeafList)
- {
- (*kState.fOutputAssembly) << ast_generated.fUserValue;
- }
+ for (auto& ast_generated : kState.fSyntaxTree->fLeafList) {
+ (*kState.fOutputAssembly) << ast_generated.fUserValue;
+ }
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly->close();
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly->close();
- delete kState.fSyntaxTree;
- kState.fSyntaxTree = nullptr;
+ delete kState.fSyntaxTree;
+ kState.fSyntaxTree = nullptr;
- if (kAcceptableErrors > 0)
- return 1;
+ if (kAcceptableErrors > 0) return 1;
- return kExitOK;
- }
+ return kExitOK;
+ }
};
/////////////////////////////////////////////////////////////////////////////////////////
-static void cxx_print_help()
-{
- kSplashCxx();
- kPrintF("%s", "No help available, see:\n");
- kPrintF("%s", "nekernel.org/docs/cxxdrv\n");
+static void cxx_print_help() {
+ kSplashCxx();
+ kPrintF("%s", "No help available, see:\n");
+ kPrintF("%s", "nekernel.org/docs/cxxdrv\n");
}
/////////////////////////////////////////////////////////////////////////////////////////
-#define kExtListCxx \
- { \
- ".cpp", ".cxx", ".cc", ".c++", ".cp" \
- }
-
-LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64)
-{
- Boolean skip = false;
-
- kKeywords.push_back({.keyword_name = "if", .keyword_kind = LibCompiler::kKeywordKindIf});
- kKeywords.push_back({.keyword_name = "else", .keyword_kind = LibCompiler::kKeywordKindElse});
- kKeywords.push_back({.keyword_name = "else if", .keyword_kind = LibCompiler::kKeywordKindElseIf});
-
- kKeywords.push_back({.keyword_name = "class", .keyword_kind = LibCompiler::kKeywordKindClass});
- kKeywords.push_back({.keyword_name = "struct", .keyword_kind = LibCompiler::kKeywordKindClass});
- kKeywords.push_back({.keyword_name = "namespace", .keyword_kind = LibCompiler::kKeywordKindNamespace});
- kKeywords.push_back({.keyword_name = "typedef", .keyword_kind = LibCompiler::kKeywordKindTypedef});
- kKeywords.push_back({.keyword_name = "using", .keyword_kind = LibCompiler::kKeywordKindTypedef});
- kKeywords.push_back({.keyword_name = "{", .keyword_kind = LibCompiler::kKeywordKindBodyStart});
- kKeywords.push_back({.keyword_name = "}", .keyword_kind = LibCompiler::kKeywordKindBodyEnd});
- kKeywords.push_back({.keyword_name = "auto", .keyword_kind = LibCompiler::kKeywordKindVariable});
- kKeywords.push_back({.keyword_name = "int", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "Boolean", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "short", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "char", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "long", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "float", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "double", .keyword_kind = LibCompiler::kKeywordKindType});
- kKeywords.push_back({.keyword_name = "void", .keyword_kind = LibCompiler::kKeywordKindType});
-
- kKeywords.push_back({.keyword_name = "auto*", .keyword_kind = LibCompiler::kKeywordKindVariablePtr});
- kKeywords.push_back({.keyword_name = "int*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "Boolean*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "unsigned*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "short*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "char*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "long*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "float*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "double*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
- kKeywords.push_back({.keyword_name = "void*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
-
- kKeywords.push_back({.keyword_name = "(", .keyword_kind = LibCompiler::kKeywordKindFunctionStart});
- kKeywords.push_back({.keyword_name = ")", .keyword_kind = LibCompiler::kKeywordKindFunctionEnd});
- kKeywords.push_back({.keyword_name = "=", .keyword_kind = LibCompiler::kKeywordKindVariableAssign});
- kKeywords.push_back({.keyword_name = "+=", .keyword_kind = LibCompiler::kKeywordKindVariableInc});
- kKeywords.push_back({.keyword_name = "-=", .keyword_kind = LibCompiler::kKeywordKindVariableDec});
- kKeywords.push_back({.keyword_name = "const", .keyword_kind = LibCompiler::kKeywordKindConstant});
- kKeywords.push_back({.keyword_name = "*", .keyword_kind = LibCompiler::kKeywordKindPtr});
- kKeywords.push_back({.keyword_name = "->", .keyword_kind = LibCompiler::kKeywordKindPtrAccess});
- kKeywords.push_back({.keyword_name = ".", .keyword_kind = LibCompiler::kKeywordKindAccess});
- kKeywords.push_back({.keyword_name = ",", .keyword_kind = LibCompiler::kKeywordKindArgSeparator});
- kKeywords.push_back({.keyword_name = ";", .keyword_kind = LibCompiler::kKeywordKindEndInstr});
- kKeywords.push_back({.keyword_name = ":", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "public:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "private:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "protected:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "final", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
- kKeywords.push_back({.keyword_name = "return", .keyword_kind = LibCompiler::kKeywordKindReturn});
- kKeywords.push_back({.keyword_name = "--*", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
- kKeywords.push_back({.keyword_name = "*/", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
- kKeywords.push_back({.keyword_name = "--/", .keyword_kind = LibCompiler::kKeywordKindCommentInline});
- kKeywords.push_back({.keyword_name = "==", .keyword_kind = LibCompiler::kKeywordKindEq});
- kKeywords.push_back({.keyword_name = "!=", .keyword_kind = LibCompiler::kKeywordKindNotEq});
- kKeywords.push_back({.keyword_name = ">=", .keyword_kind = LibCompiler::kKeywordKindGreaterEq});
- kKeywords.push_back({.keyword_name = "<=", .keyword_kind = LibCompiler::kKeywordKindLessEq});
-
- kFactory.Mount(new AssemblyCPlusPlusInterface());
- kCompilerFrontend = new CompilerFrontendCPlusPlus();
-
- for (auto index = 1UL; index < argc; ++index)
- {
- if (argv[index][0] == '-')
- {
- if (skip)
- {
- skip = false;
- continue;
- }
-
- if (strcmp(argv[index], "-version") == 0)
- {
- kSplashCxx();
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-cxx-verbose") == 0)
- {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0)
- {
- cxx_print_help();
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-cxx-dialect") == 0)
- {
- if (kCompilerFrontend)
- std::cout << kCompilerFrontend->Language() << "\n";
-
- return kExitOK;
- }
-
- if (strcmp(argv[index], "-max-err") == 0)
- {
- try
- {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...)
- {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown option: ";
- err += argv[index];
-
- Detail::print_error(err, "cxxdrv");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string argv_i = argv[index];
-
- std::vector exts = kExtListCxx;
- Boolean found = false;
-
- for (std::string ext : exts)
- {
- if (argv_i.find(ext) != std::string::npos)
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- if (kState.fVerbose)
- {
- Detail::print_error(argv_i + " is not a valid C++ source.\n", "cxxdrv");
- }
-
- return 1;
- }
-
- std::cout << "CPlusPlusCompilerAMD64: Building: " << argv[index] << std::endl;
-
- if (kFactory.Compile(argv_i, kMachine) != kExitOK)
- return 1;
- }
-
- return kExitOK;
+#define kExtListCxx \
+ { ".cpp", ".cxx", ".cc", ".c++", ".cp" }
+
+LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) {
+ Boolean skip = false;
+
+ kKeywords.push_back({.keyword_name = "if", .keyword_kind = LibCompiler::kKeywordKindIf});
+ kKeywords.push_back({.keyword_name = "else", .keyword_kind = LibCompiler::kKeywordKindElse});
+ kKeywords.push_back({.keyword_name = "else if", .keyword_kind = LibCompiler::kKeywordKindElseIf});
+
+ kKeywords.push_back({.keyword_name = "class", .keyword_kind = LibCompiler::kKeywordKindClass});
+ kKeywords.push_back({.keyword_name = "struct", .keyword_kind = LibCompiler::kKeywordKindClass});
+ kKeywords.push_back(
+ {.keyword_name = "namespace", .keyword_kind = LibCompiler::kKeywordKindNamespace});
+ kKeywords.push_back(
+ {.keyword_name = "typedef", .keyword_kind = LibCompiler::kKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "using", .keyword_kind = LibCompiler::kKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "{", .keyword_kind = LibCompiler::kKeywordKindBodyStart});
+ kKeywords.push_back({.keyword_name = "}", .keyword_kind = LibCompiler::kKeywordKindBodyEnd});
+ kKeywords.push_back({.keyword_name = "auto", .keyword_kind = LibCompiler::kKeywordKindVariable});
+ kKeywords.push_back({.keyword_name = "int", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "Boolean", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "short", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "char", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "long", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "float", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "double", .keyword_kind = LibCompiler::kKeywordKindType});
+ kKeywords.push_back({.keyword_name = "void", .keyword_kind = LibCompiler::kKeywordKindType});
+
+ kKeywords.push_back(
+ {.keyword_name = "auto*", .keyword_kind = LibCompiler::kKeywordKindVariablePtr});
+ kKeywords.push_back({.keyword_name = "int*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "Boolean*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "unsigned*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "short*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "char*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "long*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "float*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back(
+ {.keyword_name = "double*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "void*", .keyword_kind = LibCompiler::kKeywordKindTypePtr});
+
+ kKeywords.push_back(
+ {.keyword_name = "(", .keyword_kind = LibCompiler::kKeywordKindFunctionStart});
+ kKeywords.push_back({.keyword_name = ")", .keyword_kind = LibCompiler::kKeywordKindFunctionEnd});
+ kKeywords.push_back(
+ {.keyword_name = "=", .keyword_kind = LibCompiler::kKeywordKindVariableAssign});
+ kKeywords.push_back({.keyword_name = "+=", .keyword_kind = LibCompiler::kKeywordKindVariableInc});
+ kKeywords.push_back({.keyword_name = "-=", .keyword_kind = LibCompiler::kKeywordKindVariableDec});
+ kKeywords.push_back({.keyword_name = "const", .keyword_kind = LibCompiler::kKeywordKindConstant});
+ kKeywords.push_back({.keyword_name = "*", .keyword_kind = LibCompiler::kKeywordKindPtr});
+ kKeywords.push_back({.keyword_name = "->", .keyword_kind = LibCompiler::kKeywordKindPtrAccess});
+ kKeywords.push_back({.keyword_name = ".", .keyword_kind = LibCompiler::kKeywordKindAccess});
+ kKeywords.push_back({.keyword_name = ",", .keyword_kind = LibCompiler::kKeywordKindArgSeparator});
+ kKeywords.push_back({.keyword_name = ";", .keyword_kind = LibCompiler::kKeywordKindEndInstr});
+ kKeywords.push_back({.keyword_name = ":", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "public:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "private:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "protected:", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back(
+ {.keyword_name = "final", .keyword_kind = LibCompiler::kKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "return", .keyword_kind = LibCompiler::kKeywordKindReturn});
+ kKeywords.push_back(
+ {.keyword_name = "--*", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
+ kKeywords.push_back(
+ {.keyword_name = "*/", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart});
+ kKeywords.push_back(
+ {.keyword_name = "--/", .keyword_kind = LibCompiler::kKeywordKindCommentInline});
+ kKeywords.push_back({.keyword_name = "==", .keyword_kind = LibCompiler::kKeywordKindEq});
+ kKeywords.push_back({.keyword_name = "!=", .keyword_kind = LibCompiler::kKeywordKindNotEq});
+ kKeywords.push_back({.keyword_name = ">=", .keyword_kind = LibCompiler::kKeywordKindGreaterEq});
+ kKeywords.push_back({.keyword_name = "<=", .keyword_kind = LibCompiler::kKeywordKindLessEq});
+
+ kFactory.Mount(new AssemblyCPlusPlusInterface());
+ kCompilerFrontend = new CompilerFrontendCPlusPlus();
+
+ for (auto index = 1UL; index < argc; ++index) {
+ if (argv[index][0] == '-') {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+
+ if (strcmp(argv[index], "-version") == 0) {
+ kSplashCxx();
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-cxx-verbose") == 0) {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "-h") == 0) {
+ cxx_print_help();
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-cxx-dialect") == 0) {
+ if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n";
+
+ return kExitOK;
+ }
+
+ if (strcmp(argv[index], "-max-err") == 0) {
+ try {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...) {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown option: ";
+ err += argv[index];
+
+ Detail::print_error(err, "cxxdrv");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string argv_i = argv[index];
+
+ std::vector exts = kExtListCxx;
+ Boolean found = false;
+
+ for (std::string ext : exts) {
+ if (argv_i.find(ext) != std::string::npos) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (kState.fVerbose) {
+ Detail::print_error(argv_i + " is not a valid C++ source.\n", "cxxdrv");
+ }
+
+ return 1;
+ }
+
+ std::cout << "CPlusPlusCompilerAMD64: Building: " << argv[index] << std::endl;
+
+ if (kFactory.Compile(argv_i, kMachine) != kExitOK) return 1;
+ }
+
+ return kExitOK;
}
// Last rev 8-1-24