summaryrefslogtreecommitdiffstats
path: root/source/slang/lookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/lookup.cpp')
-rw-r--r--source/slang/lookup.cpp713
1 files changed, 0 insertions, 713 deletions
diff --git a/source/slang/lookup.cpp b/source/slang/lookup.cpp
deleted file mode 100644
index fe535d6e7..000000000
--- a/source/slang/lookup.cpp
+++ /dev/null
@@ -1,713 +0,0 @@
-// lookup.cpp
-#include "lookup.h"
-#include "name.h"
-
-namespace Slang {
-
-void checkDecl(SemanticsVisitor* visitor, Decl* decl);
-
-//
-
-DeclRef<ExtensionDecl> ApplyExtensionToType(
- SemanticsVisitor* semantics,
- ExtensionDecl* extDecl,
- RefPtr<Type> type);
-
-//
-
-
-// Helper for constructing breadcrumb trails during lookup, without unnecessary heap allocaiton
-struct BreadcrumbInfo
-{
- LookupResultItem::Breadcrumb::Kind kind;
- LookupResultItem::Breadcrumb::ThisParameterMode thisParameterMode = LookupResultItem::Breadcrumb::ThisParameterMode::Default;
- DeclRef<Decl> declRef;
- BreadcrumbInfo* prev = nullptr;
-};
-
-void DoLocalLookupImpl(
- Session* session,
- Name* name,
- DeclRef<ContainerDecl> containerDeclRef,
- LookupRequest const& request,
- LookupResult& result,
- BreadcrumbInfo* inBreadcrumbs);
-
-//
-
-void buildMemberDictionary(ContainerDecl* decl)
-{
- // Don't rebuild if already built
- if (decl->memberDictionaryIsValid)
- return;
-
- decl->memberDictionary.Clear();
- decl->transparentMembers.clear();
-
- // are we a generic?
- GenericDecl* genericDecl = as<GenericDecl>(decl);
-
- for (auto m : decl->Members)
- {
- auto name = m->getName();
-
- // Add any transparent members to a separate list for lookup
- if (m->HasModifier<TransparentModifier>())
- {
- TransparentMemberInfo info;
- info.decl = m.Ptr();
- decl->transparentMembers.add(info);
- }
-
- // Ignore members with no name
- if (!name)
- continue;
-
- // Ignore the "inner" member of a generic declaration
- if (genericDecl && m == genericDecl->inner)
- continue;
-
-
- m->nextInContainerWithSameName = nullptr;
-
- Decl* next = nullptr;
- if (decl->memberDictionary.TryGetValue(name, next))
- m->nextInContainerWithSameName = next;
-
- decl->memberDictionary[name] = m.Ptr();
-
- }
- decl->memberDictionaryIsValid = true;
-}
-
-
-bool DeclPassesLookupMask(Decl* decl, LookupMask mask)
-{
- // type declarations
- if(auto aggTypeDecl = as<AggTypeDecl>(decl))
- {
- return int(mask) & int(LookupMask::type);
- }
- else if(auto simpleTypeDecl = as<SimpleTypeDecl>(decl))
- {
- return int(mask) & int(LookupMask::type);
- }
- // function declarations
- else if(auto funcDecl = as<FunctionDeclBase>(decl))
- {
- return (int(mask) & int(LookupMask::Function)) != 0;
- }
- // attribute declaration
- else if( auto attrDecl = as<AttributeDecl>(decl) )
- {
- return (int(mask) & int(LookupMask::Attribute)) != 0;
- }
-
- // default behavior is to assume a value declaration
- // (no overloading allowed)
-
- return (int(mask) & int(LookupMask::Value)) != 0;
-}
-
-void AddToLookupResult(
- LookupResult& result,
- LookupResultItem item)
-{
- if (!result.isValid())
- {
- // If we hadn't found a hit before, we have one now
- result.item = item;
- }
- else if (!result.isOverloaded())
- {
- // We are about to make this overloaded
- result.items.add(result.item);
- result.items.add(item);
- }
- else
- {
- // The result was already overloaded, so we pile on
- result.items.add(item);
- }
-}
-
-LookupResult refineLookup(LookupResult const& inResult, LookupMask mask)
-{
- if (!inResult.isValid()) return inResult;
- if (!inResult.isOverloaded()) return inResult;
-
- LookupResult result;
- for (auto item : inResult.items)
- {
- if (!DeclPassesLookupMask(item.declRef.getDecl(), mask))
- continue;
-
- AddToLookupResult(result, item);
- }
- return result;
-}
-
-LookupResultItem CreateLookupResultItem(
- DeclRef<Decl> declRef,
- BreadcrumbInfo* breadcrumbInfos)
-{
- LookupResultItem item;
- item.declRef = declRef;
-
- // breadcrumbs were constructed "backwards" on the stack, so we
- // reverse them here by building a linked list the other way
- RefPtr<LookupResultItem::Breadcrumb> breadcrumbs;
- for (auto bb = breadcrumbInfos; bb; bb = bb->prev)
- {
- breadcrumbs = new LookupResultItem::Breadcrumb(
- bb->kind,
- bb->declRef,
- breadcrumbs,
- bb->thisParameterMode);
- }
- item.breadcrumbs = breadcrumbs;
- return item;
-}
-
-void DoMemberLookupImpl(
- Session* session,
- Name* name,
- RefPtr<Type> baseType,
- LookupRequest const& request,
- LookupResult& ioResult,
- BreadcrumbInfo* breadcrumbs)
-{
- if (!baseType)
- {
- return;
- }
-
- // If the type was pointer-like, then dereference it
- // automatically here.
- if (auto pointerLikeType = as<PointerLikeType>(baseType))
- {
- // Need to leave a breadcrumb to indicate that we
- // did an implicit dereference here
- BreadcrumbInfo derefBreacrumb;
- derefBreacrumb.kind = LookupResultItem::Breadcrumb::Kind::Deref;
- derefBreacrumb.prev = breadcrumbs;
-
- // Recursively perform lookup on the result of deref
- return DoMemberLookupImpl(
- session,
- name, pointerLikeType->elementType, request, ioResult, &derefBreacrumb);
- }
-
- // Default case: no dereference needed
-
- if (auto baseDeclRefType = as<DeclRefType>(baseType))
- {
- if (auto baseAggTypeDeclRef = baseDeclRefType->declRef.as<AggTypeDecl>())
- {
- DoLocalLookupImpl(
- session,
- name, baseAggTypeDeclRef, request, ioResult, breadcrumbs);
- }
- }
-
- // TODO(tfoley): any other cases to handle here?
-}
-
-void DoMemberLookupImpl(
- Session* session,
- Name* name,
- DeclRef<Decl> baseDeclRef,
- LookupRequest const& request,
- LookupResult& ioResult,
- BreadcrumbInfo* breadcrumbs)
-{
- auto baseType = getTypeForDeclRef(
- session,
- baseDeclRef);
- return DoMemberLookupImpl(
- session,
- name, baseType, request, ioResult, breadcrumbs);
-}
-
-// If we are about to perform lookup through an interface, then
-// we need to specialize the decl-ref to that interface to include
-// a "this type" subtitution. This function applies that substition
-// when it is required, and returns the existing `declRef` otherwise.
-DeclRef<Decl> maybeSpecializeInterfaceDeclRef(
- RefPtr<Type> subType,
- RefPtr<Type> superType,
- DeclRef<Decl> superTypeDeclRef, // The decl-ref we are going to perform lookup in
- DeclRef<TypeConstraintDecl> constraintDeclRef) // The type constraint that told us our type is a subtype
-{
- if (auto superInterfaceDeclRef = superTypeDeclRef.as<InterfaceDecl>())
- {
- // Create a subtype witness value to note the subtype relationship
- // that makes this specialization valid.
- //
- // Note: this is to ensure that we can specialize the subtype witness
- // later (e.g., by replacing a subtype witness that represents a generic
- // constraint parameter with the concrete generic arguments that
- // are used at a particular call site to the generic).
- RefPtr<DeclaredSubtypeWitness> subtypeWitness = new DeclaredSubtypeWitness();
- subtypeWitness->declRef = constraintDeclRef;
- subtypeWitness->sub = subType;
- subtypeWitness->sup = superType;
-
- RefPtr<ThisTypeSubstitution> thisTypeSubst = new ThisTypeSubstitution();
- thisTypeSubst->interfaceDecl = superInterfaceDeclRef.getDecl();
- thisTypeSubst->witness = subtypeWitness;
- thisTypeSubst->outer = superInterfaceDeclRef.substitutions.substitutions;
-
- auto specializedInterfaceDeclRef = DeclRef<Decl>(superInterfaceDeclRef.getDecl(), thisTypeSubst);
- return specializedInterfaceDeclRef;
- }
-
- return superTypeDeclRef;
-}
-
-// Same as the above, but we are specializing a type instead of a decl-ref
-RefPtr<Type> maybeSpecializeInterfaceDeclRef(
- Session* session,
- RefPtr<Type> subType,
- RefPtr<Type> superType, // The type we are going to perform lookup in
- DeclRef<TypeConstraintDecl> constraintDeclRef) // The type constraint that told us our type is a subtype
-{
- if (auto superDeclRefType = as<DeclRefType>(superType))
- {
- if (auto superInterfaceDeclRef = superDeclRefType->declRef.as<InterfaceDecl>())
- {
- auto specializedInterfaceDeclRef = maybeSpecializeInterfaceDeclRef(
- subType,
- superType,
- superInterfaceDeclRef,
- constraintDeclRef);
- auto specializedInterfaceType = DeclRefType::Create(session, specializedInterfaceDeclRef);
- return specializedInterfaceType;
- }
- }
-
- return superType;
-}
-
-
-// Look for members of the given name in the given container for declarations
-void DoLocalLookupImpl(
- Session* session,
- Name* name,
- DeclRef<ContainerDecl> containerDeclRef,
- LookupRequest const& request,
- LookupResult& result,
- BreadcrumbInfo* inBreadcrumbs)
-{
- if (result.lookedupDecls.Contains(containerDeclRef))
- return;
- result.lookedupDecls.Add(containerDeclRef);
-
- ContainerDecl* containerDecl = containerDeclRef.getDecl();
-
- // Ensure that the lookup dictionary in the container is up to date
- if (!containerDecl->memberDictionaryIsValid)
- {
- buildMemberDictionary(containerDecl);
- }
-
- // Look up the declarations with the chosen name in the container.
- Decl* firstDecl = nullptr;
- containerDecl->memberDictionary.TryGetValue(name, firstDecl);
-
- // Now iterate over those declarations (if any) and see if
- // we find any that meet our filtering criteria.
- // For example, we might be filtering so that we only consider
- // type declarations.
- for (auto m = firstDecl; m; m = m->nextInContainerWithSameName)
- {
- if (!DeclPassesLookupMask(m, request.mask))
- continue;
-
- // The declaration passed the test, so add it!
- AddToLookupResult(result, CreateLookupResultItem(DeclRef<Decl>(m, containerDeclRef.substitutions), inBreadcrumbs));
- }
-
-
- // TODO(tfoley): should we look up in the transparent decls
- // if we already has a hit in the current container?
-
- for(auto transparentInfo : containerDecl->transparentMembers)
- {
- // The reference to the transparent member should use whatever
- // substitutions we used in referring to its outer container
- DeclRef<Decl> transparentMemberDeclRef(transparentInfo.decl, containerDeclRef.substitutions);
-
- // We need to leave a breadcrumb so that we know that the result
- // of lookup involves a member lookup step here
-
- BreadcrumbInfo memberRefBreadcrumb;
- memberRefBreadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Member;
- memberRefBreadcrumb.declRef = transparentMemberDeclRef;
- memberRefBreadcrumb.prev = inBreadcrumbs;
-
- DoMemberLookupImpl(
- session,
- name,
- transparentMemberDeclRef,
- request,
- result,
- &memberRefBreadcrumb);
- }
-
- // Consider lookup via extension
- if( auto aggTypeDeclRef = containerDeclRef.as<AggTypeDecl>() )
- {
- RefPtr<Type> type = DeclRefType::Create(
- session,
- aggTypeDeclRef);
-
- for (auto ext = GetCandidateExtensions(aggTypeDeclRef); ext; ext = ext->nextCandidateExtension)
- {
- auto extDeclRef = ApplyExtensionToType(request.semantics, ext, type);
- if (!extDeclRef)
- continue;
-
- // TODO: eventually we need to insert a breadcrumb here so that
- // the constructed result can somehow indicate that a member
- // was found through an extension.
-
- DoLocalLookupImpl(
- session,
- name, extDeclRef, request, result, inBreadcrumbs);
- }
-
- }
- // for interface decls, also lookup in the base interfaces
- if (request.semantics)
- {
- // TODO:
- // The logic here is a bit gross, because it tries to work in terms of
- // decl-refs instead of types (e.g., it asserts that the target type
- // for an `extension` declaration must be a decl-ref type).
- //
- // This code should be converted to do a type-based lookup
- // through declared bases for *any* aggregate type declaration.
- // I think that logic is present in the type-based lookup path, but
- // it would be needed here for when doing lookup from inside an
- // aggregate declaration.
-
- // if we are looking at an extension, find the target decl that we are extending
- DeclRef<Decl> targetDeclRef = containerDeclRef;
- RefPtr<DeclRefType> targetDeclRefType;
- if (auto extDeclRef = containerDeclRef.as<ExtensionDecl>())
- {
- targetDeclRefType = as<DeclRefType>(extDeclRef.getDecl()->targetType);
- SLANG_ASSERT(targetDeclRefType);
- int diff = 0;
- targetDeclRef = targetDeclRefType->declRef.as<ContainerDecl>().SubstituteImpl(containerDeclRef.substitutions, &diff);
- }
-
- // if we are looking inside an interface decl, try find in the interfaces it inherits from
- if (targetDeclRef.is<InterfaceDecl>())
- {
- if(!targetDeclRefType)
- {
- targetDeclRefType = DeclRefType::Create(session, targetDeclRef);
- }
-
- auto baseInterfaces = getMembersOfType<InheritanceDecl>(containerDeclRef);
- for (auto inheritanceDeclRef : baseInterfaces)
- {
- checkDecl(request.semantics, inheritanceDeclRef.decl);
-
- auto baseType = inheritanceDeclRef.getDecl()->base.type.dynamicCast<DeclRefType>();
- SLANG_ASSERT(baseType);
- int diff = 0;
- auto baseInterfaceDeclRef = baseType->declRef.SubstituteImpl(containerDeclRef.substitutions, &diff);
-
- baseInterfaceDeclRef = maybeSpecializeInterfaceDeclRef(
- targetDeclRefType,
- baseType,
- baseInterfaceDeclRef,
- inheritanceDeclRef);
-
- DoLocalLookupImpl(session, name, baseInterfaceDeclRef.as<ContainerDecl>(), request, result, inBreadcrumbs);
- }
- }
- }
-}
-
-void DoLookupImpl(
- Session* session,
- Name* name,
- LookupRequest const& request,
- LookupResult& result)
-{
- auto thisParameterMode = LookupResultItem::Breadcrumb::ThisParameterMode::Default;
-
- auto scope = request.scope;
- auto endScope = request.endScope;
- for (;scope != endScope; scope = scope->parent)
- {
- // Note that we consider all "peer" scopes together,
- // so that a hit in one of them does not preclude
- // also finding a hit in another
- for(auto link = scope; link; link = link->nextSibling)
- {
- auto containerDecl = link->containerDecl;
-
- if(!containerDecl)
- continue;
-
- DeclRef<ContainerDecl> containerDeclRef =
- DeclRef<Decl>(containerDecl, createDefaultSubstitutions(session, containerDecl)).as<ContainerDecl>();
-
- BreadcrumbInfo breadcrumb;
- BreadcrumbInfo* breadcrumbs = nullptr;
-
- // Depending on the kind of container we are looking into,
- // we may need to insert something like a `this` expression
- // to resolve the lookup result.
- //
- // Note: We are checking for `AggTypeDeclBase` here, and not
- // just `AggTypeDecl`, because we want to catch `extension`
- // declarations as well.
- //
- if (auto aggTypeDeclRef = containerDeclRef.as<AggTypeDeclBase>())
- {
- breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::This;
- breadcrumb.thisParameterMode = thisParameterMode;
- breadcrumb.declRef = aggTypeDeclRef;
- breadcrumb.prev = nullptr;
-
- breadcrumbs = &breadcrumb;
- }
-
- // Now perform "local" lookup in the context of the container,
- // as if we were looking up a member directly.
-
- // if we are currently in an extension decl, perform local lookup
- // in the target decl we are extending
- if (auto extDeclRef = containerDeclRef.as<ExtensionDecl>())
- {
- if (extDeclRef.getDecl()->targetType)
- {
- if (auto targetDeclRef = as<DeclRefType>(extDeclRef.getDecl()->targetType))
- {
- if (auto aggDeclRef = targetDeclRef->declRef.as<AggTypeDecl>())
- {
- containerDeclRef = extDeclRef.Substitute(aggDeclRef);
- }
- }
- }
- }
- DoLocalLookupImpl(
- session,
- name, containerDeclRef, request, result, breadcrumbs);
-
- if( auto funcDeclRef = containerDeclRef.as<FunctionDeclBase>() )
- {
- if( funcDeclRef.getDecl()->HasModifier<MutatingAttribute>() )
- {
- thisParameterMode = LookupResultItem::Breadcrumb::ThisParameterMode::Mutating;
- }
- else
- {
- thisParameterMode = LookupResultItem::Breadcrumb::ThisParameterMode::Default;
- }
- }
- }
-
- if (result.isValid())
- {
- // If we've found a result in this scope, then there
- // is no reason to look further up (for now).
- return;
- }
- }
-
- // If we run out of scopes, then we are done.
-}
-
-LookupResult DoLookup(
- Session* session,
- Name* name,
- LookupRequest const& request)
-{
- LookupResult result;
- DoLookupImpl(session, name, request, result);
- return result;
-}
-
-LookupResult lookUp(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- RefPtr<Scope> scope,
- LookupMask mask)
-{
- LookupRequest request;
- request.semantics = semantics;
- request.scope = scope;
- request.mask = mask;
- return DoLookup(session, name, request);
-}
-
-// perform lookup within the context of a particular container declaration,
-// and do *not* look further up the chain
-LookupResult lookUpLocal(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- DeclRef<ContainerDecl> containerDeclRef,
- LookupMask mask)
-{
- LookupRequest request;
- request.semantics = semantics;
- request.mask = mask;
-
- LookupResult result;
- DoLocalLookupImpl(session, name, containerDeclRef, request, result, nullptr);
- return result;
-}
-
-void lookUpMemberImpl(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- Type* type,
- LookupResult& ioResult,
- BreadcrumbInfo* inBreadcrumbs,
- LookupMask mask);
-
-// Perform lookup "through" the given constraint decl-ref,
-// which should show that `subType` is a sub-type of some
-// super-type (e.g., an interface).
-//
-void lookUpThroughConstraint(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- Type* subType,
- DeclRef<TypeConstraintDecl> constraintDeclRef,
- LookupResult& ioResult,
- BreadcrumbInfo* inBreadcrumbs,
- LookupMask mask)
-{
- // The super-type in the constraint (e.g., `Foo` in `T : Foo`)
- // will tell us a type we should use for lookup.
- //
- auto superType = GetSup(constraintDeclRef);
- //
- // We will go ahead and perform lookup using `superType`,
- // after dealing with some details.
-
- // If we are looking up through an interface type, then
- // we need to be sure that we add an appropriate
- // "this type" substitution here, since that needs to
- // be applied to any members we look up.
- //
- superType = maybeSpecializeInterfaceDeclRef(
- session,
- subType,
- superType,
- constraintDeclRef);
-
- // We need to track the indirection we took in lookup,
- // so that we can construct an appropriate AST on the other
- // side that includes the "upcase" from sub-type to super-type.
- //
- BreadcrumbInfo breadcrumb;
- breadcrumb.prev = inBreadcrumbs;
- breadcrumb.kind = LookupResultItem::Breadcrumb::Kind::Constraint;
- breadcrumb.declRef = constraintDeclRef;
-
- // TODO: Need to consider case where this might recurse infinitely (e.g.,
- // if an inheritance clause does something like `Bad<T> : Bad<Bad<T>>`.
- //
- // TODO: The even simpler thing we need to worry about here is that if
- // there is ever a "diamond" relationship in the inheritance hierarchy,
- // we might end up seeing the same interface via different "paths" and
- // we wouldn't want that to lead to overload-resolution failure.
- //
- lookUpMemberImpl(session, semantics, name, superType, ioResult, &breadcrumb, mask);
-}
-
-void lookUpMemberImpl(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- Type* type,
- LookupResult& ioResult,
- BreadcrumbInfo* inBreadcrumbs,
- LookupMask mask)
-{
- if (auto declRefType = as<DeclRefType>(type))
- {
- auto declRef = declRefType->declRef;
- if (declRef.as<AssocTypeDecl>() || declRef.as<GlobalGenericParamDecl>())
- {
- for (auto constraintDeclRef : getMembersOfType<TypeConstraintDecl>(declRef.as<ContainerDecl>()))
- {
- lookUpThroughConstraint(
- session,
- semantics,
- name,
- type,
- constraintDeclRef,
- ioResult,
- inBreadcrumbs,
- mask);
- }
- }
- else if (auto aggTypeDeclRef = declRef.as<AggTypeDecl>())
- {
- LookupRequest request;
- request.semantics = semantics;
-
- DoLocalLookupImpl(session, name, aggTypeDeclRef, request, ioResult, inBreadcrumbs);
- }
- else if (auto genericTypeParamDeclRef = declRef.as<GenericTypeParamDecl>())
- {
- auto genericDeclRef = genericTypeParamDeclRef.GetParent().as<GenericDecl>();
- assert(genericDeclRef);
-
- for(auto constraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(genericDeclRef))
- {
- // Does this constraint pertain to the type we are working on?
- //
- // We want constraints of the form `T : Foo` where `T` is the
- // generic parameter in question, and `Foo` is whatever we are
- // constraining it to.
- auto subType = GetSub(constraintDeclRef);
- auto subDeclRefType = as<DeclRefType>(subType);
- if(!subDeclRefType)
- continue;
- if(!subDeclRefType->declRef.Equals(genericTypeParamDeclRef))
- continue;
-
- lookUpThroughConstraint(
- session,
- semantics,
- name,
- type,
- constraintDeclRef,
- ioResult,
- inBreadcrumbs,
- mask);
- }
- }
-
- }
-
-}
-
-LookupResult lookUpMember(
- Session* session,
- SemanticsVisitor* semantics,
- Name* name,
- Type* type,
- LookupMask mask)
-{
- LookupResult result;
- lookUpMemberImpl(session, semantics, name, type, result, nullptr, mask);
- return result;
-}
-
-}