From 76db3636418f1667db1c8b0d3b6cfec6c652cc84 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 4 Nov 2017 06:57:48 -0400 Subject: work in-progress --- source/slang/check.cpp | 181 +++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 98 deletions(-) (limited to 'source/slang/check.cpp') 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 substToInsert) + { + RefPtr lastSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (subst) + lastSubst = subst; + subst = subst->outer; + } + if (lastSubst) + lastSubst->outer = substToInsert; + else + declRef.substitutions = substToInsert; + } + + RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry) + { + RefPtr thisSubst; + auto subst = declRef.substitutions; + while (subst) + { + if (auto s = subst.As()) + { + thisSubst = s; + break; + } + subst = subst->outer; + } + if (!thisSubst) + { + thisSubst = new ThisTypeSubstitution(); + if (insertSubstEntry) + { + insertSubstAtBottom(declRef, thisSubst); + } + } + return thisSubst; + } + + RefPtr getExprDeclRefType(Expr * expr) + { + if (auto typetype = expr->type->As()) + return typetype->type.As(); + else + return expr->type->As(); + } + + RefPtr ConstructDeclRefExpr( DeclRef declRef, RefPtr baseExpr, @@ -169,84 +218,31 @@ namespace Slang declRefOut = &sexpr->declRef; expr = sexpr; } + + RefPtr baseThisTypeSubst; + if (auto baseDeclRefExpr = baseExpr->As()) + baseThisTypeSubst = getThisTypeSubst(baseDeclRefExpr->declRef, false); + if (auto assocTypeDecl = declRef.As()) { - RefPtr subst = new ThisTypeSubstitution(); - auto baseDeclRefType = baseExpr->type.type.As(); - if (baseDeclRefType && !baseDeclRefType->declRef.getDecl()->As()) - { - // 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()) - subst->sourceType = typeType->type; - expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), subst)); - declRefOut->substitutions = subst; + if (!baseThisTypeSubst) + baseThisTypeSubst = new ThisTypeSubstitution(); + expr->type = GetTypeForDeclRef(DeclRef(assocTypeDecl.getDecl(), baseThisTypeSubst)); + + RefPtr outerSubst = getThisTypeSubst(*declRefOut, true); + outerSubst->sourceType = expr->type.type; + if (auto outerTypeType = outerSubst->sourceType.As()) + outerSubst->sourceType = outerTypeType->type; + declRefOut->substitutions = outerSubst; return expr; } - else if (auto constraintDecl = declRef.As()) + + // propagate "this-type" substitutions + if (baseThisTypeSubst) { - expr = baseExpr; if (auto declRefExpr = expr.As()) - declRefOut = &declRefExpr->declRef; - else - return expr; - RefPtr declRefType; - if (auto typeType = baseExpr->type.type.As()) - declRefType = typeType->type->As(); - else - declRefType = baseExpr->type.type.As(); - - if (declRefType) - { - RefPtr subst = new ThisTypeSubstitution(); - subst->sourceType = declRefType; - auto exprType = DeclRefType::Create(getSession(), DeclRef(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()) - { - // propagate ThisTypeSubstitution - RefPtr declRefType; - if (auto typeType = baseExpr->type.type.As()) - declRefType = typeType->type->As(); - else - declRefType = baseExpr->type.type.As(); - RefPtr thisSubst; - if (declRefType) - { - auto subst = declRefType->declRef.substitutions; - while (subst) - { - thisSubst = subst.As(); - 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()) + { + // 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()) + 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()) { auto toTypeDeclRef = toDeclRefType->declRef; - if (auto assocDeclRef = toTypeDeclRef.As()) - { - if (auto fromTypeDeclRefType = fromType->As()) - { - if (auto thisSubst = assocDeclRef.substitutions.As()) - { - if (auto fromThisSubst = fromTypeDeclRefType->declRef.substitutions.As()) - { - if (!thisSubst->sourceType || !fromThisSubst->sourceType) - return true; - if (CanCoerce(thisSubst->sourceType.As(), fromThisSubst->sourceType.As(), outCost)) - { - if (outCost) - *outCost = kConversionCost_CastToInterface; - if (outToExpr) - *outToExpr = fromExpr; - return true; - } - } - else - return true; - } - else - return true; - } - } - else if (auto interfaceDeclRef = toTypeDeclRef.As()) + if (auto interfaceDeclRef = toTypeDeclRef.As()) { // Trying to convert to an interface type. // -- cgit v1.2.3