summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/check.cpp181
-rw-r--r--source/slang/slang.natvis9
-rw-r--r--source/slang/syntax.cpp18
3 files changed, 96 insertions, 112 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 240ac2d05..8e504e783 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -140,6 +140,55 @@ namespace Slang
return result;
}
+ void insertSubstAtBottom(DeclRefBase & declRef, RefPtr<Substitutions> substToInsert)
+ {
+ RefPtr<Substitutions> lastSubst;
+ auto subst = declRef.substitutions;
+ while (subst)
+ {
+ if (subst)
+ lastSubst = subst;
+ subst = subst->outer;
+ }
+ if (lastSubst)
+ lastSubst->outer = substToInsert;
+ else
+ declRef.substitutions = substToInsert;
+ }
+
+ RefPtr<ThisTypeSubstitution> getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry)
+ {
+ RefPtr<ThisTypeSubstitution> thisSubst;
+ auto subst = declRef.substitutions;
+ while (subst)
+ {
+ if (auto s = subst.As<ThisTypeSubstitution>())
+ {
+ thisSubst = s;
+ break;
+ }
+ subst = subst->outer;
+ }
+ if (!thisSubst)
+ {
+ thisSubst = new ThisTypeSubstitution();
+ if (insertSubstEntry)
+ {
+ insertSubstAtBottom(declRef, thisSubst);
+ }
+ }
+ return thisSubst;
+ }
+
+ RefPtr<DeclRefType> getExprDeclRefType(Expr * expr)
+ {
+ if (auto typetype = expr->type->As<TypeType>())
+ return typetype->type.As<DeclRefType>();
+ else
+ return expr->type->As<DeclRefType>();
+ }
+
+
RefPtr<Expr> ConstructDeclRefExpr(
DeclRef<Decl> declRef,
RefPtr<Expr> baseExpr,
@@ -169,84 +218,31 @@ namespace Slang
declRefOut = &sexpr->declRef;
expr = sexpr;
}
+
+ RefPtr<ThisTypeSubstitution> baseThisTypeSubst;
+ if (auto baseDeclRefExpr = baseExpr->As<DeclRefExpr>())
+ baseThisTypeSubst = getThisTypeSubst(baseDeclRefExpr->declRef, false);
+
if (auto assocTypeDecl = declRef.As<AssocTypeDecl>())
{
- RefPtr<ThisTypeSubstitution> subst = new ThisTypeSubstitution();
- auto baseDeclRefType = baseExpr->type.type.As<DeclRefType>();
- if (baseDeclRefType && !baseDeclRefType->declRef.getDecl()->As<InterfaceDecl>())
- {
- // if base type is not an interface, insert a non-trivial this_type substitution
- subst->sourceType = baseExpr->type.type;
- }
- else
- {
- // otherwise, insert a null this type substitution, indicating that "this_type" is currently a free variable
- subst->sourceType = nullptr;
- }
- if (auto typeType = subst->sourceType.As<TypeType>())
- subst->sourceType = typeType->type;
- expr->type = GetTypeForDeclRef(DeclRef<AssocTypeDecl>(assocTypeDecl.getDecl(), subst));
- declRefOut->substitutions = subst;
+ if (!baseThisTypeSubst)
+ baseThisTypeSubst = new ThisTypeSubstitution();
+ expr->type = GetTypeForDeclRef(DeclRef<AssocTypeDecl>(assocTypeDecl.getDecl(), baseThisTypeSubst));
+
+ RefPtr<ThisTypeSubstitution> outerSubst = getThisTypeSubst(*declRefOut, true);
+ outerSubst->sourceType = expr->type.type;
+ if (auto outerTypeType = outerSubst->sourceType.As<TypeType>())
+ outerSubst->sourceType = outerTypeType->type;
+ declRefOut->substitutions = outerSubst;
return expr;
}
- else if (auto constraintDecl = declRef.As<GenericTypeConstraintDecl>())
+
+ // propagate "this-type" substitutions
+ if (baseThisTypeSubst)
{
- expr = baseExpr;
if (auto declRefExpr = expr.As<DeclRefExpr>())
- declRefOut = &declRefExpr->declRef;
- else
- return expr;
- RefPtr<DeclRefType> declRefType;
- if (auto typeType = baseExpr->type.type.As<TypeType>())
- declRefType = typeType->type->As<DeclRefType>();
- else
- declRefType = baseExpr->type.type.As<DeclRefType>();
-
- if (declRefType)
- {
- RefPtr<ThisTypeSubstitution> subst = new ThisTypeSubstitution();
- subst->sourceType = declRefType;
- auto exprType = DeclRefType::Create(getSession(), DeclRef<Decl>(declRefType->declRef.decl, declRef.substitutions));
- subst->outer = declRef.substitutions;
- exprType->declRef.substitutions = subst;
- declRefOut->substitutions = subst;
- expr->type = exprType;
- return expr;
- }
+ insertSubstAtBottom(declRefExpr->declRef, baseThisTypeSubst);
}
- else if (auto callableDeclRef = declRef.As<CallableDecl>())
- {
- // propagate ThisTypeSubstitution
- RefPtr<DeclRefType> declRefType;
- if (auto typeType = baseExpr->type.type.As<TypeType>())
- declRefType = typeType->type->As<DeclRefType>();
- else
- declRefType = baseExpr->type.type.As<DeclRefType>();
- RefPtr<ThisTypeSubstitution> thisSubst;
- if (declRefType)
- {
- auto subst = declRefType->declRef.substitutions;
- while (subst)
- {
- thisSubst = subst.As<ThisTypeSubstitution>();
- if (thisSubst)
- {
- break;
- }
- subst = subst->outer;
- }
- }
- if (thisSubst)
- {
- auto newThisSubst = new ThisTypeSubstitution();
- newThisSubst->sourceType = thisSubst->sourceType;
- newThisSubst->outer = declRefType->declRef.substitutions;
- declRef.substitutions = thisSubst;
- }
- expr->type = GetTypeForDeclRef(declRef);
- *declRefOut = declRef;
- }
-
expr->type = GetTypeForDeclRef(declRef);
return expr;
}
@@ -256,6 +252,21 @@ namespace Slang
expr->loc = loc;
expr->name = declRef.GetName();
expr->type = GetTypeForDeclRef(declRef);
+ if (auto exprDeclRefType = getExprDeclRefType(expr))
+ {
+ if (auto genParmDecl = exprDeclRefType->declRef.As<GenericTypeParamDecl>())
+ {
+ // if this is a reference to generic type param, insert a this-type substitution
+ auto exprType = GetTypeForDeclRef(declRef);
+ auto thisSubst = new ThisTypeSubstitution();
+ if (auto typetype = exprType.type.As<TypeType>())
+ thisSubst->sourceType = typetype->type;
+ else
+ thisSubst->sourceType = exprType.type;
+ thisSubst->outer = declRef.substitutions;
+ declRef.substitutions = thisSubst;
+ }
+ }
expr->declRef = declRef;
return expr;
}
@@ -977,33 +988,7 @@ namespace Slang
if (auto toDeclRefType = toType->As<DeclRefType>())
{
auto toTypeDeclRef = toDeclRefType->declRef;
- if (auto assocDeclRef = toTypeDeclRef.As<AssocTypeDecl>())
- {
- if (auto fromTypeDeclRefType = fromType->As<DeclRefType>())
- {
- if (auto thisSubst = assocDeclRef.substitutions.As<ThisTypeSubstitution>())
- {
- if (auto fromThisSubst = fromTypeDeclRefType->declRef.substitutions.As<ThisTypeSubstitution>())
- {
- if (!thisSubst->sourceType || !fromThisSubst->sourceType)
- return true;
- if (CanCoerce(thisSubst->sourceType.As<Type>(), fromThisSubst->sourceType.As<Type>(), outCost))
- {
- if (outCost)
- *outCost = kConversionCost_CastToInterface;
- if (outToExpr)
- *outToExpr = fromExpr;
- return true;
- }
- }
- else
- return true;
- }
- else
- return true;
- }
- }
- else if (auto interfaceDeclRef = toTypeDeclRef.As<InterfaceDecl>())
+ if (auto interfaceDeclRef = toTypeDeclRef.As<InterfaceDecl>())
{
// Trying to convert to an interface type.
//
diff --git a/source/slang/slang.natvis b/source/slang/slang.natvis
index 357251dcd..31ffa5e80 100644
--- a/source/slang/slang.natvis
+++ b/source/slang/slang.natvis
@@ -56,4 +56,13 @@
</LinkedListItems>
</Expand>
</Type>
+ <Type Name="Slang::IRFunc">
+ <DisplayString>{{{mangledName}}}</DisplayString>
+ <Expand>
+ <Item Name="[Name]">mangledName</Item>
+ <Item Name="[ResultType]">(*(IRFuncType*)(type.pointer)).resultType</Item>
+ <Item Name="[ParameterTypes]">(*(IRFuncType*)(type.pointer)).paramTypes</Item>
+ <Item Name="[FirstBlock]">firstBlock</Item>
+ </Expand>
+ </Type>
</AutoVisualizer> \ No newline at end of file
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 2f3368f4c..24d508ed5 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -1213,7 +1213,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
}
if (!outer)
- return !subst->outer;
+ return !subst->outer || subst->outer.As<ThisTypeSubstitution>();
if (!outer->Equals(subst->outer.Ptr()))
return false;
@@ -1258,19 +1258,9 @@ void Type::accept(IValVisitor* visitor, void* extra)
bool ThisTypeSubstitution::Equals(Substitutions* subst)
{
- // both must be NULL, or non-NULL
- if (!this || !subst)
- return !this && !subst;
- auto thisSubst = dynamic_cast<ThisTypeSubstitution*>(subst);
- if (!thisSubst)
- return false;
- if (!sourceType && thisSubst->sourceType || sourceType && !thisSubst->sourceType)
- return false;
- if (thisSubst->sourceType && !thisSubst->sourceType->EqualsVal(sourceType))
- return false;
- if (!outer->Equals(subst->outer.Ptr()))
- return false;
- return true;
+ if (subst && dynamic_cast<ThisTypeSubstitution*>(subst))
+ return true;
+ return false;
}