summaryrefslogtreecommitdiffstats
path: root/source/slang/slang.cpp
diff options
context:
space:
mode:
authorSai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com>2024-08-27 16:47:05 -0400
committerGitHub <noreply@github.com>2024-08-27 16:47:05 -0400
commit4aac22da6ae902eca1e7750f4e5b83ba238b5874 (patch)
treef266e3c7c3a646473ac4af80ddbcd72702ced917 /source/slang/slang.cpp
parentd40c143eb4f19f1dfd0d0dcf9b718be6e495ca27 (diff)
Add ability to specialize generic references to functions, types and more (#4909)
* More reflection API features. + Lookup methods and members (by string) on types + Fix issue with looking up non-static members through the scope operator '::' + `GenericReflection`: Cast a decl to generic to access unspecialized generic parameter names and constraints + `GenericReflection`: Use `getGenericContainer()` from function, variable or type to access the 'nearest' generic parent along with specialization info + `GenericReflection::getConcreteType` and `GenericReflection::getConcreteIntVal`: to get the concrete type of a param in the context of the reflection object + `GenericReflection::getOuterGenericContainer` to go up one level and get the outer generic declarations (if there are more than one enclosing generic scopes) + `DeclReflection::getParent`: go to parent declaration. + Change `VariableReflection` to be a `DeclRef` rather than a decl (allows us to return properly substituted types for methods, members, and more) * Fix Falcor issue * Initial namespace reflection support * FIx issue with specializing witness tables * Add API method for specializing parameters of a generic decl * Add ability to specialize generic references to functions, types and more This PR adds the following end-points: - `specializeGeneric()` method that can be called on a generic reflection to substitute arguments for generic type and value parameters. It returns another generic reflection, but this time with the appropriate substitution. - `applySpecializations()` method to then copy these specializations onto an existing type or function reflection. - `isSubType()` to check if a type is a subtype of another type (useful to check if a type is differentiable by checking `IDifferentiable`) This PR also: - Adds `DeclReflection::Kind::Namespace` so that namespace containers are correctly reflected when walking the decl-tree. the name can be obtained through `getName()` but there's no need to cast to a namespace (since there's nothing else we can do with a namespace decl) - Fixes an issue with name-based lookups that fail if a type or function is referenced without specializations. Its helpful to be able to form a reference to a function with default substitutions, so that we can we can specialize it later (either directly, or via argument types). * Update slang.h * Fix up naming * Update slang-compiler.h * Update slang-reflection-api.cpp * Update slang.cpp * Update slang.cpp * Update slang.cpp * Use `checkGenericAppWithCheckedArgs` to do specialization * Update slang-reflection-api.cpp * Update slang-check-decl.cpp
Diffstat (limited to 'source/slang/slang.cpp')
-rw-r--r--source/slang/slang.cpp58
1 files changed, 57 insertions, 1 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 3072ef0a7..aa114e44d 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -1348,6 +1348,43 @@ SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL Linkage::specializeType(
return asExternal(specializedType);
}
+
+DeclRef<Decl> Linkage::specializeGeneric(
+ DeclRef<Decl> declRef,
+ List<Expr*> argExprs,
+ DiagnosticSink* sink)
+{
+ 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();
+
+ while (!as<GenericDecl>(decl))
+ {
+ decl = decl->parentDecl;
+ }
+
+ auto genericDecl = as<GenericDecl>(decl);
+ auto genericDeclRef = createDefaultSubstitutionsIfNeeded(getASTBuilder(), &visitor, DeclRef(genericDecl)).as<GenericDecl>();
+ genericDeclRef = substituteDeclRef(SubstitutionSet(declRef), getASTBuilder(), genericDeclRef).as<GenericDecl>();
+
+
+ DeclRefExpr* declRefExpr = getASTBuilder()->create<DeclRefExpr>();
+ declRefExpr->declRef = genericDeclRef;
+
+ GenericAppExpr* genericAppExpr = getASTBuilder()->create<GenericAppExpr>();
+ genericAppExpr->functionExpr = declRefExpr;
+ genericAppExpr->arguments = argExprs;
+
+ auto specializedDeclRef = as<DeclRefExpr>(visitor.checkGenericAppWithCheckedArgs(genericAppExpr))->declRef;
+
+ return specializedDeclRef;
+}
+
SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL Linkage::getTypeLayout(
slang::TypeReflection* inType,
SlangInt targetIndex,
@@ -2373,9 +2410,28 @@ DeclRef<Decl> ComponentType::findDeclFromStringInType(
result = declRefExpr->declRef;
}
+ if (auto genericDeclRef = result.as<GenericDecl>())
+ {
+ result = createDefaultSubstitutionsIfNeeded(
+ astBuilder, &visitor, DeclRef(genericDeclRef.getDecl()->inner));
+ result = substituteDeclRef(SubstitutionSet(genericDeclRef), astBuilder, result);
+ }
+
return result;
}
+bool ComponentType::isSubType(Type* subType, Type* superType)
+{
+ SharedSemanticsContext sharedSemanticsContext(
+ getLinkage(),
+ nullptr,
+ nullptr);
+ SemanticsContext context(&sharedSemanticsContext);
+ SemanticsVisitor visitor(context);
+
+ return (visitor.isSubtype(subType, superType, IsSubTypeOptions::None) != nullptr);
+}
+
static void collectExportedConstantInContainer(
Dictionary<String, IntVal*>& dict,
ASTBuilder* builder,
@@ -6805,4 +6861,4 @@ SlangResult EndToEndCompileRequest::isParameterLocationUsed(Int entryPointIndex,
return SLANG_OK;
}
-} // namespace Slang
+} // namespace Slang \ No newline at end of file