From c850ba44164ac2bee895137abdd184beb4123090 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 6 Mar 2019 20:16:20 -0500 Subject: * Add support for enum and type lookup via :: (scope operator) (#882) * Added test for scope operator --- source/slang/check.cpp | 162 ++++++++++++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 64 deletions(-) (limited to 'source/slang/check.cpp') 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 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 _lookupStaticMember(RefPtr expr, RefPtr baseExpression) { - // StaticMemberExpr means it is already checked - SLANG_UNEXPECTED("should not occur in unchecked AST"); - UNREACHABLE_RETURN(nullptr); - } - - RefPtr lookupResultFailure( - MemberExpr* expr, - QualType const& baseType) - { - getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); - expr->type = QualType(getSession()->getErrorType()); - return expr; - - } - - RefPtr 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(baseType)) - { - return CheckSwizzleExpr( - expr, - baseVecType->elementType, - baseVecType->elementCount); - } - else if(auto baseScalarType = as(baseType)) - { - // Treat scalar like a 1-element vector when swizzling - return CheckSwizzleExpr( - expr, - baseScalarType, - 1); - } - else if(auto typeType = as(baseType)) + if (auto typeType = as(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 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(baseType)) { return CreateErrorExpr(expr); } + + // Failure + return lookupMemberResultFailure(expr, baseType); + } + + RefPtr 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 lookupMemberResultFailure( + DeclRefExpr* expr, + QualType const& baseType) + { + // Check it's a member expression + SLANG_ASSERT(as(expr) || as(expr)); + + getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); + expr->type = QualType(getSession()->getErrorType()); + return expr; + } + + RefPtr 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(baseType)) + { + return CheckSwizzleExpr( + expr, + baseVecType->elementType, + baseVecType->elementCount); + } + else if(auto baseScalarType = as(baseType)) + { + // Treat scalar like a 1-element vector when swizzling + return CheckSwizzleExpr( + expr, + baseScalarType, + 1); + } + else if(auto typeType = as(baseType)) + { + return _lookupStaticMember(expr, expr->BaseExpression); + } + else if (as(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 -- cgit v1.2.3