summaryrefslogtreecommitdiff
path: root/source/slang/slang-ast-substitutions.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2020-06-03 17:22:48 -0400
committerGitHub <noreply@github.com>2020-06-03 17:22:48 -0400
commit1b8731c809761c4e2dbec81dcee207f8a4621903 (patch)
treeb8c67d97a71df2a8ba776b6d1a39bc13138aeaf0 /source/slang/slang-ast-substitutions.cpp
parent4e3e7f2a8f032c3f8fc4c530023aa80973598502 (diff)
Devirtualize AST types (#1368)
* Make getSup work with more general non-virtual 'virtual' mechanism. * WIP: Non virtual AST types. * Project change. * Type doesn't implement equalsImpl * Fix macro invocation Make Overridden functions public to make simply accessible by base types. * Use SLANG_UNEXPECTED. * GetScalarType -> getScalarType Use SLANG_UNEXPECTED instead on ASSERT in NamedExpressionType and TypeType
Diffstat (limited to 'source/slang/slang-ast-substitutions.cpp')
-rw-r--r--source/slang/slang-ast-substitutions.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/source/slang/slang-ast-substitutions.cpp b/source/slang/slang-ast-substitutions.cpp
new file mode 100644
index 000000000..05865fe8f
--- /dev/null
+++ b/source/slang/slang-ast-substitutions.cpp
@@ -0,0 +1,237 @@
+// slang-ast-substitutions.cpp
+#include "slang-ast-builder.h"
+#include <assert.h>
+
+#include "slang-ast-generated-macro.h"
+
+namespace Slang {
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Substitutions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+RefPtr<Substitutions> Substitutions::applySubstitutionsShallow(ASTBuilder* astBuilder, SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
+{
+ SLANG_AST_NODE_VIRTUAL_CALL(Substitutions, applySubstitutionsShallow, (astBuilder, substSet, substOuter, ioDiff))
+}
+
+bool Substitutions::equals(Substitutions* subst)
+{
+ SLANG_AST_NODE_VIRTUAL_CALL(Substitutions, equals, (subst))
+}
+
+HashCode Substitutions::getHashCode() const
+{
+ SLANG_AST_NODE_CONST_VIRTUAL_CALL(Substitutions, getHashCode, ())
+}
+
+RefPtr<Substitutions> Substitutions::_applySubstitutionsShallowOverride(ASTBuilder* astBuilder, SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
+{
+ SLANG_UNUSED(astBuilder);
+ SLANG_UNUSED(substSet);
+ SLANG_UNUSED(substOuter);
+ SLANG_UNUSED(ioDiff);
+ SLANG_UNEXPECTED("Substitutions::_applySubstitutionsShallowOverride not overridden");
+ //return RefPtr<Substitutions>();
+}
+
+bool Substitutions::_equalsOverride(Substitutions* subst)
+{
+ SLANG_UNUSED(subst);
+ SLANG_UNEXPECTED("Substitutions::_equalsOverride not overridden");
+ //return false;
+}
+
+HashCode Substitutions::_getHashCodeOverride() const
+{
+ SLANG_UNEXPECTED("Substitutions::_getHashCodeOverride not overridden");
+ //return HashCode(0);
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! GenericSubstitution !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+RefPtr<Substitutions> GenericSubstitution::_applySubstitutionsShallowOverride(ASTBuilder* astBuilder, SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
+{
+ int diff = 0;
+
+ if (substOuter != outer) diff++;
+
+ List<RefPtr<Val>> substArgs;
+ for (auto a : args)
+ {
+ substArgs.add(a->substituteImpl(astBuilder, substSet, &diff));
+ }
+
+ if (!diff) return this;
+
+ (*ioDiff)++;
+ auto substSubst = astBuilder->create<GenericSubstitution>();
+ substSubst->genericDecl = genericDecl;
+ substSubst->args = substArgs;
+ substSubst->outer = substOuter;
+ return substSubst;
+}
+
+bool GenericSubstitution::_equalsOverride(Substitutions* subst)
+{
+ // both must be NULL, or non-NULL
+ if (subst == nullptr)
+ return false;
+ if (this == subst)
+ return true;
+
+ auto genericSubst = as<GenericSubstitution>(subst);
+ if (!genericSubst)
+ return false;
+ if (genericDecl != genericSubst->genericDecl)
+ return false;
+
+ Index argCount = args.getCount();
+ SLANG_RELEASE_ASSERT(args.getCount() == genericSubst->args.getCount());
+ for (Index aa = 0; aa < argCount; ++aa)
+ {
+ if (!args[aa]->equalsVal(genericSubst->args[aa].Ptr()))
+ return false;
+ }
+
+ if (!outer)
+ return !genericSubst->outer;
+
+ if (!outer->equals(genericSubst->outer.Ptr()))
+ return false;
+
+ return true;
+}
+
+HashCode GenericSubstitution::_getHashCodeOverride() const
+{
+ HashCode rs = 0;
+ for (auto && v : args)
+ {
+ rs ^= v->getHashCode();
+ rs *= 16777619;
+ }
+ return rs;
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ThisTypeSubstitution !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+RefPtr<Substitutions> ThisTypeSubstitution::_applySubstitutionsShallowOverride(ASTBuilder* astBuilder, SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
+{
+ int diff = 0;
+
+ if (substOuter != outer) diff++;
+
+ // NOTE: Must use .as because we must have a smart pointer here to keep in scope.
+ auto substWitness = witness->substituteImpl(astBuilder, substSet, &diff).as<SubtypeWitness>();
+
+ if (!diff) return this;
+
+ (*ioDiff)++;
+ auto substSubst = astBuilder->create<ThisTypeSubstitution>();
+ substSubst->interfaceDecl = interfaceDecl;
+ substSubst->witness = substWitness;
+ substSubst->outer = substOuter;
+ return substSubst;
+}
+
+bool ThisTypeSubstitution::_equalsOverride(Substitutions* subst)
+{
+ if (!subst)
+ return false;
+ if (subst == this)
+ return true;
+
+ if (auto thisTypeSubst = as<ThisTypeSubstitution>(subst))
+ {
+ // For our purposes, two this-type substitutions are
+ // equivalent if they have the same type as `This`,
+ // even if the specific witness values they use
+ // might differ.
+ //
+ if (this->interfaceDecl != thisTypeSubst->interfaceDecl)
+ return false;
+
+ if (!this->witness->sub->equals(thisTypeSubst->witness->sub))
+ return false;
+
+ return true;
+ }
+ return false;
+}
+
+HashCode ThisTypeSubstitution::_getHashCodeOverride() const
+{
+ return witness->getHashCode();
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! GlobalGenericParamSubstitution !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+RefPtr<Substitutions> GlobalGenericParamSubstitution::_applySubstitutionsShallowOverride(ASTBuilder* astBuilder, SubstitutionSet substSet, RefPtr<Substitutions> substOuter, int* ioDiff)
+{
+ // if we find a GlobalGenericParamSubstitution in subst that references the same type_param decl
+ // return a copy of that GlobalGenericParamSubstitution
+ int diff = 0;
+
+ if (substOuter != outer) diff++;
+
+ auto substActualType = actualType->substituteImpl(astBuilder, substSet, &diff).as<Type>();
+
+ List<ConstraintArg> substConstraintArgs;
+ for (auto constraintArg : constraintArgs)
+ {
+ ConstraintArg substConstraintArg;
+ substConstraintArg.decl = constraintArg.decl;
+ substConstraintArg.val = constraintArg.val->substituteImpl(astBuilder, substSet, &diff);
+
+ substConstraintArgs.add(substConstraintArg);
+ }
+
+ if (!diff)
+ return this;
+
+ (*ioDiff)++;
+
+ RefPtr<GlobalGenericParamSubstitution> substSubst = astBuilder->create<GlobalGenericParamSubstitution>();
+ substSubst->paramDecl = paramDecl;
+ substSubst->actualType = substActualType;
+ substSubst->constraintArgs = substConstraintArgs;
+ substSubst->outer = substOuter;
+ return substSubst;
+}
+
+bool GlobalGenericParamSubstitution::_equalsOverride(Substitutions* subst)
+{
+ if (!subst)
+ return false;
+ if (subst == this)
+ return true;
+
+ if (auto genSubst = as<GlobalGenericParamSubstitution>(subst))
+ {
+ if (paramDecl != genSubst->paramDecl)
+ return false;
+ if (!actualType->equalsVal(genSubst->actualType))
+ return false;
+ if (constraintArgs.getCount() != genSubst->constraintArgs.getCount())
+ return false;
+ for (Index i = 0; i < constraintArgs.getCount(); i++)
+ {
+ if (!constraintArgs[i].val->equalsVal(genSubst->constraintArgs[i].val))
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+HashCode GlobalGenericParamSubstitution::_getHashCodeOverride() const
+{
+ HashCode rs = actualType->getHashCode();
+ for (auto && a : constraintArgs)
+ {
+ rs = combineHash(rs, a.val->getHashCode());
+ }
+ return rs;
+}
+
+
+} // namespace Slang