diff options
| author | Yong He <yonghe@outlook.com> | 2017-11-03 18:55:03 -0400 |
|---|---|---|
| committer | Yong He <yonghe@outlook.com> | 2017-11-03 18:55:03 -0400 |
| commit | 0a3656788473244b4760791c4129a4080a6631f6 (patch) | |
| tree | 98f47426d4b4cf08f31416e9dfb32df0bebbc7c8 /source/slang/check.cpp | |
| parent | 38ec0e0976010aee2f68dba47563adba798cfcc3 (diff) | |
associatedtypes: generating almost correct HLSL, but is not calling correctly mangled function.
Diffstat (limited to 'source/slang/check.cpp')
| -rw-r--r-- | source/slang/check.cpp | 157 |
1 files changed, 145 insertions, 12 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 137b1c451..240ac2d05 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -148,13 +148,15 @@ namespace Slang if (baseExpr) { RefPtr<Expr> expr; - + DeclRef<Decl> *declRefOut; if (baseExpr->type->As<TypeType>()) { auto sexpr = new StaticMemberExpr(); sexpr->loc = loc; sexpr->BaseExpression = baseExpr; sexpr->name = declRef.GetName(); + sexpr->declRef = declRef; + declRefOut = &sexpr->declRef; expr = sexpr; } else @@ -164,24 +166,88 @@ namespace Slang sexpr->BaseExpression = baseExpr; sexpr->name = declRef.GetName(); sexpr->declRef = declRef; + declRefOut = &sexpr->declRef; expr = sexpr; } if (auto assocTypeDecl = declRef.As<AssocTypeDecl>()) { RefPtr<ThisTypeSubstitution> subst = new ThisTypeSubstitution(); - subst->sourceType = baseExpr->type.type; + 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; + return expr; } else if (auto constraintDecl = declRef.As<GenericTypeConstraintDecl>()) { - expr->type = baseExpr->type; + 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; + } } - else + 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; } else @@ -908,12 +974,36 @@ namespace Slang } // - - if (auto toDeclRefType = toType->As<DeclRefType>()) { auto toTypeDeclRef = toDeclRefType->declRef; - if (auto interfaceDeclRef = toTypeDeclRef.As<InterfaceDecl>()) + 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>()) { // Trying to convert to an interface type. // @@ -927,8 +1017,42 @@ namespace Slang return true; } } - } + else if (auto genParamDeclRef = toTypeDeclRef.As<GenericTypeParamDecl>()) + { + // We need to enumerate the constraints placed on this type by its outer + // generic declaration, and see if any of them guarantees that we + // satisfy the given interface.. + auto genericDeclRef = genParamDeclRef.GetParent().As<GenericDecl>(); + SLANG_ASSERT(genericDeclRef); + + for (auto constraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(genericDeclRef)) + { + auto sub = GetSub(constraintDeclRef); + auto sup = GetSup(constraintDeclRef); + auto subDeclRef = sub->As<DeclRefType>(); + if (!subDeclRef) + continue; + if (subDeclRef->declRef != genParamDeclRef) + continue; + auto supDeclRefType = sup->As<DeclRefType>(); + if (supDeclRefType) + { + auto toInterfaceDeclRef = supDeclRefType->declRef.As<InterfaceDecl>(); + if (DoesTypeConformToInterface(fromType, toInterfaceDeclRef)) + { + if (outToExpr) + *outToExpr = CreateImplicitCastExpr(toType, fromExpr); + if (outCost) + *outCost = kConversionCost_CastToInterface; + return true; + } + } + } + + } + + } // Look for an initializer/constructor declaration in the target type, // which is marked as usable for implicit conversion, and which takes // the source type as an argument. @@ -1891,6 +2015,8 @@ namespace Slang void visitFuncDecl(FuncDecl *functionNode) { + if (functionNode->nameAndLoc.name->text == "test") + printf("break"); if (functionNode->IsChecked(DeclCheckState::Checked)) return; @@ -4384,7 +4510,7 @@ namespace Slang callExpr->FunctionExpr = baseExpr; - callExpr->type = QualType(candidate.resultType);// QualType(baseExpr->type->As<FuncType>()->resultType); + callExpr->type = QualType(candidate.resultType); // A call may yield an l-value, and we should take a look at the candidate to be sure if(auto subscriptDeclRef = candidate.item.declRef.As<SubscriptDecl>()) @@ -4575,9 +4701,7 @@ namespace Slang OverloadCandidate candidate; candidate.flavor = OverloadCandidate::Flavor::Func; candidate.item = item; - auto baseExpr = ConstructLookupResultExpr( - item, context.baseExpr, context.funcLoc); - candidate.resultType = baseExpr->type->As<FuncType>()->resultType; // GetResultType(funcDeclRef); + candidate.resultType = GetResultType(funcDeclRef); AddOverloadCandidate(context, candidate); } @@ -5739,6 +5863,9 @@ namespace Slang RefPtr<Expr> visitInvokeExpr(InvokeExpr *expr) { + if (auto mbrExpr = expr->FunctionExpr->As<MemberExpr>()) + if (mbrExpr->name->text == "add") + printf("break"); // check the base expression first expr->FunctionExpr = CheckExpr(expr->FunctionExpr); @@ -6471,6 +6598,12 @@ namespace Slang auto type = getFuncType(session, funcDeclRef); return QualType(type); } + else if (auto constraintDeclRef = declRef.As<GenericTypeConstraintDecl>()) + { + auto type = DeclRefType::Create(session, constraintDeclRef); + *outTypeResult = type; + return QualType(getTypeType(type)); + } if( sink ) { sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration"); |
