-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add API method to specialize function reference with argument types #4966
Changes from all commits
98e265f
a01ed5e
019e093
0bd730d
2e3dc07
8422abf
e32ac67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,6 @@ | |
#include "slang-type-layout.h" | ||
#include "slang-lookup.h" | ||
|
||
# | ||
#include "slang-options.h" | ||
|
||
#include "slang-repro.h" | ||
|
@@ -1069,8 +1068,12 @@ Linkage::Linkage(Session* session, ASTBuilder* astBuilder, Linkage* builtinLinka | |
for (const auto& nameToMod : builtinLinkage->mapNameToLoadedModules) | ||
mapNameToLoadedModules.add(nameToMod); | ||
} | ||
|
||
m_semanticsForReflection = new SharedSemanticsContext(this, nullptr, nullptr); | ||
} | ||
|
||
SharedSemanticsContext* Linkage::getSemanticsForReflection() { return m_semanticsForReflection.get(); } | ||
|
||
ISlangUnknown* Linkage::getInterface(const Guid& guid) | ||
{ | ||
if(guid == ISlangUnknown::getTypeGuid() || guid == ISession::getTypeGuid()) | ||
|
@@ -1348,18 +1351,11 @@ SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL Linkage::specializeType( | |
return asExternal(specializedType); | ||
} | ||
|
||
|
||
DeclRef<Decl> Linkage::specializeGeneric( | ||
DeclRef<Decl> declRef, | ||
List<Expr*> argExprs, | ||
DiagnosticSink* sink) | ||
DeclRef<GenericDecl> getGenericParentDeclRef( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit different unfortunately. |
||
ASTBuilder* astBuilder, | ||
SemanticsVisitor* visitor, | ||
DeclRef<Decl> declRef) | ||
{ | ||
SLANG_AST_BUILDER_RAII(getASTBuilder()); | ||
SLANG_ASSERT(declRef); | ||
|
||
SharedSemanticsContext sharedSemanticsContext(this, nullptr, sink); | ||
SemanticsVisitor visitor(&sharedSemanticsContext); | ||
|
||
// Create substituted parent decl ref. | ||
auto decl = declRef.getDecl(); | ||
|
||
|
@@ -1369,9 +1365,58 @@ DeclRef<Decl> Linkage::specializeGeneric( | |
} | ||
|
||
auto genericDecl = as<GenericDecl>(decl); | ||
auto genericDeclRef = createDefaultSubstitutionsIfNeeded(getASTBuilder(), &visitor, DeclRef(genericDecl)).as<GenericDecl>(); | ||
genericDeclRef = substituteDeclRef(SubstitutionSet(declRef), getASTBuilder(), genericDeclRef).as<GenericDecl>(); | ||
auto genericDeclRef = createDefaultSubstitutionsIfNeeded(astBuilder, visitor, DeclRef(genericDecl)).as<GenericDecl>(); | ||
return substituteDeclRef(SubstitutionSet(declRef), astBuilder, genericDeclRef).as<GenericDecl>(); | ||
} | ||
|
||
DeclRef<Decl> Linkage::specializeWithArgTypes( | ||
DeclRef<Decl> funcDeclRef, | ||
List<Type*> argTypes, | ||
DiagnosticSink* sink) | ||
{ | ||
SemanticsVisitor visitor(getSemanticsForReflection()); | ||
visitor = visitor.withSink(sink); | ||
|
||
ASTBuilder* astBuilder = getASTBuilder(); | ||
|
||
List<Expr*> argExprs; | ||
for (SlangInt aa = 0; aa < argTypes.getCount(); ++aa) | ||
{ | ||
auto argType = argTypes[aa]; | ||
|
||
// Create an 'empty' expr with the given type. Ideally, the expression itself should not matter | ||
// only its checked type. | ||
// | ||
auto argExpr = astBuilder->create<VarExpr>(); | ||
argExpr->type = argType; | ||
argExprs.add(argExpr); | ||
} | ||
|
||
// Construct invoke expr. | ||
auto invokeExpr = astBuilder->create<InvokeExpr>(); | ||
auto declRefExpr = astBuilder->create<DeclRefExpr>(); | ||
|
||
declRefExpr->declRef = getGenericParentDeclRef(getASTBuilder(), &visitor, funcDeclRef); | ||
invokeExpr->functionExpr = declRefExpr; | ||
invokeExpr->arguments = argExprs; | ||
|
||
auto checkedInvokeExpr = visitor.CheckInvokeExprWithCheckedOperands(invokeExpr); | ||
return as<DeclRefExpr>(as<InvokeExpr>(checkedInvokeExpr)->functionExpr)->declRef; | ||
} | ||
|
||
|
||
DeclRef<Decl> Linkage::specializeGeneric( | ||
DeclRef<Decl> declRef, | ||
List<Expr*> argExprs, | ||
DiagnosticSink* sink) | ||
{ | ||
SLANG_AST_BUILDER_RAII(getASTBuilder()); | ||
SLANG_ASSERT(declRef); | ||
|
||
SemanticsVisitor visitor(getSemanticsForReflection()); | ||
visitor = visitor.withSink(sink); | ||
|
||
auto genericDeclRef = getGenericParentDeclRef(getASTBuilder(), &visitor, declRef); | ||
|
||
DeclRefExpr* declRefExpr = getASTBuilder()->create<DeclRefExpr>(); | ||
declRefExpr->declRef = genericDeclRef; | ||
|
@@ -1561,8 +1606,9 @@ SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::createTypeConformanceComponentTy | |
|
||
try | ||
{ | ||
SharedSemanticsContext sharedSemanticsContext(this, nullptr, &sink); | ||
SemanticsVisitor visitor(&sharedSemanticsContext); | ||
SemanticsVisitor visitor(getSemanticsForReflection()); | ||
visitor = visitor.withSink(&sink); | ||
|
||
auto witness = | ||
visitor.isSubtype((Slang::Type*)type, (Slang::Type*)interfaceType, IsSubTypeOptions::None); | ||
if (auto subtypeWitness = as<SubtypeWitness>(witness)) | ||
|
@@ -2318,12 +2364,8 @@ DeclRef<Decl> ComponentType::findDeclFromString( | |
|
||
Expr* expr = linkage->parseTermString(name, scope); | ||
|
||
SharedSemanticsContext sharedSemanticsContext( | ||
linkage, | ||
nullptr, | ||
sink); | ||
SemanticsContext context(&sharedSemanticsContext); | ||
context = context.allowStaticReferenceToNonStaticMember(); | ||
SemanticsContext context(linkage->getSemanticsForReflection()); | ||
context = context.allowStaticReferenceToNonStaticMember().withSink(sink); | ||
|
||
SemanticsVisitor visitor(context); | ||
|
||
|
@@ -2377,12 +2419,8 @@ DeclRef<Decl> ComponentType::findDeclFromStringInType( | |
|
||
Expr* expr = linkage->parseTermString(name, scope); | ||
|
||
SharedSemanticsContext sharedSemanticsContext( | ||
linkage, | ||
nullptr, | ||
sink); | ||
SemanticsContext context(&sharedSemanticsContext); | ||
context = context.allowStaticReferenceToNonStaticMember(); | ||
SemanticsContext context(linkage->getSemanticsForReflection()); | ||
context = context.allowStaticReferenceToNonStaticMember().withSink(sink); | ||
|
||
SemanticsVisitor visitor(context); | ||
|
||
|
@@ -2433,11 +2471,7 @@ DeclRef<Decl> ComponentType::findDeclFromStringInType( | |
|
||
bool ComponentType::isSubType(Type* subType, Type* superType) | ||
{ | ||
SharedSemanticsContext sharedSemanticsContext( | ||
getLinkage(), | ||
nullptr, | ||
nullptr); | ||
SemanticsContext context(&sharedSemanticsContext); | ||
SemanticsContext context(getLinkage()->getSemanticsForReflection()); | ||
SemanticsVisitor visitor(context); | ||
|
||
return (visitor.isSubtype(subType, superType, IsSubTypeOptions::None) != nullptr); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does apply specializations do? Is it just get default specialized DeclRef? This imo is an internal detail in generic representation and should not be exposed in the api. What are the scenarios that this is needed from the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea here is that the generic parameters & their arguments (if any) are represented through a
SlangReflectionGeneric
. The fact that the generic is represented as a parent in the hierarchy is not directly exposed to the user. It's just that everySlangReflectionFunction
/SlangReflectionType
/SlangReflectionVariable
declaration may have an associated generic which can be obtained usinggetGenericContainer
. Further, each declaration can be nested inside another one, so you can traverse all generic parameters affecting a reflected function/variable/type by usinggetOuterGenericContainer
repeatedly.In our case, we're actually not referencing the parent generic decl directly, the decl-ref for
SlangReflectionFunction
andSlangReflectionGeneric
are actually the same decl-ref, but they expose different methods (the generic reflection is exclusively for looking through generic parameters, and is common to functions, variables & types)Each
SlangReflectionGeneric
effectively represents a set of specializations.applySpecializations
creates a specialized decl-ref out of an unspecialized one by applying the bag of specializations to the referenced decl-ref.In this case, I can lookup an unspecialized function, extract the generic-reflection, set some parameters on the generic-reflection, then apply it to the function-reflection to get the specialized version.
I couldn't come up with a sleeker way to do this, given that we can have many levels of generics, all of which may or may not already have specializations. This idea of putting specializations behind a special generic-reflection is to just avoid having to duplicate the generic-specific methods for all the different types of reflections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. As long as we make sure the API doesn't assume generic decl is the parent of the decl itself, and just treat generic as a different aspect of the same decl, then we should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should be careful on the ast - children enumeration logic to not list the generic decl as the children, but instead the inner decl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is currently the case. If the decl-walking API hits a generic decl, the user must cast it to
SlangReflectionGeneric
and callgetInnerDecl()
to get the inner node.