From c472cb5fc54fb9280d98422d778e83a1f425da52 Mon Sep 17 00:00:00 2001 From: Pasha Bibko <156938226+PashaBibko@users.noreply.github.com> Date: Wed, 7 May 2025 19:43:09 +0100 Subject: [PATCH] Changed to use concepts instead of static_assert --- Common/Common.vcxproj | 1 - Common/Common.vcxproj.filters | 3 --- Common/LX-Common.h | 15 +++++++++++++++ Common/inc/IO.h | 23 ++++++++++++++++++++--- Common/inc/Logger.h | 14 ++++++++++++++ Common/inc/ThrowIf.h | 11 +++-------- Common/src/Error.cpp | 4 ++-- Common/src/IO.cpp | 19 ------------------- IR-Generator/src/Generator.cpp | 2 +- Lexer/src/LexerErrors.cpp | 8 ++++---- Parser/src/ParserErrors.cpp | 12 ++++++------ 11 files changed, 65 insertions(+), 47 deletions(-) delete mode 100644 Common/src/IO.cpp diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 70644f4..4307610 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -158,7 +158,6 @@ - diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 6c533df..1a3bb74 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -34,9 +34,6 @@ Source Files - - Source Files - Source Files diff --git a/Common/LX-Common.h b/Common/LX-Common.h index ec37e47..718404f 100644 --- a/Common/LX-Common.h +++ b/Common/LX-Common.h @@ -63,6 +63,21 @@ #pragma warning(pop) // <- Renables all warnings +// Concepts used for template verification // + +namespace LX +{ + // Checks if a type can be outputted to std::ostream // + template concept Logable = requires(std::ostream & os, T t) + { + // I have no idea what this part does at all // + { os << t } -> std::same_as; + }; + + // Checks if a list of types can be outputted to std::ostream // + template concept AllLogable = (Logable && ...); +} + // Includes the rest of common // #include diff --git a/Common/inc/IO.h b/Common/inc/IO.h index 805bfdd..dce8295 100644 --- a/Common/inc/IO.h +++ b/Common/inc/IO.h @@ -1,7 +1,7 @@ namespace LX { // Enum of colors with their Win32 equivalent value // - enum class Color + enum class Color : WORD { BLACK = 0, BLUE = 1, @@ -20,8 +20,25 @@ namespace LX WHITE = 15 }; - // Prints a string to std::cout with a certain color using Win32 API // - extern "C" void COMMON_API PrintStringAsColor(const std::string& str, Color c); + // Variadic template to output multiple arguments to the console // + template + requires AllLogable // <- Checks all types can be outputted to the console + + // Prints arguments to the console with a given color // + inline void PrintAsColor(Args... args) + { + // Gets a handle to the console // + static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + // Sets the color of the console to the desired color // + SetConsoleTextAttribute(hConsole, (WORD)color); + + // Outputs the text // + (std::cout << ... << args); + + // Resets the color // + SetConsoleTextAttribute(hConsole, (WORD)Color::LIGHT_GRAY); + } inline std::string ReadFileToString(const std::filesystem::path& path, const std::string errorName = "input file path") { diff --git a/Common/inc/Logger.h b/Common/inc/Logger.h index d0fd675..581b4e9 100644 --- a/Common/inc/Logger.h +++ b/Common/inc/Logger.h @@ -8,13 +8,21 @@ namespace LX // It acts like a fancy namespace // Log() = delete; + // The different formats the log supports // enum class Format { + // Default, with a new line character added after every call // AUTO, + + // No new line characters after all the provided arguments // NONE }; + // Variadic template to allow an undefined ammount of arguments // template + requires AllLogable // <- Checks all types can be outputted to the console + + // Logs information (if the log is initalised) // static void out(Args... args) { // Prints out the args ending with a new line unless specified // @@ -24,11 +32,17 @@ namespace LX else { (*s_LogFile << ... << args); } } + // Variadic template to allow an undefined ammount of arguments // template + requires AllLogable // <- Checks all types can be outputted to the console + + // Adds a named break between different sections in the log // static void LogNewSection(Args... args) { + // Constant for how a break is represented in the log // static const char* BREAK = "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"; + // Outputs the arguments between two breaks // *s_LogFile << '\n' << BREAK << '\n'; (*s_LogFile << ... << args); *s_LogFile << '\n' << BREAK << '\n'; diff --git a/Common/inc/ThrowIf.h b/Common/inc/ThrowIf.h index 177eeae..bfc8c22 100644 --- a/Common/inc/ThrowIf.h +++ b/Common/inc/ThrowIf.h @@ -5,16 +5,11 @@ namespace LX // Util function to throw an error if the condition is met // // Given error type must derive from LX::RuntimeError // - template + template requires + std::is_constructible_v && // <- Checks the arguments can be used to construct the object + std::is_base_of_v // <- Checks the error class is a child of LX::RuntimeError inline void ThrowIf(const bool condition, Args&&... args) { - // Checks that the error type will be caught by the error checker // - static_assert - ( - std::is_base_of_v, - "Must throw a type that derives from LX::RuntimeError" - ); - // Checks if the condition is met and micro-optimises that errors will not be thrown // if (condition) [[unlikely]] { diff --git a/Common/src/Error.cpp b/Common/src/Error.cpp index 05e1efc..07e54e3 100644 --- a/Common/src/Error.cpp +++ b/Common/src/Error.cpp @@ -34,9 +34,9 @@ namespace LX void InvalidFilePath::PrintToConsole() const { // Tells the user the input file could not be found and how to fix the issue // - LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED); + LX::PrintAsColor("Error: "); std::cout << "Invalid " << name << ": "; - LX::PrintStringAsColor(fileLocation, LX::Color::WHITE); + LX::PrintAsColor(fileLocation); std::cout << "\n\nMake sure the file exists and the process has the correct path to the file\n"; } diff --git a/Common/src/IO.cpp b/Common/src/IO.cpp deleted file mode 100644 index c982f07..0000000 --- a/Common/src/IO.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include - -namespace LX -{ - void PrintStringAsColor(const std::string& str, Color c) - { - // Gets a handle to the console // - static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - // Sets the color of the console to the desired color // - SetConsoleTextAttribute(hConsole, (WORD)c); - - // Outputs the text // - std::cout << str; - - // Resets the color // - SetConsoleTextAttribute(hConsole, (WORD)Color::LIGHT_GRAY); - } -} diff --git a/IR-Generator/src/Generator.cpp b/IR-Generator/src/Generator.cpp index 7f2aaf3..e9172c1 100644 --- a/IR-Generator/src/Generator.cpp +++ b/IR-Generator/src/Generator.cpp @@ -43,7 +43,7 @@ extern "C" int __declspec(dllexport) GenIR(const char* a_inpPath, const char* a_ // Logs the errors type to the console if built as Debug // #ifdef _DEBUG std::cout << "LX::RuntimeError thrown of type: "; - LX::PrintStringAsColor(e.ErrorType(), LX::Color::WHITE); + LX::PrintAsColor(e.ErrorType()); std::cout << "\n"; #endif // _DEBUG diff --git a/Lexer/src/LexerErrors.cpp b/Lexer/src/LexerErrors.cpp index 5677d39..87f7d14 100644 --- a/Lexer/src/LexerErrors.cpp +++ b/Lexer/src/LexerErrors.cpp @@ -19,15 +19,15 @@ namespace LX // Prints the error with the relevant information to the console // std::cout << "\n"; - LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED); + PrintAsColor("Error: "); std::cout << "Invalid character found in "; - LX::PrintStringAsColor(file, LX::Color::WHITE); + PrintAsColor(file); std::cout << " {"; - LX::PrintStringAsColor(std::string(1, invalid), LX::Color::LIGHT_RED); + PrintAsColor(std::string(1, invalid)); std::cout << "}:\n"; std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << line << " | " << lineContents << "\n"; std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(col - 1) << ""; - LX::PrintStringAsColor("^", LX::Color::LIGHT_RED); + PrintAsColor("^"); std::cout << "\n"; } diff --git a/Parser/src/ParserErrors.cpp b/Parser/src/ParserErrors.cpp index 1bde6a0..b5dd0d5 100644 --- a/Parser/src/ParserErrors.cpp +++ b/Parser/src/ParserErrors.cpp @@ -32,23 +32,23 @@ namespace LX // Prints the error to the console with the relevant info // std::cout << "\n"; - LX::PrintStringAsColor("Error: ", LX::Color::LIGHT_RED); + PrintAsColor("Error: "); std::cout << "Incorrect syntax in "; - LX::PrintStringAsColor(file.string(), LX::Color::WHITE); + PrintAsColor(file.string()); std::cout << ", found "; - LX::PrintStringAsColor(LX::ToString(got.type).c_str(), LX::Color::WHITE); + PrintAsColor(LX::ToString(got.type).c_str()); std::cout << " expected: "; // Allows the error to have a custom type that is printed to the console // - if (expected == LX::Token::UNDEFINED) { LX::PrintStringAsColor(override.c_str(), LX::Color::WHITE); } - else { LX::PrintStringAsColor(LX::ToString(expected).c_str(), LX::Color::WHITE); } + if (expected == LX::Token::UNDEFINED) { PrintAsColor(override.c_str()); } + else { PrintAsColor(ToString(expected).c_str()); } std::cout << "\n"; // Prints the code with the error to the console // std::string errorSquiggle(got.length, '~'); std::cout << "Line: " << std::setw(lineNumberWidthInConsole) << got.line << " | " << line << "\n"; std::cout << " " << std::setw(lineNumberWidthInConsole) << "" << " | " << std::setw(got.column) << ""; - LX::PrintStringAsColor(errorSquiggle.c_str(), LX::Color::LIGHT_RED); + PrintAsColor(errorSquiggle.c_str()); std::cout << "\n"; }