Shader: Add types to error messages (and remove ID)

This commit is contained in:
SirLynix 2022-04-01 13:36:24 +02:00 committed by Jérôme Leclercq
parent 16cf75440b
commit 7c640f5c00
18 changed files with 501 additions and 320 deletions

View File

@ -61,14 +61,6 @@ namespace Nz::ShaderAst
inline bool operator!=(const FunctionType& rhs) const; inline bool operator!=(const FunctionType& rhs) const;
}; };
struct IdentifierType
{
std::string name;
inline bool operator==(const IdentifierType& rhs) const;
inline bool operator!=(const IdentifierType& rhs) const;
};
struct IntrinsicFunctionType struct IntrinsicFunctionType
{ {
IntrinsicType intrinsic; IntrinsicType intrinsic;
@ -151,7 +143,7 @@ namespace Nz::ShaderAst
inline bool operator!=(const VectorType& rhs) const; inline bool operator!=(const VectorType& rhs) const;
}; };
using ExpressionType = std::variant<NoType, AliasType, ArrayType, FunctionType, IdentifierType, IntrinsicFunctionType, PrimitiveType, MatrixType, MethodType, SamplerType, StructType, Type, UniformType, VectorType>; using ExpressionType = std::variant<NoType, AliasType, ArrayType, FunctionType, IntrinsicFunctionType, MatrixType, MethodType, PrimitiveType, SamplerType, StructType, Type, UniformType, VectorType>;
struct ContainedType struct ContainedType
{ {
@ -178,7 +170,6 @@ namespace Nz::ShaderAst
inline bool IsAliasType(const ExpressionType& type); inline bool IsAliasType(const ExpressionType& type);
inline bool IsArrayType(const ExpressionType& type); inline bool IsArrayType(const ExpressionType& type);
inline bool IsFunctionType(const ExpressionType& type); inline bool IsFunctionType(const ExpressionType& type);
inline bool IsIdentifierType(const ExpressionType& type);
inline bool IsIntrinsicFunctionType(const ExpressionType& type); inline bool IsIntrinsicFunctionType(const ExpressionType& type);
inline bool IsMatrixType(const ExpressionType& type); inline bool IsMatrixType(const ExpressionType& type);
inline bool IsMethodType(const ExpressionType& type); inline bool IsMethodType(const ExpressionType& type);
@ -189,6 +180,28 @@ namespace Nz::ShaderAst
inline bool IsTypeExpression(const ExpressionType& type); inline bool IsTypeExpression(const ExpressionType& type);
inline bool IsUniformType(const ExpressionType& type); inline bool IsUniformType(const ExpressionType& type);
inline bool IsVectorType(const ExpressionType& type); inline bool IsVectorType(const ExpressionType& type);
struct Stringifier
{
std::function<std::string(std::size_t aliasIndex)> aliasStringifier;
std::function<std::string(std::size_t structIndex)> structStringifier;
std::function<std::string(std::size_t typeIndex)> typeStringifier;
};
std::string ToString(const AliasType& type, const Stringifier& stringifier = {});
std::string ToString(const ArrayType& type, const Stringifier& stringifier = {});
std::string ToString(const ExpressionType& type, const Stringifier& stringifier = {});
std::string ToString(const FunctionType& type, const Stringifier& stringifier = {});
std::string ToString(const IntrinsicFunctionType& type, const Stringifier& stringifier = {});
std::string ToString(const MatrixType& type, const Stringifier& stringifier = {});
std::string ToString(const MethodType& type, const Stringifier& stringifier = {});
std::string ToString(NoType type, const Stringifier& stringifier = {});
std::string ToString(PrimitiveType type, const Stringifier& stringifier = {});
std::string ToString(const SamplerType& type, const Stringifier& stringifier = {});
std::string ToString(const StructType& type, const Stringifier& stringifier = {});
std::string ToString(const Type& type, const Stringifier& stringifier = {});
std::string ToString(const UniformType& type, const Stringifier& stringifier = {});
std::string ToString(const VectorType& type, const Stringifier& stringifier = {});
} }
#include <Nazara/Shader/Ast/ExpressionType.inl> #include <Nazara/Shader/Ast/ExpressionType.inl>

View File

@ -30,17 +30,6 @@ namespace Nz::ShaderAst
} }
inline bool IdentifierType::operator==(const IdentifierType& rhs) const
{
return name == rhs.name;
}
inline bool IdentifierType::operator!=(const IdentifierType& rhs) const
{
return !operator==(rhs);
}
inline bool IntrinsicFunctionType::operator==(const IntrinsicFunctionType& rhs) const inline bool IntrinsicFunctionType::operator==(const IntrinsicFunctionType& rhs) const
{ {
return intrinsic == rhs.intrinsic; return intrinsic == rhs.intrinsic;
@ -150,11 +139,6 @@ namespace Nz::ShaderAst
return std::holds_alternative<FunctionType>(type); return std::holds_alternative<FunctionType>(type);
} }
inline bool IsIdentifierType(const ExpressionType& type)
{
return std::holds_alternative<IdentifierType>(type);
}
inline bool IsIntrinsicFunctionType(const ExpressionType& type) inline bool IsIntrinsicFunctionType(const ExpressionType& type)
{ {
return std::holds_alternative<IntrinsicFunctionType>(type); return std::holds_alternative<IntrinsicFunctionType>(type);

View File

@ -66,6 +66,7 @@ namespace Nz::ShaderAst
struct Identifier; struct Identifier;
struct IdentifierData; struct IdentifierData;
template<typename T> struct IdentifierList; template<typename T> struct IdentifierList;
struct NamedPartialType;
struct Scope; struct Scope;
using AstCloner::CloneExpression; using AstCloner::CloneExpression;
@ -130,7 +131,7 @@ namespace Nz::ShaderAst
void RegisterBuiltin(); void RegisterBuiltin();
std::size_t RegisterAlias(std::string name, std::optional<IdentifierData> aliasData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation); std::size_t RegisterAlias(std::string name, std::optional<Identifier> aliasData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation);
std::size_t RegisterConstant(std::string name, std::optional<ConstantValue> value, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation); std::size_t RegisterConstant(std::string name, std::optional<ConstantValue> value, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation);
std::size_t RegisterFunction(std::string name, std::optional<FunctionData> funcData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation); std::size_t RegisterFunction(std::string name, std::optional<FunctionData> funcData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation);
std::size_t RegisterIntrinsic(std::string name, IntrinsicType type); std::size_t RegisterIntrinsic(std::string name, IntrinsicType type);
@ -141,11 +142,10 @@ namespace Nz::ShaderAst
void RegisterUnresolved(std::string name); void RegisterUnresolved(std::string name);
std::size_t RegisterVariable(std::string name, std::optional<ExpressionType> type, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation); std::size_t RegisterVariable(std::string name, std::optional<ExpressionType> type, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation);
const IdentifierData* ResolveAliasIdentifier(const IdentifierData* identifier, const ShaderLang::SourceLocation& sourceLocation) const; const Identifier* ResolveAliasIdentifier(const Identifier* identifier, const ShaderLang::SourceLocation& sourceLocation) const;
void ResolveFunctions(); void ResolveFunctions();
std::size_t ResolveStruct(const AliasType& aliasType, const ShaderLang::SourceLocation& sourceLocation); std::size_t ResolveStruct(const AliasType& aliasType, const ShaderLang::SourceLocation& sourceLocation);
std::size_t ResolveStruct(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation); std::size_t ResolveStruct(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation);
std::size_t ResolveStruct(const IdentifierType& identifierType, const ShaderLang::SourceLocation& sourceLocation);
std::size_t ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& sourceLocation); std::size_t ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& sourceLocation);
std::size_t ResolveStruct(const UniformType& uniformType, const ShaderLang::SourceLocation& sourceLocation); std::size_t ResolveStruct(const UniformType& uniformType, const ShaderLang::SourceLocation& sourceLocation);
ExpressionType ResolveType(const ExpressionType& exprType, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation); ExpressionType ResolveType(const ExpressionType& exprType, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation);
@ -154,6 +154,11 @@ namespace Nz::ShaderAst
void SanitizeIdentifier(std::string& identifier); void SanitizeIdentifier(std::string& identifier);
MultiStatementPtr SanitizeInternal(MultiStatement& rootNode, std::string* error); MultiStatementPtr SanitizeInternal(MultiStatement& rootNode, std::string* error);
std::string ToString(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation) const;
std::string ToString(const NamedPartialType& partialType, const ShaderLang::SourceLocation& sourceLocation) const;
template<typename... Args> std::string ToString(const std::variant<Args...>& value, const ShaderLang::SourceLocation& sourceLocation) const;
void TypeMustMatch(const ExpressionType& left, const ExpressionType& right, const ShaderLang::SourceLocation& sourceLocation) const;
ValidationResult TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right, const ShaderLang::SourceLocation& sourceLocation); ValidationResult TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right, const ShaderLang::SourceLocation& sourceLocation);
ValidationResult Validate(DeclareAliasStatement& node); ValidationResult Validate(DeclareAliasStatement& node);
@ -174,13 +179,11 @@ namespace Nz::ShaderAst
template<std::size_t N> ValidationResult ValidateIntrinsicParamCount(IntrinsicExpression& node); template<std::size_t N> ValidationResult ValidateIntrinsicParamCount(IntrinsicExpression& node);
ValidationResult ValidateIntrinsicParamMatchingType(IntrinsicExpression& node); ValidationResult ValidateIntrinsicParamMatchingType(IntrinsicExpression& node);
template<std::size_t N, typename F> ValidationResult ValidateIntrinsicParameter(IntrinsicExpression& node, F&& func); template<std::size_t N, typename F> ValidationResult ValidateIntrinsicParameter(IntrinsicExpression& node, F&& func);
template<std::size_t N, typename F> ValidationResult ValidateIntrinsicParameterType(IntrinsicExpression& node, F&& func); template<std::size_t N, typename F> ValidationResult ValidateIntrinsicParameterType(IntrinsicExpression& node, F&& func, const char* typeStr);
static Expression& MandatoryExpr(const ExpressionPtr& node, const ShaderLang::SourceLocation& sourceLocation); static Expression& MandatoryExpr(const ExpressionPtr& node, const ShaderLang::SourceLocation& sourceLocation);
static Statement& MandatoryStatement(const StatementPtr& node, const ShaderLang::SourceLocation& sourceLocation); static Statement& MandatoryStatement(const StatementPtr& node, const ShaderLang::SourceLocation& sourceLocation);
static void TypeMustMatch(const ExpressionType& left, const ExpressionType& right, const ShaderLang::SourceLocation& sourceLocation);
static StatementPtr Unscope(StatementPtr node); static StatementPtr Unscope(StatementPtr node);
static UInt32 ToSwizzleIndex(char c, const ShaderLang::SourceLocation& sourceLocation); static UInt32 ToSwizzleIndex(char c, const ShaderLang::SourceLocation& sourceLocation);
@ -220,7 +223,7 @@ namespace Nz::ShaderAst
struct Identifier struct Identifier
{ {
std::string name; std::string name;
IdentifierData data; IdentifierData target;
}; };
struct Context; struct Context;

View File

@ -58,7 +58,6 @@ namespace Nz
void Append(const ShaderAst::ExpressionType& type); void Append(const ShaderAst::ExpressionType& type);
void Append(const ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type); void Append(const ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type);
void Append(const ShaderAst::FunctionType& functionType); void Append(const ShaderAst::FunctionType& functionType);
void Append(const ShaderAst::IdentifierType& identifierType);
void Append(const ShaderAst::IntrinsicFunctionType& intrinsicFunctionType); void Append(const ShaderAst::IntrinsicFunctionType& intrinsicFunctionType);
void Append(const ShaderAst::MatrixType& matrixType); void Append(const ShaderAst::MatrixType& matrixType);
void Append(const ShaderAst::MethodType& methodType); void Append(const ShaderAst::MethodType& methodType);

View File

@ -55,7 +55,6 @@ namespace Nz
void Append(const ShaderAst::ExpressionType& type); void Append(const ShaderAst::ExpressionType& type);
void Append(const ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type); void Append(const ShaderAst::ExpressionValue<ShaderAst::ExpressionType>& type);
void Append(const ShaderAst::FunctionType& functionType); void Append(const ShaderAst::FunctionType& functionType);
void Append(const ShaderAst::IdentifierType& identifierType);
void Append(const ShaderAst::IntrinsicFunctionType& intrinsicFunctionType); void Append(const ShaderAst::IntrinsicFunctionType& intrinsicFunctionType);
void Append(const ShaderAst::MatrixType& matrixType); void Append(const ShaderAst::MatrixType& matrixType);
void Append(const ShaderAst::MethodType& methodType); void Append(const ShaderAst::MethodType& methodType);

View File

@ -9,140 +9,140 @@
#endif #endif
#ifndef NAZARA_SHADERLANG_AST_ERROR #ifndef NAZARA_SHADERLANG_AST_ERROR
#define NAZARA_SHADERLANG_AST_ERROR(...) NAZARA_SHADERLANG_ERROR(A, ...) #define NAZARA_SHADERLANG_AST_ERROR(...) NAZARA_SHADERLANG_ERROR(A, __VA_ARGS__)
#endif #endif
#ifndef NAZARA_SHADERLANG_COMPILER_ERROR #ifndef NAZARA_SHADERLANG_COMPILER_ERROR
#define NAZARA_SHADERLANG_COMPILER_ERROR(...) NAZARA_SHADERLANG_ERROR(C, ...) #define NAZARA_SHADERLANG_COMPILER_ERROR(...) NAZARA_SHADERLANG_ERROR(C, __VA_ARGS__)
#endif #endif
#ifndef NAZARA_SHADERLANG_LEXER_ERROR #ifndef NAZARA_SHADERLANG_LEXER_ERROR
#define NAZARA_SHADERLANG_LEXER_ERROR(...) NAZARA_SHADERLANG_ERROR(L, ...) #define NAZARA_SHADERLANG_LEXER_ERROR(...) NAZARA_SHADERLANG_ERROR(L, __VA_ARGS__)
#endif #endif
#ifndef NAZARA_SHADERLANG_PARSER_ERROR #ifndef NAZARA_SHADERLANG_PARSER_ERROR
#define NAZARA_SHADERLANG_PARSER_ERROR(...) NAZARA_SHADERLANG_ERROR(P, ...) #define NAZARA_SHADERLANG_PARSER_ERROR(...) NAZARA_SHADERLANG_ERROR(P, __VA_ARGS__)
#endif #endif
// Lexer errors // Lexer errors
NAZARA_SHADERLANG_LEXER_ERROR(1, BadNumber, "bad number") NAZARA_SHADERLANG_LEXER_ERROR(BadNumber, "bad number")
NAZARA_SHADERLANG_LEXER_ERROR(2, NumberOutOfRange, "number is out of range") NAZARA_SHADERLANG_LEXER_ERROR(NumberOutOfRange, "number is out of range")
NAZARA_SHADERLANG_LEXER_ERROR(3, UnfinishedString, "unfinished string") NAZARA_SHADERLANG_LEXER_ERROR(UnfinishedString, "unfinished string")
NAZARA_SHADERLANG_LEXER_ERROR(4, UnrecognizedChar, "unrecognized character") NAZARA_SHADERLANG_LEXER_ERROR(UnrecognizedChar, "unrecognized character")
NAZARA_SHADERLANG_LEXER_ERROR(5, UnrecognizedToken, "unrecognized token") NAZARA_SHADERLANG_LEXER_ERROR(UnrecognizedToken, "unrecognized token")
// Parser errors // Parser errors
NAZARA_SHADERLANG_PARSER_ERROR( 1, AttributeExpectString, "attribute {} requires a string parameter", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(AttributeExpectString, "attribute {} requires a string parameter", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR( 2, AttributeInvalidParameter, "invalid parameter {} for attribute {}", std::string, ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(AttributeInvalidParameter, "invalid parameter {} for attribute {}", std::string, ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR( 3, AttributeMissingParameter, "attribute {} requires a parameter", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(AttributeMissingParameter, "attribute {} requires a parameter", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR( 4, AttributeMultipleUnique, "attribute {} can only be present once", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(AttributeMultipleUnique, "attribute {} can only be present once", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR( 5, AttributeParameterIdentifier, "attribute {} parameter can only be an identifier", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(AttributeParameterIdentifier, "attribute {} parameter can only be an identifier", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR( 6, ExpectedToken, "expected token {}, got {}", ShaderLang::TokenType, ShaderLang::TokenType) NAZARA_SHADERLANG_PARSER_ERROR(ExpectedToken, "expected token {}, got {}", ShaderLang::TokenType, ShaderLang::TokenType)
NAZARA_SHADERLANG_PARSER_ERROR( 7, DuplicateIdentifier, "duplicate identifier") NAZARA_SHADERLANG_PARSER_ERROR(DuplicateIdentifier, "duplicate identifier")
NAZARA_SHADERLANG_PARSER_ERROR( 8, DuplicateModule, "duplicate module") NAZARA_SHADERLANG_PARSER_ERROR(DuplicateModule, "duplicate module")
NAZARA_SHADERLANG_PARSER_ERROR( 9, InvalidVersion, "\"{}\" is not a valid version", std::string) NAZARA_SHADERLANG_PARSER_ERROR(InvalidVersion, "\"{}\" is not a valid version", std::string)
NAZARA_SHADERLANG_PARSER_ERROR(10, InvalidUuid, "\"{}\" is not a valid UUID", std::string) NAZARA_SHADERLANG_PARSER_ERROR(InvalidUuid, "\"{}\" is not a valid UUID", std::string)
NAZARA_SHADERLANG_PARSER_ERROR(11, MissingAttribute, "missing attribute {}", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(MissingAttribute, "missing attribute {}", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR(12, ReservedKeyword, "reserved keyword") NAZARA_SHADERLANG_PARSER_ERROR(ReservedKeyword, "reserved keyword")
NAZARA_SHADERLANG_PARSER_ERROR(13, UnknownAttribute, "unknown attribute") NAZARA_SHADERLANG_PARSER_ERROR(UnknownAttribute, "unknown attribute")
NAZARA_SHADERLANG_PARSER_ERROR(14, UnknownType, "unknown type") NAZARA_SHADERLANG_PARSER_ERROR(UnknownType, "unknown type")
NAZARA_SHADERLANG_PARSER_ERROR(15, UnexpectedAttribute, "unexpected attribute {}", ShaderAst::AttributeType) NAZARA_SHADERLANG_PARSER_ERROR(UnexpectedAttribute, "unexpected attribute {}", ShaderAst::AttributeType)
NAZARA_SHADERLANG_PARSER_ERROR(16, UnexpectedEndOfFile, "unexpected end of file") NAZARA_SHADERLANG_PARSER_ERROR(UnexpectedEndOfFile, "unexpected end of file")
NAZARA_SHADERLANG_PARSER_ERROR(17, UnexpectedToken, "unexpected token {}", ShaderLang::TokenType) NAZARA_SHADERLANG_PARSER_ERROR(UnexpectedToken, "unexpected token {}", ShaderLang::TokenType)
// Compiler errors // Compiler errors
NAZARA_SHADERLANG_COMPILER_ERROR(2, AliasUnexpectedType, "for now, only aliases, functions and structs can be aliased") NAZARA_SHADERLANG_COMPILER_ERROR(AliasUnexpectedType, "for now, only aliases, functions and structs can be aliased (got {})", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ArrayLength, "array length must a strictly positive integer") NAZARA_SHADERLANG_COMPILER_ERROR(ArrayLength, "array length must a strictly positive integer, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, AssignTemporary, "temporary values cannot be assigned") NAZARA_SHADERLANG_COMPILER_ERROR(AssignTemporary, "temporary values cannot be assigned")
NAZARA_SHADERLANG_COMPILER_ERROR(2, AttributeUnexpectedExpression, "unexpected expression for this type") NAZARA_SHADERLANG_COMPILER_ERROR(AttributeUnexpectedExpression, "unexpected expression for this type")
NAZARA_SHADERLANG_COMPILER_ERROR(2, AttributeUnexpectedType, "unexpected attribute type") NAZARA_SHADERLANG_COMPILER_ERROR(AttributeUnexpectedType, "unexpected attribute type")
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(BinaryIncompatibleTypes, "incompatibles types ({} and {})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryUnsupported, "{} type (<TODO>) does not support this binary operation", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(BinaryUnsupported, "{} type ({}) does not support this binary operation", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, BranchOutsideOfFunction, "non-const branching statements can only exist inside a function") NAZARA_SHADERLANG_COMPILER_ERROR(BranchOutsideOfFunction, "non-const branching statements can only exist inside a function")
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastComponentMismatch, "component count doesn't match required component count") NAZARA_SHADERLANG_COMPILER_ERROR(CastComponentMismatch, "component count ({}) doesn't match required component count ({})", UInt32, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(CastIncompatibleTypes, "incompatibles types ({} and {})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastMatrixExpectedVector, "expected vector type, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(CastMatrixExpectedVector, "expected vector type, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastMatrixVectorComponentMismatch, "vector component count ({}) doesn't match target matrix row count ({})", UInt32, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(CastMatrixVectorComponentMismatch, "vector component count ({}) doesn't match target matrix row count ({})", UInt32, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, CircularImport, "circular import detected on {}", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(CircularImport, "circular import detected on {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConditionExpectedBool, "expected a boolean value") NAZARA_SHADERLANG_COMPILER_ERROR(ConditionExpectedBool, "expected boolean for condition, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstMissingExpression, "const variables must have an expression") NAZARA_SHADERLANG_COMPILER_ERROR(ConstMissingExpression, "const variables must have an expression")
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstantExpectedValue, "expected a value") NAZARA_SHADERLANG_COMPILER_ERROR(ConstantExpectedValue, "expected a value")
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstantExpressionRequired, "a constant expression is required in this context") NAZARA_SHADERLANG_COMPILER_ERROR(ConstantExpressionRequired, "a constant expression is required in this context")
NAZARA_SHADERLANG_COMPILER_ERROR(2, DepthWriteAttribute, "only fragment entry-points can have the depth_write attribute") NAZARA_SHADERLANG_COMPILER_ERROR(DepthWriteAttribute, "only fragment entry-points can have the depth_write attribute")
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardEarlyFragmentTests, "discard is not compatible with early fragment tests") NAZARA_SHADERLANG_COMPILER_ERROR(DiscardEarlyFragmentTests, "discard is not compatible with early fragment tests")
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardOutsideOfFragmentStage, "discard can only be used in the fragment stage (function gets called in the {} stage)", ShaderStageType) NAZARA_SHADERLANG_COMPILER_ERROR(DiscardOutsideOfFragmentStage, "discard can only be used in the fragment stage (function gets called in the {} stage)", ShaderStageType)
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardOutsideOfFunction, "discard can only be used inside a function") NAZARA_SHADERLANG_COMPILER_ERROR(DiscardOutsideOfFunction, "discard can only be used inside a function")
NAZARA_SHADERLANG_COMPILER_ERROR(2, EarlyFragmentTestsAttribute, "only functions with entry(frag) attribute can have the early_fragments_tests attribute") NAZARA_SHADERLANG_COMPILER_ERROR(EarlyFragmentTestsAttribute, "only functions with entry(frag) attribute can have the early_fragments_tests attribute")
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryFunctionParameter, "entry functions can either take one struct parameter or no parameter") NAZARA_SHADERLANG_COMPILER_ERROR(EntryFunctionParameter, "entry functions can either take one struct parameter or no parameter")
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryPointAlreadyDefined, "the same entry type has been defined multiple times") NAZARA_SHADERLANG_COMPILER_ERROR(EntryPointAlreadyDefined, "the {} entry type has been defined multiple times", ShaderStageType)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedFunction, "expected function expression") NAZARA_SHADERLANG_COMPILER_ERROR(ExpectedFunction, "expected function expression")
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedIntrinsicFunction, "expected intrinsic function expression") NAZARA_SHADERLANG_COMPILER_ERROR(ExpectedIntrinsicFunction, "expected intrinsic function expression")
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedPartialType, "only partial types can be specialized, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(ExpectedPartialType, "only partial types can be specialized, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtAlreadyDeclared, "external variable {} is already declared", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(ExtAlreadyDeclared, "external variable {} is already declared", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtBindingAlreadyUsed, "binding (set={}, binding={}) is already in use", UInt32, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(ExtBindingAlreadyUsed, "binding (set={}, binding={}) is already in use", UInt32, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtMissingBindingIndex, "external variable requires a binding index") NAZARA_SHADERLANG_COMPILER_ERROR(ExtMissingBindingIndex, "external variable requires a binding index")
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtTypeNotAllowed, "external variable {} is of wrong type: only uniform and sampler are allowed in external blocks", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(ExtTypeNotAllowed, "external variable {} is of wrong type ({}): only uniform and sampler are allowed in external blocks", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForEachUnsupportedType, "for-each statements can only be called on array types, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(ForEachUnsupportedType, "for-each statements can only be called on array types, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForFromTypeExpectIntegerType, "numerical for from expression must be an integer or unsigned integer, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(ForFromTypeExpectIntegerType, "numerical for from expression must be an integer or unsigned integer, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForStepUnmatchingType, "numerical for step expression type (<TODO>) must match from expression type (<TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(ForStepUnmatchingType, "numerical for step expression type ({}) must match from expression type ({})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForToUnmatchingType, "numerical for to expression type (<TODO>) must match from expression type (<TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(ForToUnmatchingType, "numerical for to expression type ({}) must match from expression type ({})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, FullTypeExpected, "expected a full type, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(FullTypeExpected, "expected a full type, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallExpectedFunction, "expected function expression") NAZARA_SHADERLANG_COMPILER_ERROR(FunctionCallExpectedFunction, "expected function expression")
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallOutsideOfFunction, "function calls must happen inside a function") NAZARA_SHADERLANG_COMPILER_ERROR(FunctionCallOutsideOfFunction, "function calls must happen inside a function")
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnexpectedEntryFunction, "{} is an entry function which cannot be called by the program", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(FunctionCallUnexpectedEntryFunction, "{} is an entry function which cannot be called by the program", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnmatchingParameterCount, "function {} expects {} parameter(s), but got {}", std::string, UInt32, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(FunctionCallUnmatchingParameterCount, "function {} expects {} parameter(s), but got {}", std::string, UInt32, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnmatchingParameterType, "function {} parameter #{} type mismatch (expected <TODO>, got <TODO>)", std::string, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(FunctionCallUnmatchingParameterType, "function {} parameter #{} type mismatch (expected {}, got {})", std::string, UInt32, std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionDeclarationInsideFunction, "a function cannot be defined inside another function") NAZARA_SHADERLANG_COMPILER_ERROR(FunctionDeclarationInsideFunction, "a function cannot be defined inside another function")
NAZARA_SHADERLANG_COMPILER_ERROR(2, IdentifierAlreadyUsed, "identifier {} is already used", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(IdentifierAlreadyUsed, "identifier {} is already used", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexRequiresIntegerIndices, "index access requires integer indices (got <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(IndexRequiresIntegerIndices, "index access requires integer indices (got {})", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexStructRequiresInt32Indices, "struct indexing requires constant i32 indices (got <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(IndexStructRequiresInt32Indices, "struct indexing requires constant i32 indices (got {})", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexUnexpectedType, "unexpected type: only arrays, structs, vectors and matrices can be indexed (got <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(IndexUnexpectedType, "unexpected type: only arrays, structs, vectors and matrices can be indexed (got {})", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedFloat, "expected scalar or vector floating-points") NAZARA_SHADERLANG_COMPILER_ERROR(IntrinsicExpectedFloat, "expected scalar or vector floating-points")
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedParameterCount, "expected {} parameter(s)", UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(IntrinsicExpectedParameterCount, "expected {} parameter(s)", UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedType, "expected type <TODO> for parameter #{}, got <TODO>", UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(IntrinsicExpectedType, "expected type {1} for parameter #{0}, got {2}", UInt32, std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnexpectedBoolean, "boolean parameters are not allowed") NAZARA_SHADERLANG_COMPILER_ERROR(IntrinsicUnexpectedBoolean, "boolean parameters are not allowed")
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnmatchingParameterType, "all types must match") NAZARA_SHADERLANG_COMPILER_ERROR(IntrinsicUnmatchingParameterType, "all types must match")
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidScalarSwizzle, "invalid swizzle for scalar") NAZARA_SHADERLANG_COMPILER_ERROR(InvalidScalarSwizzle, "invalid swizzle for scalar")
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidSwizzle, "invalid swizzle {}", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(InvalidSwizzle, "invalid swizzle {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, MissingOptionValue, "option {} requires a value (no default value set)", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(MissingOptionValue, "option {} requires a value (no default value set)", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ModuleCompilationFailed, "module {} compilation failed: {}", std::string, std::string) NAZARA_SHADERLANG_COMPILER_ERROR(ModuleCompilationFailed, "module {} compilation failed: {}", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, ModuleNotFound, "module {} not found", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(ModuleNotFound, "module {} not found", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, NoModuleResolver, "import statement found but no module resolver has been set (and partial sanitization is not enabled)") NAZARA_SHADERLANG_COMPILER_ERROR(NoModuleResolver, "import statement found but no module resolver has been set (and partial sanitization is not enabled)")
NAZARA_SHADERLANG_COMPILER_ERROR(2, OptionDeclarationInsideFunction, "options must be declared outside of functions") NAZARA_SHADERLANG_COMPILER_ERROR(OptionDeclarationInsideFunction, "options must be declared outside of functions")
NAZARA_SHADERLANG_COMPILER_ERROR(2, PartialTypeExpect, "expected a {} type at #{}", std::string, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(PartialTypeExpect, "expected a {} type at #{}", std::string, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, PartialTypeParameterCountMismatch, "parameter count mismatch (expected {}, got {})", UInt32, UInt32) NAZARA_SHADERLANG_COMPILER_ERROR(PartialTypeParameterCountMismatch, "parameter count mismatch (expected {}, got {})", UInt32, UInt32)
NAZARA_SHADERLANG_COMPILER_ERROR(2, SamplerUnexpectedType, "for now only f32 samplers are supported (got <TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(SamplerUnexpectedType, "for now only f32 samplers are supported (got {})", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructDeclarationInsideFunction, "structs must be declared outside of functions") NAZARA_SHADERLANG_COMPILER_ERROR(StructDeclarationInsideFunction, "structs must be declared outside of functions")
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructExpected, "struct type expected, got <TODO>") NAZARA_SHADERLANG_COMPILER_ERROR(StructExpected, "struct type expected, got {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructFieldBuiltinLocation, "a struct field cannot have both builtin and location attributes") NAZARA_SHADERLANG_COMPILER_ERROR(StructFieldBuiltinLocation, "a struct field cannot have both builtin and location attributes")
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructFieldMultiple, "multiple {} active struct field found, only one can be active at a time", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(StructFieldMultiple, "multiple {} active struct field found, only one can be active at a time", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructLayoutInnerMismatch, "inner struct layout mismatch, struct is declared with {} but field has layout {}", std::string, std::string) NAZARA_SHADERLANG_COMPILER_ERROR(StructLayoutInnerMismatch, "inner struct layout mismatch, struct is declared with {} but field has layout {}", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructLayoutTypeNotAllowed, "{} type is not allowed in {} layout", std::string, std::string) NAZARA_SHADERLANG_COMPILER_ERROR(StructLayoutTypeNotAllowed, "{} type is not allowed in {} layout", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, SwizzleUnexpectedType, "expression type (<TODO>) does not support swizzling") NAZARA_SHADERLANG_COMPILER_ERROR(SwizzleUnexpectedType, "expression type ({}) does not support swizzling", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnaryUnsupported, "type (<TODO>) does not support this unary operation", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(UnaryUnsupported, "type ({}) does not support this unary operation", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnexpectedAccessedType, "unexpected type (only struct and vectors can be indexed with identifiers)") NAZARA_SHADERLANG_COMPILER_ERROR(UnexpectedAccessedType, "unexpected type (only struct and vectors can be indexed with identifiers)")
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownField, "unknown field {}", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(UnknownField, "unknown field {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownIdentifier, "unknown identifier {}", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(UnknownIdentifier, "unknown identifier {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownMethod, "unknown method {}", std::string) NAZARA_SHADERLANG_COMPILER_ERROR(UnknownMethod, "unknown method {}", std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnmatchingTypes, "left expression type (<TODO>) doesn't match right expression type (<TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(UnmatchingTypes, "left expression type ({}) doesn't match right expression type ({})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationMissingTypeAndValue, "variable must either have a type or an initial value") NAZARA_SHADERLANG_COMPILER_ERROR(VarDeclarationMissingTypeAndValue, "variable must either have a type or an initial value")
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationOutsideOfFunction, "global variables outside of external blocks are forbidden") NAZARA_SHADERLANG_COMPILER_ERROR(VarDeclarationOutsideOfFunction, "global variables outside of external blocks are forbidden")
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationTypeUnmatching, "initial expression type (<TODO>) doesn't match specified type (<TODO>)") NAZARA_SHADERLANG_COMPILER_ERROR(VarDeclarationTypeUnmatching, "initial expression type ({}) doesn't match specified type ({})", std::string, std::string)
NAZARA_SHADERLANG_COMPILER_ERROR(2, WhileUnrollNotSupported, "unroll(always) is not yet supported on while, use a for loop") NAZARA_SHADERLANG_COMPILER_ERROR(WhileUnrollNotSupported, "unroll(always) is not yet supported on while, use a for loop")
// AST errors // AST errors
NAZARA_SHADERLANG_AST_ERROR(1, AlreadyUsedIndex, "index {} is already used", std::size_t) NAZARA_SHADERLANG_AST_ERROR(AlreadyUsedIndex, "index {} is already used", std::size_t)
NAZARA_SHADERLANG_AST_ERROR(1, AttributeRequiresValue, "index {} is already used", std::size_t) NAZARA_SHADERLANG_AST_ERROR(AttributeRequiresValue, "index {} is already used", std::size_t)
NAZARA_SHADERLANG_AST_ERROR(2, AlreadyUsedIndexPreregister, "cannot preregister used index {} as its already used", std::size_t) NAZARA_SHADERLANG_AST_ERROR(AlreadyUsedIndexPreregister, "cannot preregister used index {} as its already used", std::size_t)
NAZARA_SHADERLANG_AST_ERROR(2, EmptyIdentifier, "identifier cannot be empty") NAZARA_SHADERLANG_AST_ERROR(EmptyIdentifier, "identifier cannot be empty")
NAZARA_SHADERLANG_AST_ERROR(2, Internal, "internal error: {}", std::string) NAZARA_SHADERLANG_AST_ERROR(Internal, "internal error: {}", std::string)
NAZARA_SHADERLANG_AST_ERROR(2, InvalidConstantIndex, "invalid constant index #{}", std::size_t) NAZARA_SHADERLANG_AST_ERROR(InvalidConstantIndex, "invalid constant index #{}", std::size_t)
NAZARA_SHADERLANG_AST_ERROR(2, InvalidIndex, "invalid index {}", std::size_t) NAZARA_SHADERLANG_AST_ERROR(InvalidIndex, "invalid index {}", std::size_t)
NAZARA_SHADERLANG_AST_ERROR(2, MissingExpression, "a mandatory expression is missing") NAZARA_SHADERLANG_AST_ERROR(MissingExpression, "a mandatory expression is missing")
NAZARA_SHADERLANG_AST_ERROR(2, MissingStatement, "a mandatory statement is missing") NAZARA_SHADERLANG_AST_ERROR(MissingStatement, "a mandatory statement is missing")
NAZARA_SHADERLANG_AST_ERROR(2, NoIdentifier, "at least one identifier is required") NAZARA_SHADERLANG_AST_ERROR(NoIdentifier, "at least one identifier is required")
NAZARA_SHADERLANG_AST_ERROR(2, NoIndex, "at least one index is required") NAZARA_SHADERLANG_AST_ERROR(NoIndex, "at least one index is required")
NAZARA_SHADERLANG_AST_ERROR(2, UnexpectedIdentifier, "unexpected identifier of type {}", std::string) NAZARA_SHADERLANG_AST_ERROR(UnexpectedIdentifier, "unexpected identifier of type {}", std::string)
#undef NAZARA_SHADERLANG_ERROR #undef NAZARA_SHADERLANG_ERROR
#undef NAZARA_SHADERLANG_AST_ERROR #undef NAZARA_SHADERLANG_AST_ERROR

View File

@ -29,17 +29,24 @@ namespace Nz::ShaderLang
Max = Parsing Max = Parsing
}; };
enum class ErrorType
{
#define NAZARA_SHADERLANG_ERROR(ErrorPrefix, ErrorName, ...) ErrorPrefix ## ErrorName,
#include <Nazara/Shader/ShaderLangErrorList.hpp>
};
class Error : public std::exception class Error : public std::exception
{ {
public: public:
inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, unsigned int errorType) noexcept; inline Error(SourceLocation sourceLocation, ErrorCategory errorCategory, ErrorType errorType) noexcept;
Error(const Error&) = delete; Error(const Error&) = delete;
Error(Error&&) noexcept = default; Error(Error&&) noexcept = default;
~Error() = default; ~Error() = default;
inline ErrorCategory GetErrorCategory() const; inline ErrorCategory GetErrorCategory() const;
const std::string& GetErrorMessage() const; const std::string& GetErrorMessage() const;
inline unsigned int GetErrorType() const; inline ErrorType GetErrorType() const;
inline const SourceLocation& GetSourceLocation() const; inline const SourceLocation& GetSourceLocation() const;
const char* what() const noexcept override; const char* what() const noexcept override;
@ -54,39 +61,39 @@ namespace Nz::ShaderLang
mutable std::string m_errorMessage; mutable std::string m_errorMessage;
ErrorCategory m_errorCategory; ErrorCategory m_errorCategory;
SourceLocation m_sourceLocation; SourceLocation m_sourceLocation;
unsigned int m_errorType; ErrorType m_errorType;
}; };
class AstError : public Error class AstError : public Error
{ {
public: public:
inline AstError(SourceLocation sourceLocation, unsigned int errorType) noexcept; inline AstError(SourceLocation sourceLocation, ErrorType errorType) noexcept;
}; };
class CompilationError : public Error class CompilationError : public Error
{ {
public: public:
inline CompilationError(SourceLocation sourceLocation, unsigned int errorType) noexcept; inline CompilationError(SourceLocation sourceLocation, ErrorType errorType) noexcept;
}; };
class LexingError : public Error class LexingError : public Error
{ {
public: public:
inline LexingError(SourceLocation sourceLocation, unsigned int errorType) noexcept; inline LexingError(SourceLocation sourceLocation, ErrorType errorType) noexcept;
}; };
class ParsingError : public Error class ParsingError : public Error
{ {
public: public:
inline ParsingError(SourceLocation sourceLocation, unsigned int errorType) noexcept; inline ParsingError(SourceLocation sourceLocation, ErrorType errorType) noexcept;
}; };
#define NAZARA_SHADERLANG_NEWERRORTYPE(Prefix, BaseClass, ErrorType, ErrorName, ErrorString, ...) \ #define NAZARA_SHADERLANG_NEWERRORTYPE(Prefix, BaseClass, ErrorPrefix, ErrorName, ErrorString, ...) \
class Prefix ## ErrorName ## Error final : public BaseClass \ class Prefix ## ErrorName ## Error final : public BaseClass \
{ \ { \
public: \ public: \
template<typename... Args> Prefix ## ErrorName ## Error(SourceLocation sourceLocation, Args&&... args) : \ template<typename... Args> Prefix ## ErrorName ## Error(SourceLocation sourceLocation, Args&&... args) : \
BaseClass(std::move(sourceLocation), ErrorType), \ BaseClass(std::move(sourceLocation), ErrorType:: ErrorPrefix ## ErrorName), \
m_parameters(std::forward<Args>(args)...) \ m_parameters(std::forward<Args>(args)...) \
{ \ { \
} \ } \
@ -97,10 +104,10 @@ namespace Nz::ShaderLang
std::tuple<__VA_ARGS__> m_parameters; \ std::tuple<__VA_ARGS__> m_parameters; \
}; };
#define NAZARA_SHADERLANG_AST_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Ast, AstError, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_AST_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Ast, AstError, A, ErrorName, ErrorString, __VA_ARGS__)
#define NAZARA_SHADERLANG_LEXER_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Lexer, LexingError, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_LEXER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Lexer, LexingError, L, ErrorName, ErrorString, __VA_ARGS__)
#define NAZARA_SHADERLANG_PARSER_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Parser, ParsingError, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_PARSER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Parser, ParsingError, P, ErrorName, ErrorString, __VA_ARGS__)
#define NAZARA_SHADERLANG_COMPILER_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Compiler, CompilationError, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_COMPILER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Compiler, CompilationError, C, ErrorName, ErrorString, __VA_ARGS__)
#include <Nazara/Shader/ShaderLangErrorList.hpp> #include <Nazara/Shader/ShaderLangErrorList.hpp>

View File

@ -7,7 +7,7 @@
namespace Nz::ShaderLang namespace Nz::ShaderLang
{ {
inline Error::Error(SourceLocation sourceLocation, ErrorCategory errorCategory, unsigned int errorType) noexcept : inline Error::Error(SourceLocation sourceLocation, ErrorCategory errorCategory, ErrorType errorType) noexcept :
m_errorCategory(errorCategory), m_errorCategory(errorCategory),
m_sourceLocation(std::move(sourceLocation)), m_sourceLocation(std::move(sourceLocation)),
m_errorType(errorType) m_errorType(errorType)
@ -19,7 +19,7 @@ namespace Nz::ShaderLang
return m_errorCategory; return m_errorCategory;
} }
inline unsigned int Error::GetErrorType() const inline ErrorType Error::GetErrorType() const
{ {
return m_errorType; return m_errorType;
} }
@ -30,22 +30,22 @@ namespace Nz::ShaderLang
} }
inline AstError::AstError(SourceLocation sourceLocation, unsigned int errorType) noexcept : inline AstError::AstError(SourceLocation sourceLocation, ErrorType errorType) noexcept :
Error(std::move(sourceLocation), ErrorCategory::Ast, errorType) Error(std::move(sourceLocation), ErrorCategory::Ast, errorType)
{ {
} }
inline CompilationError::CompilationError(SourceLocation sourceLocation, unsigned int errorType) noexcept : inline CompilationError::CompilationError(SourceLocation sourceLocation, ErrorType errorType) noexcept :
Error(std::move(sourceLocation), ErrorCategory::Compilation, errorType) Error(std::move(sourceLocation), ErrorCategory::Compilation, errorType)
{ {
} }
inline ParsingError::ParsingError(SourceLocation sourceLocation, unsigned int errorType) noexcept : inline ParsingError::ParsingError(SourceLocation sourceLocation, ErrorType errorType) noexcept :
Error(std::move(sourceLocation), ErrorCategory::Parsing, errorType) Error(std::move(sourceLocation), ErrorCategory::Parsing, errorType)
{ {
} }
inline LexingError::LexingError(SourceLocation sourceLocation, unsigned int errorType) noexcept : inline LexingError::LexingError(SourceLocation sourceLocation, ErrorType errorType) noexcept :
Error(std::move(sourceLocation), ErrorCategory::Lexing, errorType) Error(std::move(sourceLocation), ErrorCategory::Lexing, errorType)
{ {
} }

View File

@ -181,7 +181,6 @@ namespace Nz
TypePtr BuildType(const ShaderAst::AliasType& type) const; TypePtr BuildType(const ShaderAst::AliasType& type) const;
TypePtr BuildType(const ShaderAst::ArrayType& type) const; TypePtr BuildType(const ShaderAst::ArrayType& type) const;
TypePtr BuildType(const ShaderAst::ExpressionType& type) const; TypePtr BuildType(const ShaderAst::ExpressionType& type) const;
TypePtr BuildType(const ShaderAst::IdentifierType& type) const;
TypePtr BuildType(const ShaderAst::MatrixType& type) const; TypePtr BuildType(const ShaderAst::MatrixType& type) const;
TypePtr BuildType(const ShaderAst::NoType& type) const; TypePtr BuildType(const ShaderAst::NoType& type) const;
TypePtr BuildType(const ShaderAst::PrimitiveType& type) const; TypePtr BuildType(const ShaderAst::PrimitiveType& type) const;

View File

@ -480,11 +480,6 @@ namespace Nz::ShaderAst
m_stream << UInt8(1); m_stream << UInt8(1);
Enum(arg); Enum(arg);
} }
else if constexpr (std::is_same_v<T, IdentifierType>)
{
m_stream << UInt8(2);
m_stream << arg.name;
}
else if constexpr (std::is_same_v<T, MatrixType>) else if constexpr (std::is_same_v<T, MatrixType>)
{ {
m_stream << UInt8(3); m_stream << UInt8(3);
@ -769,15 +764,6 @@ namespace Nz::ShaderAst
break; break;
} }
case 2: //< Identifier
{
std::string identifier;
Value(identifier);
type = IdentifierType{ std::move(identifier) };
break;
}
case 3: //< MatrixType case 3: //< MatrixType
{ {
std::size_t columnCount, rowCount; std::size_t columnCount, rowCount;

View File

@ -95,4 +95,150 @@ namespace Nz::ShaderAst
assert(rhs.objectType); assert(rhs.objectType);
return objectType->type == rhs.objectType->type && methodIndex == rhs.methodIndex; return objectType->type == rhs.objectType->type && methodIndex == rhs.methodIndex;
} }
std::string ToString(const AliasType& type, const Stringifier& stringifier)
{
std::string str = "alias ";
if (stringifier.aliasStringifier)
str += stringifier.aliasStringifier(type.aliasIndex);
else
{
str += "#";
str += std::to_string(type.aliasIndex);
}
str += " -> ";
str += ToString(type.targetType->type);
return str;
}
std::string ToString(const ArrayType& type, const Stringifier& stringifier)
{
std::string str = "array[";
str += ToString(type.containedType->type, stringifier);
str += ", ";
str += std::to_string(type.length);
str += "]";
return str;
}
std::string ShaderAst::ToString(const ExpressionType& type, const Stringifier& stringifier)
{
return std::visit([&](auto&& arg)
{
return ToString(arg, stringifier);
}, type);
}
std::string ToString(const FunctionType& /*type*/, const Stringifier& /*stringifier*/)
{
return "<function type>";
}
std::string ToString(const IntrinsicFunctionType& /*type*/, const Stringifier& /*stringifier*/)
{
return "<intrinsic function type>";
}
std::string ToString(const MatrixType& type, const Stringifier& /*stringifier*/)
{
std::string str = "mat";
if (type.columnCount == type.rowCount)
str += std::to_string(type.columnCount);
else
{
str += std::to_string(type.columnCount);
str += "x";
str += std::to_string(type.rowCount);
}
str += "[";
str += ToString(type.type);
str += "]";
return str;
}
std::string ToString(const MethodType& type, const Stringifier& /*stringifier*/)
{
return "<method of object " + ToString(type.objectType->type) + " type>";
}
std::string ToString(NoType /*type*/, const Stringifier& /*stringifier*/)
{
return "()";
}
std::string ToString(PrimitiveType type, const Stringifier& /*stringifier*/)
{
switch (type)
{
case ShaderAst::PrimitiveType::Boolean: return "bool";
case ShaderAst::PrimitiveType::Float32: return "f32";
case ShaderAst::PrimitiveType::Int32: return "i32";
case ShaderAst::PrimitiveType::UInt32: return "u32";
case ShaderAst::PrimitiveType::String: return "string";
}
return "<unhandled primitive type>";
}
std::string ToString(const SamplerType& type, const Stringifier& /*stringifier*/)
{
std::string str = "sampler";
switch (type.dim)
{
case ImageType::E1D: str += "1D"; break;
case ImageType::E1D_Array: str += "1DArray"; break;
case ImageType::E2D: str += "2D"; break;
case ImageType::E2D_Array: str += "2DArray"; break;
case ImageType::E3D: str += "3D"; break;
case ImageType::Cubemap: str += "Cube"; break;
}
str += "[";
str += ToString(type.sampledType);
str += "]";
return str;
}
std::string ToString(const StructType& type, const Stringifier& stringifier)
{
if (stringifier.structStringifier)
return "struct " + stringifier.structStringifier(type.structIndex);
else
return "struct #" + std::to_string(type.structIndex);
}
std::string ToString(const Type& type, const Stringifier& stringifier)
{
if (stringifier.typeStringifier)
return "type " + stringifier.typeStringifier(type.typeIndex);
else
return "type #" + std::to_string(type.typeIndex);
}
std::string ToString(const UniformType& type, const Stringifier& stringifier)
{
std::string str = "uniform[";
str += ToString(type.containedType, stringifier);
str += "]";
return str;
}
std::string ToString(const VectorType& type, const Stringifier& /*stringifier*/)
{
std::string str = "vec";
str += std::to_string(type.componentCount);
str += "[";
str += ToString(type.type);
str += "]";
return str;
}
} }

View File

@ -137,6 +137,12 @@ namespace Nz::ShaderAst
std::vector<Scope> scopes; std::vector<Scope> scopes;
}; };
struct SanitizeVisitor::NamedPartialType
{
std::string name;
PartialType type;
};
struct SanitizeVisitor::Context struct SanitizeVisitor::Context
{ {
struct ModuleData struct ModuleData
@ -166,11 +172,11 @@ namespace Nz::ShaderAst
std::shared_ptr<Environment> moduleEnv; std::shared_ptr<Environment> moduleEnv;
IdentifierList<ConstantValue> constantValues; IdentifierList<ConstantValue> constantValues;
IdentifierList<FunctionData> functions; IdentifierList<FunctionData> functions;
IdentifierList<IdentifierData> aliases; IdentifierList<Identifier> aliases;
IdentifierList<IntrinsicType> intrinsics; IdentifierList<IntrinsicType> intrinsics;
IdentifierList<std::size_t> moduleIndices; IdentifierList<std::size_t> moduleIndices;
IdentifierList<StructDescription*> structs; IdentifierList<StructDescription*> structs;
IdentifierList<std::variant<ExpressionType, PartialType>> types; IdentifierList<std::variant<ExpressionType, NamedPartialType>> types;
IdentifierList<ExpressionType> variableTypes; IdentifierList<ExpressionType> variableTypes;
ModulePtr currentModule; ModulePtr currentModule;
Options options; Options options;
@ -455,8 +461,8 @@ namespace Nz::ShaderAst
ExpressionPtr SanitizeVisitor::Clone(AliasValueExpression& node) ExpressionPtr SanitizeVisitor::Clone(AliasValueExpression& node)
{ {
const IdentifierData* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(node.aliasId, node.sourceLocation), node.sourceLocation); const Identifier* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(node.aliasId, node.sourceLocation), node.sourceLocation);
ExpressionPtr targetExpr = HandleIdentifier(targetIdentifier, node.sourceLocation); ExpressionPtr targetExpr = HandleIdentifier(&targetIdentifier->target, node.sourceLocation);
if (m_context->options.removeAliases) if (m_context->options.removeAliases)
return targetExpr; return targetExpr;
@ -512,11 +518,11 @@ namespace Nz::ShaderAst
{ {
const auto& alias = static_cast<AliasValueExpression&>(*targetExpr); const auto& alias = static_cast<AliasValueExpression&>(*targetExpr);
const IdentifierData* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), targetExpr->sourceLocation); const Identifier* aliasIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), targetExpr->sourceLocation);
if (targetIdentifier->category != IdentifierCategory::Function) if (aliasIdentifier->target.category != IdentifierCategory::Function)
throw ShaderLang::CompilerExpectedFunctionError{ targetExpr->sourceLocation }; throw ShaderLang::CompilerExpectedFunctionError{ targetExpr->sourceLocation };
targetFuncIndex = targetIdentifier->index; targetFuncIndex = aliasIdentifier->target.index;
} }
else else
throw ShaderLang::CompilerExpectedFunctionError{ targetExpr->sourceLocation }; throw ShaderLang::CompilerExpectedFunctionError{ targetExpr->sourceLocation };
@ -714,7 +720,7 @@ namespace Nz::ShaderAst
} }
if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean }) if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean })
throw ShaderLang::CompilerConditionExpectedBoolError{ cloneCondition->sourceLocation }; throw ShaderLang::CompilerConditionExpectedBoolError{ cloneCondition->sourceLocation, ToString(GetConstantType(*conditionValue), cloneCondition->sourceLocation) };
if (std::get<bool>(*conditionValue)) if (std::get<bool>(*conditionValue))
return AstCloner::Clone(*node.truePath); return AstCloner::Clone(*node.truePath);
@ -868,7 +874,7 @@ namespace Nz::ShaderAst
return AstCloner::Clone(node); //< Unresolvable condition return AstCloner::Clone(node); //< Unresolvable condition
if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean }) if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean })
throw ShaderLang::CompilerConditionExpectedBoolError{ cond.condition->sourceLocation }; throw ShaderLang::CompilerConditionExpectedBoolError{ cond.condition->sourceLocation, ToString(GetConstantType(*conditionValue), cond.condition->sourceLocation) };
if (std::get<bool>(*conditionValue)) if (std::get<bool>(*conditionValue))
return Unscope(AstCloner::Clone(*cond.statement)); return Unscope(AstCloner::Clone(*cond.statement));
@ -903,7 +909,7 @@ namespace Nz::ShaderAst
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
if (!IsPrimitiveType(*condType) || std::get<PrimitiveType>(*condType) != PrimitiveType::Boolean) if (!IsPrimitiveType(*condType) || std::get<PrimitiveType>(*condType) != PrimitiveType::Boolean)
throw ShaderLang::CompilerConditionExpectedBoolError{ condStatement.condition->sourceLocation }; throw ShaderLang::CompilerConditionExpectedBoolError{ condStatement.condition->sourceLocation, ToString(*condType, condStatement.condition->sourceLocation)};
condStatement.statement = CloneStatement(MandatoryStatement(cond.statement, node.sourceLocation)); condStatement.statement = CloneStatement(MandatoryStatement(cond.statement, node.sourceLocation));
return ValidationResult::Validated; return ValidationResult::Validated;
@ -956,7 +962,7 @@ namespace Nz::ShaderAst
} }
if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean }) if (GetConstantType(*conditionValue) != ExpressionType{ PrimitiveType::Boolean })
throw ShaderLang::CompilerConditionExpectedBoolError{ cloneCondition->sourceLocation }; throw ShaderLang::CompilerConditionExpectedBoolError{ cloneCondition->sourceLocation, ToString(GetConstantType(*conditionValue), cloneCondition->sourceLocation) };
if (std::get<bool>(*conditionValue)) if (std::get<bool>(*conditionValue))
return AstCloner::Clone(*node.statement); return AstCloner::Clone(*node.statement);
@ -999,7 +1005,7 @@ namespace Nz::ShaderAst
std::optional<ExpressionType> constType = ResolveTypeExpr(clone->type, true, node.sourceLocation); std::optional<ExpressionType> constType = ResolveTypeExpr(clone->type, true, node.sourceLocation);
if (clone->type.HasValue() && constType.has_value() && *constType != ResolveAlias(expressionType)) if (clone->type.HasValue() && constType.has_value() && *constType != ResolveAlias(expressionType))
throw ShaderLang::CompilerVarDeclarationTypeUnmatchingError{ clone->expression->sourceLocation }; throw ShaderLang::CompilerVarDeclarationTypeUnmatchingError{ clone->expression->sourceLocation, ToString(expressionType, clone->expression->sourceLocation), ToString(*constType, node.sourceLocation) };
clone->type = expressionType; clone->type = expressionType;
@ -1070,7 +1076,7 @@ namespace Nz::ShaderAst
else if (IsSamplerType(targetType)) else if (IsSamplerType(targetType))
varType = targetType; varType = targetType;
else else
throw ShaderLang::CompilerExtTypeNotAllowedError{ extVar.sourceLocation, extVar.name }; throw ShaderLang::CompilerExtTypeNotAllowedError{ extVar.sourceLocation, extVar.name, ToString(*resolvedType, extVar.sourceLocation) };
extVar.type = std::move(resolvedType).value(); extVar.type = std::move(resolvedType).value();
extVar.varIndex = RegisterVariable(extVar.name, std::move(varType), extVar.varIndex, extVar.sourceLocation); extVar.varIndex = RegisterVariable(extVar.name, std::move(varType), extVar.varIndex, extVar.sourceLocation);
@ -1123,7 +1129,7 @@ namespace Nz::ShaderAst
if (!m_context->options.allowPartialSanitization) if (!m_context->options.allowPartialSanitization)
{ {
if (m_context->entryFunctions[UnderlyingCast(stageType)]) if (m_context->entryFunctions[UnderlyingCast(stageType)])
throw ShaderLang::CompilerEntryPointAlreadyDefinedError{ clone->sourceLocation }; throw ShaderLang::CompilerEntryPointAlreadyDefinedError{ clone->sourceLocation, stageType };
m_context->entryFunctions[UnderlyingCast(stageType)] = &node; m_context->entryFunctions[UnderlyingCast(stageType)] = &node;
} }
@ -1342,7 +1348,7 @@ namespace Nz::ShaderAst
MandatoryStatement(node.statement, node.sourceLocation); MandatoryStatement(node.statement, node.sourceLocation);
const ExpressionType* fromExprType = GetExpressionType(*fromExpr); const ExpressionType* fromExprType = GetExpressionType(*fromExpr);
const ExpressionType* toExprType = GetExpressionType(*fromExpr); const ExpressionType* toExprType = GetExpressionType(*toExpr);
ExpressionValue<LoopUnroll> unrollValue; ExpressionValue<LoopUnroll> unrollValue;
@ -1381,15 +1387,15 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedFromExprType = ResolveAlias(*fromExprType); const ExpressionType& resolvedFromExprType = ResolveAlias(*fromExprType);
if (!IsPrimitiveType(resolvedFromExprType)) if (!IsPrimitiveType(resolvedFromExprType))
throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation }; throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation, ToString(*fromExprType, fromExpr->sourceLocation) };
PrimitiveType counterType = std::get<PrimitiveType>(resolvedFromExprType); PrimitiveType counterType = std::get<PrimitiveType>(resolvedFromExprType);
if (counterType != PrimitiveType::Int32 && counterType != PrimitiveType::UInt32) if (counterType != PrimitiveType::Int32 && counterType != PrimitiveType::UInt32)
throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation }; throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation, ToString(*fromExprType, fromExpr->sourceLocation) };
const ExpressionType& resolvedToExprType = ResolveAlias(*toExprType); const ExpressionType& resolvedToExprType = ResolveAlias(*toExprType);
if (resolvedToExprType != resolvedFromExprType) if (resolvedToExprType != resolvedFromExprType)
throw ShaderLang::CompilerForToUnmatchingTypeError{ toExpr->sourceLocation }; throw ShaderLang::CompilerForToUnmatchingTypeError{ toExpr->sourceLocation, ToString(*toExprType, toExpr->sourceLocation), ToString(*fromExprType, fromExpr->sourceLocation) };
if (stepExpr) if (stepExpr)
{ {
@ -1399,7 +1405,7 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedStepExprType = ResolveAlias(*stepExprType); const ExpressionType& resolvedStepExprType = ResolveAlias(*stepExprType);
if (resolvedStepExprType != resolvedFromExprType) if (resolvedStepExprType != resolvedFromExprType)
throw ShaderLang::CompilerForStepUnmatchingTypeError{ stepExpr->sourceLocation }; throw ShaderLang::CompilerForStepUnmatchingTypeError{ stepExpr->sourceLocation, ToString(*stepExprType, stepExpr->sourceLocation), ToString(*fromExprType, fromExpr->sourceLocation) };
} }
if (unrollValue.HasValue()) if (unrollValue.HasValue())
@ -1570,7 +1576,7 @@ namespace Nz::ShaderAst
innerType = arrayType.containedType->type; innerType = arrayType.containedType->type;
} }
else else
throw ShaderLang::CompilerForEachUnsupportedTypeError{ node.sourceLocation }; throw ShaderLang::CompilerForEachUnsupportedTypeError{ node.sourceLocation, ToString(*exprType, node.sourceLocation) };
ExpressionValue<LoopUnroll> unrollValue; ExpressionValue<LoopUnroll> unrollValue;
if (node.unroll.HasValue()) if (node.unroll.HasValue())
@ -1896,7 +1902,7 @@ namespace Nz::ShaderAst
return nullptr; return nullptr;
} }
return &it->data; return &it->target;
} }
template<typename F> template<typename F>
@ -1906,7 +1912,7 @@ namespace Nz::ShaderAst
{ {
if (identifier.name == identifierName) if (identifier.name == identifierName)
{ {
if (functor(identifier.data)) if (functor(identifier.target))
return true; return true;
} }
@ -1920,7 +1926,7 @@ namespace Nz::ShaderAst
return nullptr; return nullptr;
} }
return &it->data; return &it->target;
} }
const ExpressionType* SanitizeVisitor::GetExpressionType(Expression& expr) const const ExpressionType* SanitizeVisitor::GetExpressionType(Expression& expr) const
@ -2228,7 +2234,7 @@ namespace Nz::ShaderAst
{ {
Int32 value = std::get<Int32>(length); Int32 value = std::get<Int32>(length);
if (value <= 0) if (value <= 0)
throw ShaderLang::CompilerArrayLengthError{ sourceLocation }; throw ShaderLang::CompilerArrayLengthError{ sourceLocation, std::to_string(value) };
lengthValue = SafeCast<UInt32>(value); lengthValue = SafeCast<UInt32>(value);
} }
@ -2236,10 +2242,10 @@ namespace Nz::ShaderAst
{ {
lengthValue = std::get<UInt32>(length); lengthValue = std::get<UInt32>(length);
if (lengthValue == 0) if (lengthValue == 0)
throw ShaderLang::CompilerArrayLengthError{ sourceLocation }; throw ShaderLang::CompilerArrayLengthError{ sourceLocation, std::to_string(lengthValue) };
} }
else else
throw ShaderLang::CompilerArrayLengthError{ sourceLocation }; throw ShaderLang::CompilerArrayLengthError{ sourceLocation, ToString(GetConstantType(length), sourceLocation) };
ArrayType arrayType; ArrayType arrayType;
arrayType.containedType = std::make_unique<ContainedType>(); arrayType.containedType = std::make_unique<ContainedType>();
@ -2326,7 +2332,7 @@ namespace Nz::ShaderAst
// TODO: Add support for integer samplers // TODO: Add support for integer samplers
if (primitiveType != PrimitiveType::Float32) if (primitiveType != PrimitiveType::Float32)
throw ShaderLang::CompilerSamplerUnexpectedTypeError{ sourceLocation }; throw ShaderLang::CompilerSamplerUnexpectedTypeError{ sourceLocation, ToString(exprType, sourceLocation) };
return SamplerType { return SamplerType {
sampler.imageType, primitiveType sampler.imageType, primitiveType
@ -2365,7 +2371,7 @@ namespace Nz::ShaderAst
RegisterIntrinsic("reflect", IntrinsicType::Reflect); RegisterIntrinsic("reflect", IntrinsicType::Reflect);
} }
std::size_t SanitizeVisitor::RegisterAlias(std::string name, std::optional<IdentifierData> aliasData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation) std::size_t SanitizeVisitor::RegisterAlias(std::string name, std::optional<Identifier> aliasData, std::optional<std::size_t> index, const ShaderLang::SourceLocation& sourceLocation)
{ {
if (FindIdentifier(name)) if (FindIdentifier(name))
throw ShaderLang::CompilerIdentifierAlreadyUsedError{ sourceLocation, name }; throw ShaderLang::CompilerIdentifierAlreadyUsedError{ sourceLocation, name };
@ -2553,7 +2559,13 @@ namespace Nz::ShaderAst
std::size_t typeIndex; std::size_t typeIndex;
if (partialType) if (partialType)
typeIndex = m_context->types.Register(std::move(*partialType), index, sourceLocation); {
NamedPartialType namedPartial;
namedPartial.name = name;
namedPartial.type = std::move(*partialType);
typeIndex = m_context->types.Register(std::move(namedPartial), index, sourceLocation);
}
else if (index) else if (index)
{ {
m_context->types.PreregisterIndex(*index, sourceLocation); m_context->types.PreregisterIndex(*index, sourceLocation);
@ -2609,10 +2621,10 @@ namespace Nz::ShaderAst
return varIndex; return varIndex;
} }
auto SanitizeVisitor::ResolveAliasIdentifier(const IdentifierData* identifier, const ShaderLang::SourceLocation& sourceLocation) const -> const IdentifierData* auto SanitizeVisitor::ResolveAliasIdentifier(const Identifier* identifier, const ShaderLang::SourceLocation& sourceLocation) const -> const Identifier*
{ {
while (identifier->category == IdentifierCategory::Alias) while (identifier->target.category == IdentifierCategory::Alias)
identifier = &m_context->aliases.Retrieve(identifier->index, sourceLocation); identifier = &m_context->aliases.Retrieve(identifier->target.index, sourceLocation);
return identifier; return identifier;
} }
@ -2682,7 +2694,7 @@ namespace Nz::ShaderAst
{ {
using T = std::decay_t<decltype(arg)>; using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, IdentifierType> || std::is_same_v<T, StructType> || std::is_same_v<T, UniformType> || std::is_same_v<T, AliasType>) if constexpr (std::is_same_v<T, StructType> || std::is_same_v<T, UniformType> || std::is_same_v<T, AliasType>)
return ResolveStruct(arg, sourceLocation); return ResolveStruct(arg, sourceLocation);
else if constexpr (std::is_same_v<T, NoType> || else if constexpr (std::is_same_v<T, NoType> ||
std::is_same_v<T, ArrayType> || std::is_same_v<T, ArrayType> ||
@ -2695,25 +2707,13 @@ namespace Nz::ShaderAst
std::is_same_v<T, Type> || std::is_same_v<T, Type> ||
std::is_same_v<T, VectorType>) std::is_same_v<T, VectorType>)
{ {
throw ShaderLang::CompilerStructExpectedError{ sourceLocation }; throw ShaderLang::CompilerStructExpectedError{ sourceLocation, ToString(exprType, sourceLocation) };
} }
else else
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor"); static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
}, exprType); }, exprType);
} }
std::size_t SanitizeVisitor::ResolveStruct(const IdentifierType& identifierType, const ShaderLang::SourceLocation& sourceLocation)
{
const IdentifierData* identifierData = FindIdentifier(identifierType.name);
if (!identifierData)
throw ShaderLang::CompilerUnknownIdentifierError{ sourceLocation, identifierType.name };
if (identifierData->category != IdentifierCategory::Struct)
throw ShaderLang::CompilerStructExpectedError{ sourceLocation };
return identifierData->index;
}
std::size_t SanitizeVisitor::ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& /*sourceLocation*/) std::size_t SanitizeVisitor::ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& /*sourceLocation*/)
{ {
return structType.structIndex; return structType.structIndex;
@ -2737,8 +2737,8 @@ namespace Nz::ShaderAst
std::size_t typeIndex = std::get<Type>(exprType).typeIndex; std::size_t typeIndex = std::get<Type>(exprType).typeIndex;
const auto& type = m_context->types.Retrieve(typeIndex, sourceLocation); const auto& type = m_context->types.Retrieve(typeIndex, sourceLocation);
if (std::holds_alternative<PartialType>(type)) if (!std::holds_alternative<ExpressionType>(type))
throw ShaderLang::CompilerFullTypeExpectedError{ sourceLocation }; throw ShaderLang::CompilerFullTypeExpectedError{ sourceLocation, ToString(type, sourceLocation) };
return std::get<ExpressionType>(type); return std::get<ExpressionType>(type);
} }
@ -2799,6 +2799,47 @@ namespace Nz::ShaderAst
return output; return output;
} }
std::string SanitizeVisitor::ToString(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation) const
{
Stringifier stringifier;
stringifier.aliasStringifier = [&](std::size_t aliasIndex)
{
return m_context->aliases.Retrieve(aliasIndex, sourceLocation).name;
};
stringifier.structStringifier = [&](std::size_t structIndex)
{
return m_context->structs.Retrieve(structIndex, sourceLocation)->name;
};
stringifier.typeStringifier = [&](std::size_t typeIndex)
{
return ToString(m_context->types.Retrieve(typeIndex, sourceLocation), sourceLocation);
};
return ShaderAst::ToString(exprType, stringifier);
}
std::string SanitizeVisitor::ToString(const NamedPartialType& partialType, const ShaderLang::SourceLocation& /*sourceLocation*/) const
{
return partialType.name + " (partial)";
}
template<typename... Args>
std::string SanitizeVisitor::ToString(const std::variant<Args...>& value, const ShaderLang::SourceLocation& sourceLocation) const
{
return std::visit([&](auto&& arg)
{
return ToString(arg, sourceLocation);
}, value);
}
void SanitizeVisitor::TypeMustMatch(const ExpressionType& left, const ExpressionType& right, const ShaderLang::SourceLocation& sourceLocation) const
{
if (ResolveAlias(left) != ResolveAlias(right))
throw ShaderLang::CompilerUnmatchingTypesError{ sourceLocation, ToString(left, sourceLocation), ToString(right, sourceLocation) };
}
auto SanitizeVisitor::TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right, const ShaderLang::SourceLocation& sourceLocation) -> ValidationResult auto SanitizeVisitor::TypeMustMatch(const ExpressionPtr& left, const ExpressionPtr& right, const ShaderLang::SourceLocation& sourceLocation) -> ValidationResult
{ {
const ExpressionType* leftType = GetExpressionType(*left); const ExpressionType* leftType = GetExpressionType(*left);
@ -2821,26 +2862,29 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedType = ResolveAlias(*exprType); const ExpressionType& resolvedType = ResolveAlias(*exprType);
IdentifierData targetIdentifier; Identifier aliasIdentifier;
aliasIdentifier.name = node.name;
if (IsStructType(resolvedType)) if (IsStructType(resolvedType))
{ {
std::size_t structIndex = ResolveStruct(resolvedType, node.expression->sourceLocation); std::size_t structIndex = ResolveStruct(resolvedType, node.expression->sourceLocation);
targetIdentifier = { structIndex, IdentifierCategory::Struct }; aliasIdentifier.target = { structIndex, IdentifierCategory::Struct };
} }
else if (IsFunctionType(resolvedType)) else if (IsFunctionType(resolvedType))
{ {
std::size_t funcIndex = std::get<FunctionType>(resolvedType).funcIndex; std::size_t funcIndex = std::get<FunctionType>(resolvedType).funcIndex;
targetIdentifier = { funcIndex, IdentifierCategory::Function }; aliasIdentifier.target = { funcIndex, IdentifierCategory::Function };
} }
else if (IsAliasType(resolvedType)) else if (IsAliasType(resolvedType))
{ {
const AliasType& alias = std::get<AliasType>(resolvedType); const AliasType& alias = std::get<AliasType>(resolvedType);
targetIdentifier = { alias.aliasIndex, IdentifierCategory::Alias }; aliasIdentifier.target = { alias.aliasIndex, IdentifierCategory::Alias };
} }
else else
throw ShaderLang::CompilerAliasUnexpectedTypeError{ node.sourceLocation }; throw ShaderLang::CompilerAliasUnexpectedTypeError{ node.sourceLocation, ToString(*exprType, node.expression->sourceLocation) };
node.aliasIndex = RegisterAlias(node.name, targetIdentifier, node.aliasIndex, node.sourceLocation);
node.aliasIndex = RegisterAlias(node.name, std::move(aliasIdentifier), node.aliasIndex, node.sourceLocation);
return ValidationResult::Validated; return ValidationResult::Validated;
} }
@ -2853,7 +2897,7 @@ namespace Nz::ShaderAst
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
if (ResolveAlias(*conditionType) != ExpressionType{ PrimitiveType::Boolean }) if (ResolveAlias(*conditionType) != ExpressionType{ PrimitiveType::Boolean })
throw ShaderLang::CompilerConditionExpectedBoolError{ node.condition->sourceLocation }; throw ShaderLang::CompilerConditionExpectedBoolError{ node.condition->sourceLocation, ToString(*conditionType, node.condition->sourceLocation) };
return ValidationResult::Validated; return ValidationResult::Validated;
} }
@ -2871,18 +2915,18 @@ namespace Nz::ShaderAst
std::size_t typeIndex = std::get<Type>(resolvedExprType).typeIndex; std::size_t typeIndex = std::get<Type>(resolvedExprType).typeIndex;
const auto& type = m_context->types.Retrieve(typeIndex, node.sourceLocation); const auto& type = m_context->types.Retrieve(typeIndex, node.sourceLocation);
if (!std::holds_alternative<PartialType>(type)) if (!std::holds_alternative<NamedPartialType>(type))
throw ShaderLang::CompilerExpectedPartialTypeError{ node.sourceLocation }; throw ShaderLang::CompilerExpectedPartialTypeError{ node.sourceLocation, ToString(std::get<ExpressionType>(type), node.sourceLocation) };
const PartialType& partialType = std::get<PartialType>(type); const auto& partialType = std::get<NamedPartialType>(type);
if (partialType.parameters.size() != node.indices.size()) if (partialType.type.parameters.size() != node.indices.size())
throw ShaderLang::CompilerPartialTypeParameterCountMismatchError{ node.sourceLocation, SafeCast<UInt32>(partialType.parameters.size()), SafeCast<UInt32>(node.indices.size()) }; throw ShaderLang::CompilerPartialTypeParameterCountMismatchError{ node.sourceLocation, SafeCast<UInt32>(partialType.type.parameters.size()), SafeCast<UInt32>(node.indices.size()) };
StackVector<TypeParameter> parameters = NazaraStackVector(TypeParameter, partialType.parameters.size()); StackVector<TypeParameter> parameters = NazaraStackVector(TypeParameter, partialType.type.parameters.size());
for (std::size_t i = 0; i < partialType.parameters.size(); ++i) for (std::size_t i = 0; i < partialType.type.parameters.size(); ++i)
{ {
const ExpressionPtr& indexExpr = node.indices[i]; const ExpressionPtr& indexExpr = node.indices[i];
switch (partialType.parameters[i]) switch (partialType.type.parameters[i])
{ {
case TypeParameterCategory::ConstantValue: case TypeParameterCategory::ConstantValue:
{ {
@ -2904,7 +2948,7 @@ namespace Nz::ShaderAst
ExpressionType resolvedType = ResolveType(*indexExprType, true, node.sourceLocation); ExpressionType resolvedType = ResolveType(*indexExprType, true, node.sourceLocation);
switch (partialType.parameters[i]) switch (partialType.type.parameters[i])
{ {
case TypeParameterCategory::PrimitiveType: case TypeParameterCategory::PrimitiveType:
{ {
@ -2932,8 +2976,8 @@ namespace Nz::ShaderAst
} }
} }
assert(parameters.size() == partialType.parameters.size()); assert(parameters.size() == partialType.type.parameters.size());
node.cachedExpressionType = partialType.buildFunc(parameters.data(), parameters.size(), node.sourceLocation); node.cachedExpressionType = partialType.type.buildFunc(parameters.data(), parameters.size(), node.sourceLocation);
} }
else else
{ {
@ -2947,11 +2991,11 @@ namespace Nz::ShaderAst
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
if (!IsPrimitiveType(*indexType)) if (!IsPrimitiveType(*indexType))
throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation }; throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation, ToString(*indexType, indexExpr->sourceLocation) };
PrimitiveType primitiveIndexType = std::get<PrimitiveType>(*indexType); PrimitiveType primitiveIndexType = std::get<PrimitiveType>(*indexType);
if (primitiveIndexType != PrimitiveType::Int32 && primitiveIndexType != PrimitiveType::UInt32) if (primitiveIndexType != PrimitiveType::Int32 && primitiveIndexType != PrimitiveType::UInt32)
throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation }; throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation, ToString(*indexType, indexExpr->sourceLocation) };
if (IsArrayType(resolvedExprType)) if (IsArrayType(resolvedExprType))
{ {
@ -2962,7 +3006,7 @@ namespace Nz::ShaderAst
else if (IsStructType(resolvedExprType)) else if (IsStructType(resolvedExprType))
{ {
if (primitiveIndexType != PrimitiveType::Int32) if (primitiveIndexType != PrimitiveType::Int32)
throw ShaderLang::CompilerIndexStructRequiresInt32IndicesError{ node.sourceLocation }; throw ShaderLang::CompilerIndexStructRequiresInt32IndicesError{ node.sourceLocation, ToString(*indexType, indexExpr->sourceLocation) };
ConstantValueExpression& constantExpr = static_cast<ConstantValueExpression&>(*indexExpr); ConstantValueExpression& constantExpr = static_cast<ConstantValueExpression&>(*indexExpr);
@ -2993,7 +3037,7 @@ namespace Nz::ShaderAst
resolvedExprType = swizzledVec.type; resolvedExprType = swizzledVec.type;
} }
else else
throw ShaderLang::CompilerIndexUnexpectedTypeError{ node.sourceLocation }; throw ShaderLang::CompilerIndexUnexpectedTypeError{ node.sourceLocation, ToString(*indexType, indexExpr->sourceLocation) };
} }
node.cachedExpressionType = std::move(resolvedExprType); node.cachedExpressionType = std::move(resolvedExprType);
@ -3072,11 +3116,11 @@ namespace Nz::ShaderAst
{ {
const auto& alias = static_cast<AliasValueExpression&>(*node.targetFunction); const auto& alias = static_cast<AliasValueExpression&>(*node.targetFunction);
const IdentifierData* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), node.sourceLocation); const Identifier* aliasIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), node.sourceLocation);
if (targetIdentifier->category != IdentifierCategory::Function) if (aliasIdentifier->target.category != IdentifierCategory::Function)
throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation }; throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation };
targetFuncIndex = targetIdentifier->index; targetFuncIndex = aliasIdentifier->target.index;
} }
else else
throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation }; throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation };
@ -3095,7 +3139,7 @@ namespace Nz::ShaderAst
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
if (ResolveAlias(*parameterType) != ResolveAlias(referenceDeclaration->parameters[i].type.GetResultingValue())) if (ResolveAlias(*parameterType) != ResolveAlias(referenceDeclaration->parameters[i].type.GetResultingValue()))
throw ShaderLang::CompilerFunctionCallUnmatchingParameterTypeError{ node.sourceLocation, referenceDeclaration->name, SafeCast<UInt32>(i) }; throw ShaderLang::CompilerFunctionCallUnmatchingParameterTypeError{ node.sourceLocation, referenceDeclaration->name, SafeCast<UInt32>(i), ToString(referenceDeclaration->parameters[i].type.GetResultingValue(), referenceDeclaration->parameters[i].sourceLocation), ToString(*parameterType, node.parameters[i]->sourceLocation) };
} }
if (node.parameters.size() != referenceDeclaration->parameters.size()) if (node.parameters.size() != referenceDeclaration->parameters.size())
@ -3126,18 +3170,21 @@ namespace Nz::ShaderAst
if (IsMatrixType(ResolveAlias(*firstExprType))) if (IsMatrixType(ResolveAlias(*firstExprType)))
{ {
if (node.expressions[1]) if (node.expressions[1])
throw ShaderLang::CompilerCastComponentMismatchError{ node.expressions[1]->sourceLocation }; throw ShaderLang::CompilerCastComponentMismatchError{ node.expressions[1]->sourceLocation, 2, 1 }; //< get real component count
// Matrix to matrix cast: always valid // Matrix to matrix cast: always valid
} }
else else
{ {
assert(targetMatrixType.columnCount <= 4); assert(targetMatrixType.columnCount <= 4);
UInt32 expressionCount = 0;
for (std::size_t i = 0; i < targetMatrixType.columnCount; ++i) for (std::size_t i = 0; i < targetMatrixType.columnCount; ++i)
{ {
const auto& exprPtr = node.expressions[i]; const auto& exprPtr = node.expressions[i];
if (!exprPtr) if (!exprPtr)
throw ShaderLang::CompilerCastComponentMismatchError{ node.sourceLocation }; throw ShaderLang::CompilerCastComponentMismatchError{ node.sourceLocation, expressionCount, SafeCast<UInt32>(targetMatrixType.columnCount) };
expressionCount++;
const ExpressionType* exprType = GetExpressionType(*exprPtr); const ExpressionType* exprType = GetExpressionType(*exprPtr);
if (!exprType) if (!exprType)
@ -3145,7 +3192,7 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedExprType = ResolveAlias(*exprType); const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
if (!IsVectorType(resolvedExprType)) if (!IsVectorType(resolvedExprType))
throw ShaderLang::CompilerCastMatrixExpectedVectorError{ node.sourceLocation }; throw ShaderLang::CompilerCastMatrixExpectedVectorError{ node.sourceLocation, ToString(resolvedExprType, node.expressions[i]->sourceLocation) };
const VectorType& vecType = std::get<VectorType>(resolvedExprType); const VectorType& vecType = std::get<VectorType>(resolvedExprType);
if (vecType.componentCount != targetMatrixType.rowCount) if (vecType.componentCount != targetMatrixType.rowCount)
@ -3180,13 +3227,13 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedExprType = ResolveAlias(*exprType); const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType)) if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType))
throw ShaderLang::CompilerCastIncompatibleTypesError{ exprPtr->sourceLocation }; throw ShaderLang::CompilerCastIncompatibleTypesError{ exprPtr->sourceLocation, ToString(targetType, node.sourceLocation), ToString(resolvedExprType, exprPtr->sourceLocation) };
componentCount += GetComponentCount(resolvedExprType); componentCount += GetComponentCount(resolvedExprType);
} }
if (componentCount != requiredComponents) if (componentCount != requiredComponents)
throw ShaderLang::CompilerCastComponentMismatchError{ node.sourceLocation }; throw ShaderLang::CompilerCastComponentMismatchError{ node.sourceLocation, SafeCast<UInt32>(componentCount), SafeCast<UInt32>(requiredComponents) };
} }
node.cachedExpressionType = targetType; node.cachedExpressionType = targetType;
@ -3309,7 +3356,7 @@ namespace Nz::ShaderAst
case IntrinsicType::CrossProduct: case IntrinsicType::CrossProduct:
if (IsUnresolved(ValidateIntrinsicParamCount<2>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<2>(node))
|| IsUnresolved(ValidateIntrinsicParamMatchingType(node)) || IsUnresolved(ValidateIntrinsicParamMatchingType(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector, "floating-point vector")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
return SetReturnTypeToFirstParameterType(); return SetReturnTypeToFirstParameterType();
@ -3317,7 +3364,7 @@ namespace Nz::ShaderAst
case IntrinsicType::DotProduct: case IntrinsicType::DotProduct:
if (IsUnresolved(ValidateIntrinsicParamCount<2>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<2>(node))
|| IsUnresolved(ValidateIntrinsicParamMatchingType(node)) || IsUnresolved(ValidateIntrinsicParamMatchingType(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector, "floating-point vector")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
return SetReturnTypeToFirstParameterInnerType(); return SetReturnTypeToFirstParameterInnerType();
@ -3331,7 +3378,7 @@ namespace Nz::ShaderAst
case IntrinsicType::Length: case IntrinsicType::Length:
if (IsUnresolved(ValidateIntrinsicParamCount<1>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<1>(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector, "floating-point vector")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
return SetReturnTypeToFirstParameterInnerType(); return SetReturnTypeToFirstParameterInnerType();
@ -3347,7 +3394,7 @@ namespace Nz::ShaderAst
case IntrinsicType::Normalize: case IntrinsicType::Normalize:
if (IsUnresolved(ValidateIntrinsicParamCount<1>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<1>(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector, "floating-point vector")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
return SetReturnTypeToFirstParameterType(); return SetReturnTypeToFirstParameterType();
@ -3363,7 +3410,7 @@ namespace Nz::ShaderAst
case IntrinsicType::Reflect: case IntrinsicType::Reflect:
if (IsUnresolved(ValidateIntrinsicParamCount<2>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<2>(node))
|| IsUnresolved(ValidateIntrinsicParamMatchingType(node)) || IsUnresolved(ValidateIntrinsicParamMatchingType(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsFloatingPointVector, "floating-point vector")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
return SetReturnTypeToFirstParameterType(); return SetReturnTypeToFirstParameterType();
@ -3371,7 +3418,7 @@ namespace Nz::ShaderAst
case IntrinsicType::SampleTexture: case IntrinsicType::SampleTexture:
{ {
if (IsUnresolved(ValidateIntrinsicParamCount<2>(node)) if (IsUnresolved(ValidateIntrinsicParamCount<2>(node))
|| IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsSamplerType))) || IsUnresolved(ValidateIntrinsicParameterType<0>(node, IsSamplerType, "sampler type")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
// Special check: vector dimensions must match sample type // Special check: vector dimensions must match sample type
@ -3403,7 +3450,7 @@ namespace Nz::ShaderAst
return type == ExpressionType{ VectorType{ requiredComponentCount, PrimitiveType::Float32 } }; return type == ExpressionType{ VectorType{ requiredComponentCount, PrimitiveType::Float32 } };
}; };
if (IsUnresolved(ValidateIntrinsicParameterType<1>(node, IsRightType))) if (IsUnresolved(ValidateIntrinsicParameterType<1>(node, IsRightType, "sampler of requirement components")))
return ValidationResult::Unresolved; return ValidationResult::Unresolved;
node.cachedExpressionType = VectorType{ 4, samplerType.sampledType }; node.cachedExpressionType = VectorType{ 4, samplerType.sampledType };
@ -3423,7 +3470,7 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedExprType = ResolveAlias(*exprType); const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType)) if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType))
throw ShaderLang::CompilerSwizzleUnexpectedTypeError{ node.sourceLocation }; throw ShaderLang::CompilerSwizzleUnexpectedTypeError{ node.sourceLocation, ToString(*exprType, node.expression->sourceLocation) };
PrimitiveType baseType; PrimitiveType baseType;
std::size_t componentCount; std::size_t componentCount;
@ -3477,7 +3524,7 @@ namespace Nz::ShaderAst
case UnaryType::LogicalNot: case UnaryType::LogicalNot:
{ {
if (resolvedExprType != ExpressionType(PrimitiveType::Boolean)) if (resolvedExprType != ExpressionType(PrimitiveType::Boolean))
throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation }; throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation, ToString(*exprType, node.sourceLocation) };
break; break;
} }
@ -3491,10 +3538,10 @@ namespace Nz::ShaderAst
else if (IsVectorType(resolvedExprType)) else if (IsVectorType(resolvedExprType))
basicType = std::get<VectorType>(resolvedExprType).type; basicType = std::get<VectorType>(resolvedExprType).type;
else else
throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation }; throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation, ToString(*exprType, node.sourceLocation) };
if (basicType != PrimitiveType::Float32 && basicType != PrimitiveType::Int32 && basicType != PrimitiveType::UInt32) if (basicType != PrimitiveType::Float32 && basicType != PrimitiveType::Int32 && basicType != PrimitiveType::UInt32)
throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation }; throw ShaderLang::CompilerUnaryUnsupportedError{ node.sourceLocation, ToString(*exprType, node.sourceLocation) };
break; break;
} }
@ -3513,10 +3560,10 @@ namespace Nz::ShaderAst
ExpressionType SanitizeVisitor::ValidateBinaryOp(BinaryType op, const ExpressionType& leftExprType, const ExpressionType& rightExprType, const ShaderLang::SourceLocation& sourceLocation) ExpressionType SanitizeVisitor::ValidateBinaryOp(BinaryType op, const ExpressionType& leftExprType, const ExpressionType& rightExprType, const ShaderLang::SourceLocation& sourceLocation)
{ {
if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType)) if (!IsPrimitiveType(leftExprType) && !IsMatrixType(leftExprType) && !IsVectorType(leftExprType))
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType)) if (!IsPrimitiveType(rightExprType) && !IsMatrixType(rightExprType) && !IsVectorType(rightExprType))
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "right" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "right", ToString(rightExprType, sourceLocation) };
if (IsPrimitiveType(leftExprType)) if (IsPrimitiveType(leftExprType))
{ {
@ -3528,7 +3575,7 @@ namespace Nz::ShaderAst
case BinaryType::CompLe: case BinaryType::CompLe:
case BinaryType::CompLt: case BinaryType::CompLt:
if (leftType == PrimitiveType::Boolean) if (leftType == PrimitiveType::Boolean)
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
[[fallthrough]]; [[fallthrough]];
case BinaryType::CompEq: case BinaryType::CompEq:
@ -3568,16 +3615,16 @@ namespace Nz::ShaderAst
return rightExprType; return rightExprType;
} }
else else
throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation }; throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation, ToString(leftExprType, sourceLocation), ToString(rightExprType, sourceLocation) };
break; break;
} }
case PrimitiveType::Boolean: case PrimitiveType::Boolean:
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
default: default:
throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation }; throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation, ToString(leftExprType, sourceLocation), ToString(rightExprType, sourceLocation) };
} }
} }
@ -3585,7 +3632,7 @@ namespace Nz::ShaderAst
case BinaryType::LogicalOr: case BinaryType::LogicalOr:
{ {
if (leftType != PrimitiveType::Boolean) if (leftType != PrimitiveType::Boolean)
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
TypeMustMatch(leftExprType, rightExprType, sourceLocation); TypeMustMatch(leftExprType, rightExprType, sourceLocation);
return PrimitiveType::Boolean; return PrimitiveType::Boolean;
@ -3630,17 +3677,17 @@ namespace Nz::ShaderAst
TypeMustMatch(leftType.type, rightType.type, sourceLocation); TypeMustMatch(leftType.type, rightType.type, sourceLocation);
if (leftType.columnCount != rightType.componentCount) if (leftType.columnCount != rightType.componentCount)
throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation }; throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation, ToString(leftExprType, sourceLocation), ToString(rightExprType, sourceLocation) };
return rightExprType; return rightExprType;
} }
else else
throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation }; throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation, ToString(leftExprType, sourceLocation), ToString(rightExprType, sourceLocation) };
} }
case BinaryType::LogicalAnd: case BinaryType::LogicalAnd:
case BinaryType::LogicalOr: case BinaryType::LogicalOr:
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
} }
} }
else if (IsVectorType(leftExprType)) else if (IsVectorType(leftExprType))
@ -3676,20 +3723,21 @@ namespace Nz::ShaderAst
return rightExprType; return rightExprType;
} }
else else
throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation }; throw ShaderLang::CompilerBinaryIncompatibleTypesError{ sourceLocation, ToString(leftExprType, sourceLocation), ToString(rightExprType, sourceLocation) };
break; break;
} }
case BinaryType::LogicalAnd: case BinaryType::LogicalAnd:
case BinaryType::LogicalOr: case BinaryType::LogicalOr:
throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left" }; throw ShaderLang::CompilerBinaryUnsupportedError{ sourceLocation, "left", ToString(leftExprType, sourceLocation) };
} }
} }
throw ShaderLang::AstInternalError{ sourceLocation, "unchecked operation" }; throw ShaderLang::AstInternalError{ sourceLocation, "unchecked operation" };
} }
template<std::size_t N> template<std::size_t N>
auto SanitizeVisitor::ValidateIntrinsicParamCount(IntrinsicExpression& node) -> ValidationResult auto SanitizeVisitor::ValidateIntrinsicParamCount(IntrinsicExpression& node) -> ValidationResult
{ {
@ -3737,7 +3785,7 @@ namespace Nz::ShaderAst
} }
template<std::size_t N, typename F> template<std::size_t N, typename F>
auto SanitizeVisitor::ValidateIntrinsicParameterType(IntrinsicExpression& node, F&& func) -> ValidationResult auto SanitizeVisitor::ValidateIntrinsicParameterType(IntrinsicExpression& node, F&& func, const char* typeStr) -> ValidationResult
{ {
assert(node.parameters.size() > N); assert(node.parameters.size() > N);
auto& parameter = MandatoryExpr(node.parameters[N], node.sourceLocation); auto& parameter = MandatoryExpr(node.parameters[N], node.sourceLocation);
@ -3748,7 +3796,7 @@ namespace Nz::ShaderAst
const ExpressionType& resolvedType = ResolveAlias(*type); const ExpressionType& resolvedType = ResolveAlias(*type);
if (!func(resolvedType)) if (!func(resolvedType))
throw ShaderLang::CompilerIntrinsicExpectedTypeError{ parameter.sourceLocation, SafeCast<UInt32>(N) }; throw ShaderLang::CompilerIntrinsicExpectedTypeError{ parameter.sourceLocation, SafeCast<UInt32>(N), typeStr, ToString(*type, parameter.sourceLocation)};
return ValidationResult::Validated; return ValidationResult::Validated;
} }
@ -3769,12 +3817,6 @@ namespace Nz::ShaderAst
return *node; return *node;
} }
void SanitizeVisitor::TypeMustMatch(const ExpressionType& left, const ExpressionType& right, const ShaderLang::SourceLocation& sourceLocation)
{
if (ResolveAlias(left) != ResolveAlias(right))
throw ShaderLang::CompilerUnmatchingTypesError{ sourceLocation };
}
StatementPtr SanitizeVisitor::Unscope(StatementPtr node) StatementPtr SanitizeVisitor::Unscope(StatementPtr node)
{ {
assert(node); assert(node);

View File

@ -312,11 +312,6 @@ namespace Nz
throw std::runtime_error("unexpected FunctionType"); throw std::runtime_error("unexpected FunctionType");
} }
void GlslWriter::Append(const ShaderAst::IdentifierType& /*identifierType*/)
{
throw std::runtime_error("unexpected identifier type");
}
void GlslWriter::Append(const ShaderAst::IntrinsicFunctionType& /*intrinsicFunctionType*/) void GlslWriter::Append(const ShaderAst::IntrinsicFunctionType& /*intrinsicFunctionType*/)
{ {
throw std::runtime_error("unexpected intrinsic function type"); throw std::runtime_error("unexpected intrinsic function type");

View File

@ -187,11 +187,6 @@ namespace Nz
throw std::runtime_error("unexpected function type"); throw std::runtime_error("unexpected function type");
} }
void LangWriter::Append(const ShaderAst::IdentifierType& identifierType)
{
Append(identifierType.name);
}
void LangWriter::Append(const ShaderAst::IntrinsicFunctionType& /*functionType*/) void LangWriter::Append(const ShaderAst::IntrinsicFunctionType& /*functionType*/)
{ {
throw std::runtime_error("unexpected intrinsic function type"); throw std::runtime_error("unexpected intrinsic function type");

View File

@ -58,6 +58,25 @@ struct fmt::formatter<Nz::ShaderLang::ErrorCategory> : formatter<string_view>
} }
}; };
template <>
struct fmt::formatter<Nz::ShaderLang::ErrorType> : formatter<string_view>
{
template <typename FormatContext>
auto format(const Nz::ShaderLang::ErrorType& p, FormatContext& ctx) -> decltype(ctx.out())
{
// TODO: Add ToString
std::string_view name = "<unhandled error type>";
switch (p)
{
#define NAZARA_SHADERLANG_ERROR(ErrorPrefix, ErrorName, ...) case Nz::ShaderLang::ErrorType:: ErrorPrefix ## ErrorName: name = #ErrorPrefix #ErrorName; break;
#include <Nazara/Shader/ShaderLangErrorList.hpp>
}
return formatter<string_view>::format(name, ctx);
}
};
template <> template <>
struct fmt::formatter<Nz::ShaderStageType> : formatter<string_view> struct fmt::formatter<Nz::ShaderStageType> : formatter<string_view>
{ {
@ -123,10 +142,10 @@ namespace Nz::ShaderLang
return std::apply([&](const auto... args) { return fmt::format(ErrorString, args...); }, m_parameters); \ return std::apply([&](const auto... args) { return fmt::format(ErrorString, args...); }, m_parameters); \
} }
#define NAZARA_SHADERLANG_AST_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Ast, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_AST_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Ast, A, ErrorName, ErrorString, __VA_ARGS__)
#define NAZARA_SHADERLANG_LEXER_ERROR(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Lexer, ErrorType, 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(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Parser, ErrorType, 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(ErrorType, ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Compiler, ErrorType, ErrorName, ErrorString, __VA_ARGS__) #define NAZARA_SHADERLANG_COMPILER_ERROR(ErrorName, ErrorString, ...) NAZARA_SHADERLANG_NEWERRORTYPE(Compiler, C, ErrorName, ErrorString, __VA_ARGS__)
#include <Nazara/Shader/ShaderLangErrorList.hpp> #include <Nazara/Shader/ShaderLangErrorList.hpp>

View File

@ -704,12 +704,6 @@ namespace Nz
}, type); }, type);
} }
auto SpirvConstantCache::BuildType(const ShaderAst::IdentifierType& /*type*/) const -> TypePtr
{
// No IdentifierType is expected (as they should have been resolved by now)
throw std::runtime_error("unexpected identifier");
}
auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) const -> TypePtr auto SpirvConstantCache::BuildType(const ShaderAst::PrimitiveType& type) const -> TypePtr
{ {
return std::make_shared<Type>([&]() -> AnyType return std::make_shared<Type>([&]() -> AnyType

View File

@ -491,7 +491,7 @@ Nz::ShaderAst::ModulePtr ShaderGraph::ToModule() const
extVar.bindingIndex = buffer.bindingIndex; extVar.bindingIndex = buffer.bindingIndex;
extVar.bindingSet = buffer.setIndex; extVar.bindingSet = buffer.setIndex;
extVar.name = buffer.name; extVar.name = buffer.name;
extVar.type = Nz::ShaderAst::ExpressionType{ Nz::ShaderAst::IdentifierType{ structInfo.name } }; extVar.type = Nz::ShaderAst::ExpressionPtr{ Nz::ShaderBuilder::Identifier(structInfo.name) };
} }
for (const auto& texture : m_textures) for (const auto& texture : m_textures)
@ -553,9 +553,9 @@ Nz::ShaderAst::ModulePtr ShaderGraph::ToModule() const
return shaderModule; return shaderModule;
} }
Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(const std::variant<PrimitiveType, std::size_t>& type) const Nz::ShaderAst::ExpressionValue<Nz::ShaderAst::ExpressionType> ShaderGraph::ToShaderExpressionType(const std::variant<PrimitiveType, std::size_t>& type) const
{ {
return std::visit([&](auto&& arg) -> Nz::ShaderAst::ExpressionType return std::visit([&](auto&& arg) -> Nz::ShaderAst::ExpressionValue<Nz::ShaderAst::ExpressionType>
{ {
using T = std::decay_t<decltype(arg)>; using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, PrimitiveType>) if constexpr (std::is_same_v<T, PrimitiveType>)
@ -564,7 +564,7 @@ Nz::ShaderAst::ExpressionType ShaderGraph::ToShaderExpressionType(const std::var
{ {
assert(arg < m_structs.size()); assert(arg < m_structs.size());
const auto& s = m_structs[arg]; const auto& s = m_structs[arg];
return Nz::ShaderAst::IdentifierType{ s.name }; return Nz::ShaderAst::ExpressionPtr{ Nz::ShaderBuilder::Identifier(s.name) };
} }
else else
static_assert(Nz::AlwaysFalse<T>::value, "non-exhaustive visitor"); static_assert(Nz::AlwaysFalse<T>::value, "non-exhaustive visitor");

View File

@ -68,7 +68,7 @@ class ShaderGraph
QJsonObject Save(); QJsonObject Save();
Nz::ShaderAst::ModulePtr ToModule() const; Nz::ShaderAst::ModulePtr ToModule() const;
Nz::ShaderAst::ExpressionType ToShaderExpressionType(const std::variant<PrimitiveType, std::size_t>& type) const; Nz::ShaderAst::ExpressionValue<Nz::ShaderAst::ExpressionType> ToShaderExpressionType(const std::variant<PrimitiveType, std::size_t>& type) const;
void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t setIndex, std::size_t bindingIndex); void UpdateBuffer(std::size_t bufferIndex, std::string name, BufferType bufferType, std::size_t structIndex, std::size_t setIndex, std::size_t bindingIndex);
void UpdateOption(std::size_t optionIndex, std::string option); void UpdateOption(std::size_t optionIndex, std::string option);