From 9dedcf30b1a15f23c7ca530d3d9896692f347734 Mon Sep 17 00:00:00 2001 From: Pasha Bibko <156938226+PashaBibko@users.noreply.github.com> Date: Sun, 20 Jul 2025 18:09:29 +0100 Subject: [PATCH] Added proper logging capabilities --- .gitignore | 3 ++ Common/IO.h | 85 +++++++++++++++++++++++++++++++++++++++++++++ LXC/LXC.cpp | 12 +++++++ Lexer/inc/Token.h | 4 ++- Lexer/src/Lexer.cpp | 10 +++--- Lexer/src/Token.cpp | 9 +++-- 6 files changed, 115 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 34ea02d..b07dc7e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ out/ .vs/ProjectSettings.json .vs/slnx.sqlite .vs/VSWorkspaceState.json + +# Ignores the log output file of the .exe # +LXC.log diff --git a/Common/IO.h b/Common/IO.h index ea34dcc..a60077d 100644 --- a/Common/IO.h +++ b/Common/IO.h @@ -3,8 +3,20 @@ #include #include +#include #include +namespace LXC::Internal +{ + // Returns a reference to the log file // + // To be used only by LXC components // + inline std::ofstream& Log() + { + static std::ofstream sLog; + return sLog; + } +} + namespace LXC::Util { // Checks if a type can be outputted to std::ostream // @@ -17,6 +29,13 @@ namespace LXC::Util // Checks if a list of types can be outputted to std::ostream // template concept AllLogable = (Logable && ...); + // Checks if the type has a custom log method // + template concept HasLogStrFunc = requires(T obj) + { + // Checks the type has a function LogStr that returns a string // + { obj.LogStr() } -> std::same_as; + }; + // Enum to translate to the Win32 code for the colors // enum Color : WORD { @@ -69,4 +88,70 @@ namespace LXC::Util (std::cout << ... << args); std::cout << std::endl; } + + // Intitalises the log with the given file name // + inline void CreateLog(const std::filesystem::path& path) + { + // Opens the log file with the given path // + std::ofstream& log = Internal::Log(); + log.open(path); + + // Assigns a function to close the log file on program exit // + std::atexit([]() + { + std::ofstream& log = Internal::Log(); + log.close(); + }); + } + + // Logs all the arguments to the file (automatically flushes) // + template + requires AllLogable && (sizeof...(Args) > 1) + inline void Log(Args... args) + { + std::ofstream& log = Internal::Log(); + + // Only attempts to write to an open log // + if (log.is_open()) _UNLIKELY + { + // Opening symbol to make the log look fancy // + log << "[LXC-M] \""; + + // Fowards the arguments to the log and flushes // + (log << ... << args); + log << "\"\n"; + log.flush(); + } + } + + // Logs a singular argument to the log, calls Log() if it can on the object // + template + requires HasLogStrFunc || Logable + inline void Log(T arg) + { + std::ofstream& log = Internal::Log(); + + // Only attempts to write to an open log // + if (log.is_open()) _UNLIKELY + { + // Opening symbol to make log look fancy // + log << "[LXC-S] "; + + // Logic if it can call LogStr() // + if constexpr (HasLogStrFunc) + { + // Prints the generated string // + log << '{' << arg.LogStr() << "}\n"; + log.flush(); + } + + // Default logic // + else + { + // Prints the singular arg // + log << '"' << arg << "\"\n"; + log.flush(); + } + } + } } diff --git a/LXC/LXC.cpp b/LXC/LXC.cpp index 4ee52a2..c9b4813 100644 --- a/LXC/LXC.cpp +++ b/LXC/LXC.cpp @@ -6,6 +6,9 @@ int main(int argc, char** argv) { using namespace LXC; + // Creates the debug log // + Util::CreateLog("LXC.log"); + // Reads the given file to a string // Util::ReturnVal fileContents = Util::ReadFile("example/example.lx"); if (fileContents.Failed()) _UNLIKELY @@ -18,9 +21,12 @@ int main(int argc, char** argv) Util::PrintAs(" Error: "); Util::PrintLn(Util::FileReadError::ReasonStr(err.reason), " [", std::filesystem::absolute(err.path), ']'); + Util::Log("Opening source file failed. Stopping program."); Util::Stop(); } + Util::Log("Succesfully opened source file."); + // Turns the file contents into a vector of tokens // Util::ReturnVal tokens = Lexer::TokenizeFile(fileContents); if (tokens.Failed()) _UNLIKELY @@ -31,5 +37,11 @@ int main(int argc, char** argv) Util::Stop(); } + // Prints all of the tokens to the log // + for (const auto& token : tokens.Result()) + { + Util::Log(token); + } + return 0; } diff --git a/Lexer/inc/Token.h b/Lexer/inc/Token.h index 64b3e5c..88bf691 100644 --- a/Lexer/inc/Token.h +++ b/Lexer/inc/Token.h @@ -92,7 +92,9 @@ namespace LXC::Lexer // Getters for the c-string to stop it being reassigned (or deleted) // inline const char* const Str() const { return contents; } - operator const char* const() { return contents; } + + // Outputs all the relevant infomration in a string for logging purposes // + std::string LogStr() const; // The type of the token // const TokenType type; diff --git a/Lexer/src/Lexer.cpp b/Lexer/src/Lexer.cpp index e28fa0a..8a83a18 100644 --- a/Lexer/src/Lexer.cpp +++ b/Lexer/src/Lexer.cpp @@ -36,7 +36,7 @@ namespace LXC::Lexer } trackers; - while (ctx.index > ctx.len) + while (ctx.index < ctx.len) { // The current char within the source that is being lexed // const char current = ctx.source[ctx.index]; @@ -57,7 +57,7 @@ namespace LXC::Lexer // Creates the token (if at the end of the string literal) // if (!trackers.inStrLiteral) - ctx.out.push_back({ ctx, trackers.sectionStart, (USHORT)(ctx.index - trackers.sectionStart), Token::String_Literal }); + ctx.out.emplace_back(ctx, trackers.sectionStart, (USHORT)(ctx.index - trackers.sectionStart), Token::String_Literal); } else if (trackers.inStrLiteral) {} @@ -71,7 +71,7 @@ namespace LXC::Lexer // Checks for the end of the number literal to create the token // if (!IsNumeric(next)) _UNLIKELY { - ctx.out.push_back({ ctx, trackers.sectionStart, (USHORT)(ctx.index - trackers.sectionStart), Token::Num_Literal }); + ctx.out.emplace_back(ctx, trackers.sectionStart, (USHORT)(ctx.index - trackers.sectionStart), Token::Num_Literal); trackers.inNumLiteral = false; } } @@ -86,7 +86,7 @@ namespace LXC::Lexer // Checks for the end of the word to create the token // if (!IsAlpha(next)) _UNLIKELY { - ctx.out.push_back({ ctx, trackers.sectionStart, (USHORT)(ctx.index - trackers.sectionStart), Token::Identifier }); + ctx.out.emplace_back(ctx, trackers.sectionStart, static_cast(ctx.index - trackers.sectionStart), Token::Identifier); trackers.inIdentifier = false; } } @@ -94,7 +94,7 @@ namespace LXC::Lexer // Iterates to the next index // ctx.column++; ctx.index++; - } + } return ctx.out; } diff --git a/Lexer/src/Token.cpp b/Lexer/src/Token.cpp index e1e6f87..402505e 100644 --- a/Lexer/src/Token.cpp +++ b/Lexer/src/Token.cpp @@ -23,9 +23,14 @@ namespace LXC::Lexer Token::~Token() { // Frees any allocated memory // - if (contents != nullptr) - delete[] contents; + //if (contents != nullptr) + // delete[] contents; contents = nullptr; } + + std::string LXC::Lexer::Token::LogStr() const + { + return std::string("CALL LogStr() function"); + } }