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";
}