diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 162 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 29 |
2 files changed, 126 insertions, 65 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 37c0d5baf..91bbd694a 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -8843,63 +8843,14 @@ namespace Slang } } - RefPtr<Expr> visitStaticMemberExpr(StaticMemberExpr* /*expr*/) + // Look up a static member + // @param expr Can be StaticMemberExpr or MemberExpr + // @param baseExpression Is the underlying type expression determined from resolving expr + RefPtr<Expr> _lookupStaticMember(RefPtr<DeclRefExpr> expr, RefPtr<Expr> baseExpression) { - // StaticMemberExpr means it is already checked - SLANG_UNEXPECTED("should not occur in unchecked AST"); - UNREACHABLE_RETURN(nullptr); - } - - RefPtr<Expr> lookupResultFailure( - MemberExpr* expr, - QualType const& baseType) - { - getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); - expr->type = QualType(getSession()->getErrorType()); - return expr; - - } - - RefPtr<Expr> visitMemberExpr(MemberExpr * expr) - { - expr->BaseExpression = CheckExpr(expr->BaseExpression); - - expr->BaseExpression = MaybeDereference(expr->BaseExpression); + auto& baseType = baseExpression->type; - // If the base of the member lookup has an interface type - // *without* a suitable this-type substitution, then we are - // trying to perform lookup on a value of existential type, - // and we should "open" the existential here so that we - // can expose its structure. - // - expr->BaseExpression = maybeOpenExistential(expr->BaseExpression); - - auto & baseType = expr->BaseExpression->type; - - // Note: Checking for vector types before declaration-reference types, - // because vectors are also declaration reference types... - // - // Also note: the way this is done right now means that the ability - // to swizzle vectors interferes with any chance of looking up - // members via extension, for vector or scalar types. - // - // TODO: Matrix swizzles probably need to be handled at some point. - if (auto baseVecType = as<VectorExpressionType>(baseType)) - { - return CheckSwizzleExpr( - expr, - baseVecType->elementType, - baseVecType->elementCount); - } - else if(auto baseScalarType = as<BasicExpressionType>(baseType)) - { - // Treat scalar like a 1-element vector when swizzling - return CheckSwizzleExpr( - expr, - baseScalarType, - 1); - } - else if(auto typeType = as<TypeType>(baseType)) + if (auto typeType = as<TypeType>(baseType)) { // We are looking up a member inside a type. // We want to be careful here because we should only find members @@ -8921,7 +8872,7 @@ namespace Slang type); if (!lookupResult.isValid()) { - return lookupResultFailure(expr, baseType); + return lookupMemberResultFailure(expr, baseType); } // We need to confirm that whatever member we @@ -8947,13 +8898,13 @@ namespace Slang // For now let's just be expedient and disallow all of that, because // we can always add it back in later. - if(!lookupResult.isOverloaded()) + if (!lookupResult.isOverloaded()) { // The non-overloaded case is relatively easy. We just want // to look at the member being referenced, and check if // it is allowed in a `static` context: // - if(!isUsableAsStaticMember(lookupResult.item)) + if (!isUsableAsStaticMember(lookupResult.item)) { getSink()->diagnose( expr->loc, @@ -8972,10 +8923,10 @@ namespace Slang // are non-static. bool anyNonStatic = false; List<LookupResultItem> staticItems; - for(auto item : lookupResult.items) + for (auto item : lookupResult.items) { // Is this item usable as a static member? - if(isUsableAsStaticMember(item)) + if (isUsableAsStaticMember(item)) { // If yes, then it will be part of the output. staticItems.Add(item); @@ -8988,11 +8939,11 @@ namespace Slang } // Was there anything non-static in the list? - if(anyNonStatic) + if (anyNonStatic) { // If we had some static items, then that's okay, // we just want to use our newly-filtered list. - if(staticItems.Count()) + if (staticItems.Count()) { lookupResult.items = staticItems; } @@ -9012,13 +8963,96 @@ namespace Slang return createLookupResultExpr( lookupResult, - expr->BaseExpression, + baseExpression, expr->loc); } else if (as<ErrorType>(baseType)) { return CreateErrorExpr(expr); } + + // Failure + return lookupMemberResultFailure(expr, baseType); + } + + RefPtr<Expr> visitStaticMemberExpr(StaticMemberExpr* expr) + { + expr->BaseExpression = CheckExpr(expr->BaseExpression); + + // Not sure this is needed -> but guess someone could do + expr->BaseExpression = MaybeDereference(expr->BaseExpression); + + // If the base of the member lookup has an interface type + // *without* a suitable this-type substitution, then we are + // trying to perform lookup on a value of existential type, + // and we should "open" the existential here so that we + // can expose its structure. + // + + expr->BaseExpression = maybeOpenExistential(expr->BaseExpression); + // Do a static lookup + return _lookupStaticMember(expr, expr->BaseExpression); + } + + RefPtr<Expr> lookupMemberResultFailure( + DeclRefExpr* expr, + QualType const& baseType) + { + // Check it's a member expression + SLANG_ASSERT(as<StaticMemberExpr>(expr) || as<MemberExpr>(expr)); + + getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); + expr->type = QualType(getSession()->getErrorType()); + return expr; + } + + RefPtr<Expr> visitMemberExpr(MemberExpr * expr) + { + expr->BaseExpression = CheckExpr(expr->BaseExpression); + + expr->BaseExpression = MaybeDereference(expr->BaseExpression); + + // If the base of the member lookup has an interface type + // *without* a suitable this-type substitution, then we are + // trying to perform lookup on a value of existential type, + // and we should "open" the existential here so that we + // can expose its structure. + // + expr->BaseExpression = maybeOpenExistential(expr->BaseExpression); + + auto & baseType = expr->BaseExpression->type; + + // Note: Checking for vector types before declaration-reference types, + // because vectors are also declaration reference types... + // + // Also note: the way this is done right now means that the ability + // to swizzle vectors interferes with any chance of looking up + // members via extension, for vector or scalar types. + // + // TODO: Matrix swizzles probably need to be handled at some point. + if (auto baseVecType = as<VectorExpressionType>(baseType)) + { + return CheckSwizzleExpr( + expr, + baseVecType->elementType, + baseVecType->elementCount); + } + else if(auto baseScalarType = as<BasicExpressionType>(baseType)) + { + // Treat scalar like a 1-element vector when swizzling + return CheckSwizzleExpr( + expr, + baseScalarType, + 1); + } + else if(auto typeType = as<TypeType>(baseType)) + { + return _lookupStaticMember(expr, expr->BaseExpression); + } + else if (as<ErrorType>(baseType)) + { + return CreateErrorExpr(expr); + } else { LookupResult lookupResult = lookUpMember( @@ -9028,7 +9062,7 @@ namespace Slang baseType.Ptr()); if (!lookupResult.isValid()) { - return lookupResultFailure(expr, baseType); + return lookupMemberResultFailure(expr, baseType); } // TODO: need to filter for declarations that are valid to refer diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index a7ccb7b8a..5cb712489 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -1738,8 +1738,10 @@ namespace Slang } static RefPtr<Expr> parseMemberType(Parser * parser, RefPtr<Expr> base) { + // When called the :: or . have been consumed, so don't need to consume here. + RefPtr<MemberExpr> memberExpr = new MemberExpr(); - parser->ReadToken(TokenType::Dot); + parser->FillPosition(memberExpr.Ptr()); memberExpr->BaseExpression = base; memberExpr->name = expectIdentifier(parser).name; @@ -1853,7 +1855,12 @@ namespace Slang case TokenType::OpLess: typeExpr = parseGenericApp(parser, typeExpr); break; + case TokenType::Scope: + parser->ReadToken(TokenType::Scope); + typeExpr = parseMemberType(parser, typeExpr); + break; case TokenType::Dot: + parser->ReadToken(TokenType::Dot); typeExpr = parseMemberType(parser, typeExpr); break; default: @@ -4192,6 +4199,26 @@ namespace Slang } break; + // Scope access `x::m` + case TokenType::Scope: + { + RefPtr<StaticMemberExpr> staticMemberExpr = new StaticMemberExpr(); + + // TODO(tfoley): why would a member expression need this? + staticMemberExpr->scope = parser->currentScope.Ptr(); + + parser->FillPosition(staticMemberExpr.Ptr()); + staticMemberExpr->BaseExpression = expr; + parser->ReadToken(TokenType::Scope); + staticMemberExpr->name = expectIdentifier(parser).name; + + if (peekTokenType(parser) == TokenType::OpLess) + expr = maybeParseGenericApp(parser, staticMemberExpr); + else + expr = staticMemberExpr; + + break; + } // Member access `x.m` case TokenType::Dot: { |
