#pragma once #include #include #include namespace error_handling { inline void print_position(std::ostream &out, std::pair start_position, std::pair end_position) { out << '[' << start_position.first + 1 << ", " << start_position.second + 1 << "] - [" << end_position.first + 1 << ", " << end_position.second + 1 << ']'; } inline void print_source_location(std::ostream &out, const std::source_location &location) { out << "\x1b[1;33mSOURCE LOCATION:\x1b[0m " << location.file_name() << "(" << location.line() << ":" << location.column() << ") `" << location.function_name() << "`.\n"; } inline void handle_general_error(std::string_view message) { std::cerr << "\x1b[1;31mGeneral Error:\x1b[0m " << message << ".\n"; exit(1); } inline void expect(bool condition, std::string_view failure_message, const std::source_location &location = std::source_location::current()) { if (!condition) { std::cerr << "\x1b[1;33mExpected condition failed (compiler error):\x1b[0m " << failure_message << ".\n"; print_source_location(std::cerr, location); exit(1); } } inline void ensure(bool condition, std::string_view failure_message, const std::source_location &location = std::source_location::current()) { if (!condition) { std::cerr << "\x1b[1;33mEnsured condition failed (compiler error):\x1b[0m " << failure_message << ".\n"; print_source_location(std::cerr, location); exit(1); } } } // namespace error_handling namespace utils { // in std from c++23 [[noreturn]] inline void unreachable() { // Uses compiler specific extensions if possible. // Even if no extension is used, undefined behavior is still raised by // an empty function body and the noreturn attribute. #if defined(_MSC_VER) && !defined(__clang__) // MSVC __assume(false); #else // GCC, Clang __builtin_unreachable(); #endif } } // namespace utils