// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - Shader module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include // https://fmt.dev/latest/api.html#udt template <> struct fmt::formatter : formatter { template auto format(const Nz::ShaderAst::AttributeType& p, FormatContext& ctx) -> decltype(ctx.out()) { // TODO: Add ToString std::string_view name = ""; switch (p) { case Nz::ShaderAst::AttributeType::Binding: name = "binding"; break; case Nz::ShaderAst::AttributeType::Builtin: name = "builtin"; break; case Nz::ShaderAst::AttributeType::Cond: name = "cond"; break; case Nz::ShaderAst::AttributeType::DepthWrite: name = "depth_write"; break; case Nz::ShaderAst::AttributeType::EarlyFragmentTests: name = "early_fragment_tests"; break; case Nz::ShaderAst::AttributeType::Entry: name = "entry"; break; case Nz::ShaderAst::AttributeType::Export: name = "export"; break; case Nz::ShaderAst::AttributeType::Layout: name = "layout"; break; case Nz::ShaderAst::AttributeType::Location: name = "location"; break; case Nz::ShaderAst::AttributeType::LangVersion: name = "nzsl_version"; break; case Nz::ShaderAst::AttributeType::Set: name = "set"; break; case Nz::ShaderAst::AttributeType::Unroll: name = "unroll"; break; case Nz::ShaderAst::AttributeType::Uuid: name = "uuid"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const Nz::ShaderLang::ErrorCategory& p, FormatContext& ctx) -> decltype(ctx.out()) { return formatter::format(ToString(p), ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const Nz::ShaderLang::ErrorType& p, FormatContext& ctx) -> decltype(ctx.out()) { return formatter::format(ToString(p), ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const Nz::ShaderStageType& p, FormatContext& ctx) -> decltype(ctx.out()) { // TODO: Add ToString std::string_view name = ""; switch (p) { case Nz::ShaderStageType::Fragment: name = "fragment"; break; case Nz::ShaderStageType::Vertex: name = "vertex"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const Nz::ShaderLang::TokenType& p, FormatContext& ctx) -> decltype(ctx.out()) { return formatter::format(ToString(p), ctx); } }; namespace Nz::ShaderLang { std::string_view ToString(ErrorCategory errorCategory) { switch (errorCategory) { case ErrorCategory::Ast: return "Ast"; case ErrorCategory::Compilation: return "Compilation"; case ErrorCategory::Lexing: return "Lexing"; case ErrorCategory::Parsing: return "Parsing"; } return ""; } std::string_view ToString(ErrorType errorType) { switch (errorType) { #define NAZARA_SHADERLANG_ERROR(ErrorPrefix, ErrorName, ...) case ErrorType:: ErrorPrefix ## ErrorName: return #ErrorPrefix #ErrorName; #include } return ""; } const std::string& Error::GetErrorMessage() const { if (m_errorMessage.empty()) m_errorMessage = BuildErrorMessage(); return m_errorMessage; } const std::string& Error::GetFullErrorMessage() const { if (m_fullErrorMessage.empty()) { if (m_sourceLocation.IsValid()) { std::string_view sourceFile; if (m_sourceLocation.file) sourceFile = *m_sourceLocation.file; if (m_sourceLocation.startLine != m_sourceLocation.endLine) m_fullErrorMessage = fmt::format("{}({} -> {},{} -> {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.endLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorType, GetErrorMessage()); else if (m_sourceLocation.startColumn != m_sourceLocation.endColumn) m_fullErrorMessage = fmt::format("{}({},{} -> {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_sourceLocation.endColumn, m_errorType, GetErrorMessage()); else m_fullErrorMessage = fmt::format("{}({}, {}): {} error: {}", sourceFile, m_sourceLocation.startLine, m_sourceLocation.startColumn, m_errorType, GetErrorMessage()); } else m_fullErrorMessage = fmt::format("?: {} error: {}", m_errorType, GetErrorMessage()); } return m_fullErrorMessage; } const char* Error::what() const noexcept { return GetFullErrorMessage().c_str(); } #define NAZARA_SHADERLANG_NEWERRORTYPE(Prefix, ErrorType, ErrorName, ErrorString, ...) \ std::string Prefix ## ErrorName ## Error::BuildErrorMessage() const \ { \ return std::apply([&](const auto... args) { return fmt::format(ErrorString, args...); }, m_parameters); \ } #define NAZARA_SHADERLANG_AST_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Ast, A, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_LEXER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Lexer, L, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_PARSER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Parser, P, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_COMPILER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Compiler, C, ErrorName, ErrorString, __VA_ARGS__) #include #undef NAZARA_SHADERLANG_NEWERRORTYPE }