From 093bf1eb9149ba82258b5a5a159b2f54263b17c2 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 31 Oct 2017 11:12:08 -0400 Subject: work in-progress: type checking associated types --- source/slang/parser.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'source/slang/parser.cpp') diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 554eebc18..224450a66 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -544,21 +544,6 @@ namespace Slang return typeDefDecl; } - RefPtr ParseAssocType(Parser * parser, void *) - { - RefPtr 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** ioModifierLink, RefPtr modifier) { @@ -2102,7 +2087,7 @@ namespace Slang return decl; } - static void parseOptionalInheritanceClause(Parser* parser, AggTypeDecl* decl) + static void parseOptionalInheritanceClause(Parser* parser, ContainerDecl* decl) { if( AdvanceIf(parser, TokenType::Colon) ) { @@ -2121,6 +2106,18 @@ namespace Slang } } + RefPtr ParseAssocType(Parser * parser, void *) + { + RefPtr assocTypeDecl = new AssocTypeDecl(); + + auto nameToken = parser->ReadToken(TokenType::Identifier); + assocTypeDecl->nameAndLoc = NameLoc(nameToken); + assocTypeDecl->loc = nameToken.loc; + parseOptionalInheritanceClause(parser, assocTypeDecl.Ptr()); + parser->ReadToken(TokenType::Semicolon); + return assocTypeDecl; + } + static RefPtr parseInterfaceDecl(Parser* parser, void* /*userData*/) { RefPtr decl = new InterfaceDecl(); @@ -4062,7 +4059,7 @@ namespace Slang #define DECL(KEYWORD, CALLBACK) \ addBuiltinSyntax(session, scope, #KEYWORD, &CALLBACK) DECL(typedef, ParseTypeDef); - DECL(assoctype, ParseAssocType); + DECL(associatedtype,ParseAssocType); DECL(cbuffer, parseHLSLCBufferDecl); DECL(tbuffer, parseHLSLTBufferDecl); DECL(__generic, ParseGenericDecl); -- cgit v1.2.3 From d5e2319c33115d0241dd9d2047c0a5f029553dde Mon Sep 17 00:00:00 2001 From: "YONGH\\yongh" Date: Thu, 2 Nov 2017 19:21:15 -0400 Subject: work inprogress --- source/slang/check.cpp | 53 +++++++++++++++--------- source/slang/lookup.cpp | 21 ++++++++++ source/slang/parser.cpp | 25 +++++++++++- source/slang/syntax.cpp | 36 ++-------------- tests/compute/assoctype-complex.slang | 59 +++++++++++++++++++++++++++ tests/compute/assoctype-complex.slang._ignore | 44 -------------------- tests/compute/generics-constraint1.slang | 17 ++++++++ 7 files changed, 157 insertions(+), 98 deletions(-) create mode 100644 tests/compute/assoctype-complex.slang delete mode 100644 tests/compute/assoctype-complex.slang._ignore create mode 100644 tests/compute/generics-constraint1.slang (limited to 'source/slang/parser.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 2f4ed2ce8..dc4e48545 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -169,23 +169,18 @@ namespace Slang sexpr->declRef = declRef; expr = sexpr; } - if (auto assocTypeDeclRef = declRef.As()) + if (auto constraintType = expr->type->As()) { - if (auto genConstraintType = baseExpr->type->As()) - { - // if this is a reference from a generic parameter, we need to generate a AssocTypeDeclRefType type. - // for example, if we have an expression T.U where T:ISimple, and U is an associated type defined in ISimple. - // then this expression should evaluate to AssocTypeDeclRefType(T, U). - auto assocTypeDeclType = new AssocTypeDeclRefType(); - assocTypeDeclType->declRef = assocTypeDeclRef; - assocTypeDeclType->sourceType = genConstraintType->subType; - assocTypeDeclType->setSession(getSession()); - expr->type = QualType(getTypeType(assocTypeDeclType)); - } + if (baseExpr->type->As()) + constraintType->subType = baseExpr->type->As()->type; + else + constraintType->subType = baseExpr->type; + } - else if (auto funcDeclRef = declRef.As()) + + if (auto genConstraintType = baseExpr->type->As()) { - if (auto genConstraintType = baseExpr->type->As()) + if (auto funcDeclRef = declRef.As()) { // if this is call expression, propagate the source associated type to the result type auto funcType = expr->type->As(); @@ -201,9 +196,24 @@ namespace Slang newFuncType->setSession(funcType->getSession()); expr->type = QualType(newFuncType); } - + } + else if (auto assocTypeDeclRef = declRef.As()) + { + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = genConstraintType->subType; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); } } + else if (auto assocTypeDeclRef = declRef.As()) + { + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = baseExpr->type; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); + } return expr; } else @@ -1262,6 +1272,14 @@ namespace Slang checkDecl(genericDecl->inner); } + void visitGenericTypeConstraintDecl(GenericTypeConstraintDecl * genericConstraintDecl) + { + // check the type being inherited from + auto base = genericConstraintDecl->sup; + base = TranslateTypeNode(base); + genericConstraintDecl->sup = base; + } + void visitInheritanceDecl(InheritanceDecl* inheritanceDecl) { // check the type being inherited from @@ -1325,11 +1343,6 @@ namespace Slang // These are only used in the stdlib, so no checking is needed for now } - void visitGenericTypeConstraintDecl(GenericTypeConstraintDecl*) - { - // These are only used in the stdlib, so no checking is needed for now - } - void visitModifier(Modifier*) { // Do nothing with modifiers for now diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp index c0cb657c4..b97dac560 100644 --- a/source/slang/lookup.cpp +++ b/source/slang/lookup.cpp @@ -453,6 +453,27 @@ void lookUpMemberImpl( } } } + else if (auto assocTypeDeclRefType = type->As()) + { + auto assocTypeDeclRef = assocTypeDeclRefType->declRef; + for (auto constraintDeclRef : getMembersOfType(assocTypeDeclRef)) + { + // The super-type in the constraint (e.g., `Foo` in `T : Foo`) + // will tell us a type we should use for lookup. + auto bound = GetSup(constraintDeclRef); + + // Go ahead and use the target type, with an appropriate breadcrumb + // to indicate that we indirected through a type constraint. + + BreadcrumbInfo breadcrumb; + breadcrumb.prev = inBreadcrumbs; + breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint; + breadcrumb.declRef = constraintDeclRef; + + // TODO: Need to consider case where this might recurse infinitely. + lookUpMemberImpl(session, semantics, name, bound, ioResult, &breadcrumb); + } + } } LookupResult lookUpMember( diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 224450a66..bf85356db 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -2113,7 +2113,30 @@ namespace Slang auto nameToken = parser->ReadToken(TokenType::Identifier); assocTypeDecl->nameAndLoc = NameLoc(nameToken); assocTypeDecl->loc = nameToken.loc; - parseOptionalInheritanceClause(parser, assocTypeDecl.Ptr()); + if (AdvanceIf(parser, TokenType::Colon)) + { + while (!parser->tokenReader.IsAtEnd()) + { + auto paramConstraint = new GenericTypeConstraintDecl(); + parser->FillPosition(paramConstraint); + + auto paramType = DeclRefType::Create( + parser->getSession(), + DeclRef(assocTypeDecl, nullptr)); + + auto paramTypeExpr = new SharedTypeExpr(); + paramTypeExpr->loc = assocTypeDecl->loc; + paramTypeExpr->base.type = paramType; + paramTypeExpr->type = QualType(getTypeType(paramType)); + + paramConstraint->sub = TypeExp(paramTypeExpr); + paramConstraint->sup = parser->ParseTypeExp(); + + AddMember(assocTypeDecl, paramConstraint); + if (!AdvanceIf(parser, TokenType::Comma)) + break; + } + } parser->ReadToken(TokenType::Semicolon); return assocTypeDecl; } diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index fd7fc0e14..3e38955ba 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -961,7 +961,8 @@ void Type::accept(IValVisitor* visitor, void* extra) { if (!sourceType) return this; - if (auto parentDeclRefType = sourceType->As()) + auto substSourceType = sourceType->SubstituteImpl(subst, ioDiff); + if (auto parentDeclRefType = substSourceType.As()) { auto parentDeclRef = parentDeclRefType->declRef; DeclRef newParentDeclRef = parentDeclRef.As(); @@ -1045,38 +1046,7 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr GenericConstraintDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) { - auto genParamDecl = subType.As()->declRef.As(); - // search for a substitution that might apply to us - for (auto s = subst; s; s = s->outer.Ptr()) - { - // the generic decl associated with the substitution list must be - // the generic decl that declared this parameter - auto genericDecl = s->genericDecl; - if (genericDecl != genParamDecl.getDecl()->ParentDecl) - continue; - int index = 0; - for (auto m : genericDecl->Members) - { - if (m.Ptr() == genParamDecl.getDecl()) - { - // We've found it, so return the corresponding specialization argument - (*ioDiff)++; - return s->args[index]; - } - else if (auto typeParam = m.As()) - { - index++; - } - else if (auto valParam = m.As()) - { - index++; - } - else - { - } - } - } - return this; + return subType->SubstituteImpl(subst, ioDiff); } int GenericConstraintDeclRefType::GetHashCode() diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang new file mode 100644 index 000000000..de3f1a103 --- /dev/null +++ b/tests/compute/assoctype-complex.slang @@ -0,0 +1,59 @@ +//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + +RWStructuredBuffer outputBuffer; +interface IBase +{ + associatedtype V; + V sub(V a0, V a1); +} +interface ISimple +{ + associatedtype U : IBase; + U.V add(U v0, U v1); +} + +struct Val : IBase +{ + typedef int V; + V sub(V a0, V a1) + { + return a0-a1; + } +}; + +struct Simple : ISimple +{ + typedef Val U; + Val.V add(U v0, U v1) + { + return v0.sub(4, v1.sub(1,2)); + } +}; +/* +__generic +T.U.V test(T simple, T.U v0, T.U v1) +{ + return simple.add(v0, v1); +} + +__generic +T test(T v0, T v1) +{ + return v0 + v1; +} +*/ +__generic +T test(T v0, T v1) +{ + return T(3.0); +} +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + //Simple s; + //Val v0, v1; + //float outVal = test(s, v0, v1); // == 1.0 + float outVal = test(1.0, 2.0); + outputBuffer[dispatchThreadID.x] = outVal; +} \ No newline at end of file diff --git a/tests/compute/assoctype-complex.slang._ignore b/tests/compute/assoctype-complex.slang._ignore deleted file mode 100644 index 3e590b2e0..000000000 --- a/tests/compute/assoctype-complex.slang._ignore +++ /dev/null @@ -1,44 +0,0 @@ -RWStructuredBuffer outputBuffer; -interface IBase -{ - associatedtype V; - V sub(V a0, V a1); -} -interface ISimple -{ - associatedtype U : IBase; - U.V add(U v0, U v1); -} - -struct Val : IBase -{ - typedef int V; - V sub(V a0, V a1) - { - return a0-a1; - } -}; - -struct Simple : ISimple -{ - typedef Val U; - Val.V add(U v0, U v1) - { - return v0.sub(4, v1.sub(1,2)); - } -}; - -__generic -T.U.V test(T simple, T.U v0, T.U v1) -{ - return simple.add(v0, v1); -} - -[numthreads(4, 1, 1)] -void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) -{ - Simple s; - Val v0, v1; - float outVal = test(s, v0, v1); // == 1.0 - outputBuffer[0] = outVal; -} \ No newline at end of file diff --git a/tests/compute/generics-constraint1.slang b/tests/compute/generics-constraint1.slang new file mode 100644 index 000000000..ff90c1cc9 --- /dev/null +++ b/tests/compute/generics-constraint1.slang @@ -0,0 +1,17 @@ +//TEST(smoke, compute):COMPARE_COMPUTE:-xslang -use-ir +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + +RWStructuredBuffer outputBuffer; + +__generic +T test(T v0, T v1) +{ + return T(3.0); +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + float outVal = test(1.0, 2.0); + outputBuffer[dispatchThreadID.x] = outVal; +} \ No newline at end of file -- cgit v1.2.3 From 33d9f07d6c86e80c44af4de0693532cee6635135 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 19:19:23 -0400 Subject: cleanup useless code --- source/slang/emit.cpp | 5 --- source/slang/lower-to-ir.cpp | 5 --- source/slang/lower.cpp | 5 --- source/slang/parser.cpp | 2 +- source/slang/syntax.cpp | 79 -------------------------------------------- source/slang/type-defs.h | 32 ------------------ 6 files changed, 1 insertion(+), 127 deletions(-) (limited to 'source/slang/parser.cpp') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index fc6fc0184..056454845 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1194,11 +1194,6 @@ struct EmitVisitor EmitDeclarator(declarator); } - void visitThisType(ThisType* /*type*/, TypeEmitArg const&) - { - return; - } - void visitDeclRefType(DeclRefType* declRefType, TypeEmitArg const& arg) { auto declarator = arg.declarator; diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index a7baf265c..be91b9d3d 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -882,11 +882,6 @@ struct ValLoweringVisitor : ValVisitor()); } - RefPtr visitThisType(ThisType* type) - { - return type; - } - RefPtr visitNamedExpressionType(NamedExpressionType* type) { if (shared->target == CodeGenTarget::GLSL) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 8e0d5d66f..954496b68 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -2087,7 +2087,7 @@ namespace Slang return decl; } - static void parseOptionalInheritanceClause(Parser* parser, ContainerDecl* decl) + static void parseOptionalInheritanceClause(Parser* parser, AggTypeDecl* decl) { if( AdvanceIf(parser, TokenType::Colon) ) { diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 255cf4ff1..9acdadad6 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -376,85 +376,6 @@ void Type::accept(IValVisitor* visitor, void* extra) (int)(typeid(this).hash_code())); } - // ThisType - - String ThisType::ToString() - { - return ""; - } - - int ThisType::GetHashCode() - { - return 0; - } - - bool ThisType::EqualsImpl(Type * /*type*/) - { - return true; - } - - Type* ThisType::CreateCanonicalType() - { - // A declaration reference is already canonical - return this; - } - - RefPtr ThisType::SubstituteImpl(Substitutions* subst, int* /*ioDiff*/) - { - while (subst) - { - if (auto thisTypeSubst = dynamic_cast(subst)) - { - return thisTypeSubst->sourceType; - } - subst = subst->outer; - } - return this; - } - - // MemberType - /* - String MemberType::ToString() - { - return objectType->ToString() + "::" + declRef.toString(); - } - - int MemberType::GetHashCode() - { - return combineHash(objectType->GetHashCode(), declRef.GetHashCode()); - } - - bool MemberType::EqualsImpl(Type * type) - { - if (auto memberType = dynamic_cast(type)) - return objectType->Equals(memberType->objectType.Ptr()) && declRef.Equals(memberType->declRef); - return false; - } - - Type* MemberType::CreateCanonicalType() - { - if (auto declRefType = objectType->As()) - { - if (auto aggDeclRef = declRefType->declRef.As()) - { - Decl* targetDecl = nullptr; - if (aggDeclRef.getDecl()->memberDictionary.TryGetValue(declRef.getDecl()->nameAndLoc.name, targetDecl)) - { - if (auto typeDefDecl = dynamic_cast(targetDecl)) - return typeDefDecl->type.type; - else - return DeclRefType::Create(getSession(), DeclRef(targetDecl, aggDeclRef.substitutions)); - } - } - } - return this; - } - - RefPtr MemberType::SubstituteImpl(Substitutions* subst, int* ioDiff) - { - return this; - } - */ // DeclRefType String DeclRefType::ToString() diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 7eda5b5ce..60f519c82 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -55,38 +55,6 @@ protected: ) END_SYNTAX_CLASS() -SYNTAX_CLASS(ThisType, Type) -RAW( - virtual String ToString() override; - virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; - - ThisType() - {} - protected: - virtual int GetHashCode() override; - virtual bool EqualsImpl(Type * type) override; - virtual Type* CreateCanonicalType() override; - ) -END_SYNTAX_CLASS() - -/* -SYNTAX_CLASS(MemberType, Type) - FIELD(RefPtr, objectType) - DECL_FIELD(DeclRef, declRef) - RAW( - virtual String ToString() override; - virtual RefPtr SubstituteImpl(Substitutions* subst, int* ioDiff) override; - - MemberType() - {} - protected: - virtual int GetHashCode() override; - virtual bool EqualsImpl(Type * type) override; - virtual Type* CreateCanonicalType() override; - ) -END_SYNTAX_CLASS() -*/ - // A type that takes the form of a reference to some declaration SYNTAX_CLASS(DeclRefType, Type) DECL_FIELD(DeclRef, declRef) -- cgit v1.2.3 From 0d250f0d49e9e29d143c5794671669ea025b357e Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 20:21:19 -0400 Subject: style fixes --- source/slang/check.cpp | 3 ++- source/slang/parser.cpp | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'source/slang/parser.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index bc3823292..79a4f28cf 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1972,8 +1972,9 @@ namespace Slang return; VisitFunctionDeclaration(functionNode); - // TODO: This should really onlye set "checked header" + // TODO: This should really only set "checked header" functionNode->SetCheckState(DeclCheckState::Checked); + // TODO: should put the checking of the body onto a "work list" // to avoid recursion here. if (functionNode->Body) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 954496b68..57956485a 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -1428,8 +1428,7 @@ namespace Slang return typeExpr; } - static TypeSpec - parseTypeSpec(Parser* parser) + static TypeSpec parseTypeSpec(Parser* parser) { TypeSpec typeSpec; @@ -1462,15 +1461,19 @@ namespace Slang RefPtr typeExpr = basicType; - while (parser->LookAheadToken(TokenType::OpLess) || parser->LookAheadToken(TokenType::Dot)) + bool shouldLoop = true; + while (shouldLoop) { - if (parser->LookAheadToken(TokenType::OpLess)) + switch (peekTokenType(parser)) { + case TokenType::OpLess: typeExpr = parseGenericApp(parser, typeExpr); - } - else - { + break; + case TokenType::Dot: typeExpr = parseMemberType(parser, typeExpr); + break; + default: + shouldLoop = false; } } -- cgit v1.2.3