diff options
| -rw-r--r-- | source/slang/decl-defs.h | 5 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 38 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 27 | ||||
| -rw-r--r-- | source/slang/type-defs.h | 23 | ||||
| -rw-r--r-- | tests/compute/assoctype-simple.slang | 34 |
5 files changed, 124 insertions, 3 deletions
diff --git a/source/slang/decl-defs.h b/source/slang/decl-defs.h index c96fe6d09..4021f5a38 100644 --- a/source/slang/decl-defs.h +++ b/source/slang/decl-defs.h @@ -122,6 +122,11 @@ SYNTAX_CLASS(TypeDefDecl, SimpleTypeDecl) SYNTAX_FIELD(TypeExp, type) END_SYNTAX_CLASS() +// An 'assoctype' declaration +SYNTAX_CLASS(AssocTypeDecl, SimpleTypeDecl) + SYNTAX_FIELD(TypeExp, constraint) +END_SYNTAX_CLASS() + // A scope for local declarations (e.g., as part of a statement) SIMPLE_SYNTAX_CLASS(ScopeDecl, ContainerDecl) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 322f403e6..554eebc18 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -544,6 +544,21 @@ namespace Slang return typeDefDecl; } + RefPtr<RefObject> ParseAssocType(Parser * parser, void *) + { + RefPtr<AssocTypeDecl> assocTypeDecl = new AssocTypeDecl(); + + auto nameToken = parser->ReadToken(TokenType::Identifier); + assocTypeDecl->nameAndLoc = NameLoc(nameToken); + assocTypeDecl->loc = nameToken.loc; + if (parser->LookAheadToken(TokenType::Colon)) + { + auto type = parser->ParseTypeExp(); + assocTypeDecl->constraint = type; + } + return assocTypeDecl; + } + // Add a modifier to a list of modifiers being built static void AddModifier(RefPtr<Modifier>** ioModifierLink, RefPtr<Modifier> modifier) { @@ -1396,6 +1411,16 @@ namespace Slang return genericApp; } + static RefPtr<Expr> parseMemberType(Parser * parser, RefPtr<Expr> base) + { + RefPtr<MemberExpr> memberExpr = new MemberExpr(); + parser->ReadToken(TokenType::Dot); + parser->FillPosition(memberExpr.Ptr()); + memberExpr->BaseExpression = base; + memberExpr->name = expectIdentifier(parser).name; + return memberExpr; + } + // Parse option `[]` braces after a type expression, that indicate an array type static RefPtr<Expr> parsePostfixTypeSuffix( Parser* parser, @@ -1452,9 +1477,16 @@ namespace Slang RefPtr<Expr> typeExpr = basicType; - if (parser->LookAheadToken(TokenType::OpLess)) + while (parser->LookAheadToken(TokenType::OpLess) || parser->LookAheadToken(TokenType::Dot)) { - typeExpr = parseGenericApp(parser, typeExpr); + if (parser->LookAheadToken(TokenType::OpLess)) + { + typeExpr = parseGenericApp(parser, typeExpr); + } + else + { + typeExpr = parseMemberType(parser, typeExpr); + } } // GLSL allows `[]` directly in a type specifier @@ -4029,8 +4061,8 @@ namespace Slang // Add syntax for declaration keywords #define DECL(KEYWORD, CALLBACK) \ addBuiltinSyntax<Decl>(session, scope, #KEYWORD, &CALLBACK) - DECL(typedef, ParseTypeDef); + DECL(assoctype, ParseAssocType); DECL(cbuffer, parseHLSLCBufferDecl); DECL(tbuffer, parseHLSLTBufferDecl); DECL(__generic, ParseGenericDecl); diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 6cf3fd7c9..165b2d132 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -940,6 +940,33 @@ void Type::accept(IValVisitor* visitor, void* extra) return this; } + // AssocTypeDeclRefType + + String AssocTypeDeclRefType::ToString() + { + // TODO: what is appropriate here? + return "<AssocType>"; + } + + bool AssocTypeDeclRefType::EqualsImpl(Type * type) + { + if (auto assocTypeDeclRefType = type->As<AssocTypeDeclRefType>()) + { + return declRef.Equals(assocTypeDeclRefType->declRef); + } + return false; + } + + int AssocTypeDeclRefType::GetHashCode() + { + return declRef.GetHashCode(); + } + + Type* AssocTypeDeclRefType::CreateCanonicalType() + { + return this; + } + // ArithmeticExpressionType // VectorExpressionType diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 2010d07b4..7648e0b87 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -491,3 +491,26 @@ protected: virtual Type* CreateCanonicalType() override; ) END_SYNTAX_CLASS() + +// The "type" of an expression that references a asscoiated type decl (via 'assoctype' keyword). +SYNTAX_CLASS(AssocTypeDeclRefType, Type) + DECL_FIELD(DeclRef<AssocTypeDecl>, declRef) + RAW( + AssocTypeDeclRefType() + {} + AssocTypeDeclRefType( + DeclRef<AssocTypeDecl> declRef) + : declRef(declRef) + {} + + + DeclRef<AssocTypeDecl> const& GetDeclRef() const { return declRef; } + + virtual String ToString() override; + + protected: + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual Type* CreateCanonicalType() override; + ) +END_SYNTAX_CLASS()
\ No newline at end of file diff --git a/tests/compute/assoctype-simple.slang b/tests/compute/assoctype-simple.slang new file mode 100644 index 000000000..5a2c339a6 --- /dev/null +++ b/tests/compute/assoctype-simple.slang @@ -0,0 +1,34 @@ +//TEST(smoke,compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +// Confirm that generics syntax can be used in user +// code and generates valid output. + +RWStructuredBuffer<float> outputBuffer; + +interface ISimple +{ + assoctype T; + T add(T v0, T v1); +} + +struct Simple : ISimple +{ + typedef float T; + T add(T v0, float v1) + { + return v0 + v1; + } +}; + +__generic<T:ISimple> +T.T test(T simple, T.T v0, T.T v1) +{ + return simple.add(v0, v1); +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + float outVal = test<Simple>(Simple(), 2.0, 1.0); // == 3.0 + outputBuffer[tid] = outVal; +}
\ No newline at end of file |
