diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/check.cpp | 83 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 6 | ||||
| -rw-r--r-- | source/slang/ir-insts.h | 3 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 17 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 8 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 7 | ||||
| -rw-r--r-- | source/slang/mangle.cpp | 4 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 118 | ||||
| -rw-r--r-- | source/slang/type-defs.h | 33 |
9 files changed, 243 insertions, 36 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp index fe7498d86..2f4ed2ce8 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -147,26 +147,64 @@ namespace Slang { if (baseExpr) { + RefPtr<Expr> expr; + if (baseExpr->type->As<TypeType>()) { - auto expr = new StaticMemberExpr(); - expr->loc = loc; - expr->BaseExpression = baseExpr; - expr->name = declRef.GetName(); - expr->type = GetTypeForDeclRef(declRef); - expr->declRef = declRef; - return expr; + auto sexpr = new StaticMemberExpr(); + sexpr->loc = loc; + sexpr->BaseExpression = baseExpr; + sexpr->name = declRef.GetName(); + sexpr->type = GetTypeForDeclRef(declRef); + sexpr->declRef = declRef; + expr = sexpr; } else { - auto expr = new MemberExpr(); - expr->loc = loc; - expr->BaseExpression = baseExpr; - expr->name = declRef.GetName(); - expr->type = GetTypeForDeclRef(declRef); - expr->declRef = declRef; - return expr; + auto sexpr = new MemberExpr(); + sexpr->loc = loc; + sexpr->BaseExpression = baseExpr; + sexpr->name = declRef.GetName(); + sexpr->type = GetTypeForDeclRef(declRef); + sexpr->declRef = declRef; + expr = sexpr; + } + if (auto assocTypeDeclRef = declRef.As<AssocTypeDecl>()) + { + if (auto genConstraintType = baseExpr->type->As<GenericConstraintDeclRefType>()) + { + // if this is a reference from a generic parameter, we need to generate a AssocTypeDeclRefType type. + // for example, if we have an expression T.U where T:ISimple, and U is an associated type defined in ISimple. + // then this expression should evaluate to AssocTypeDeclRefType(T, U). + auto assocTypeDeclType = new AssocTypeDeclRefType(); + assocTypeDeclType->declRef = assocTypeDeclRef; + assocTypeDeclType->sourceType = genConstraintType->subType; + assocTypeDeclType->setSession(getSession()); + expr->type = QualType(getTypeType(assocTypeDeclType)); + } } + else if (auto funcDeclRef = declRef.As<CallableDecl>()) + { + if (auto genConstraintType = baseExpr->type->As<GenericConstraintDeclRefType>()) + { + // if this is call expression, propagate the source associated type to the result type + auto funcType = expr->type->As<FuncType>(); + if (auto assocRsType = funcType->resultType.As<AssocTypeDeclRefType>()) + { + RefPtr<FuncType> newFuncType = new FuncType(); + newFuncType->paramTypes = funcType->paramTypes; + RefPtr<AssocTypeDeclRefType> newRsType = new AssocTypeDeclRefType(); + newRsType->declRef = assocRsType->declRef; + newRsType->sourceType = genConstraintType->subType; + newRsType->setSession(getSession()); + newFuncType->resultType = newRsType; + newFuncType->setSession(funcType->getSession()); + expr->type = QualType(newFuncType); + } + + } + } + return expr; } else { @@ -1878,7 +1916,6 @@ namespace Slang VisitFunctionDeclaration(functionNode); // TODO: This should really onlye set "checked header" functionNode->SetCheckState(DeclCheckState::Checked); - // TODO: should put the checking of the body onto a "work list" // to avoid recursion here. if (functionNode->Body) @@ -2309,7 +2346,6 @@ namespace Slang { if (functionNode->IsChecked(DeclCheckState::CheckedHeader)) return; functionNode->SetCheckState(DeclCheckState::CheckingHeader); - this->function = functionNode; auto returnType = CheckProperType(functionNode->ReturnType); functionNode->ReturnType = returnType; @@ -4366,7 +4402,7 @@ namespace Slang callExpr->FunctionExpr = baseExpr; - callExpr->type = QualType(candidate.resultType); + callExpr->type = QualType(candidate.resultType);// QualType(baseExpr->type->As<FuncType>()->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>()) @@ -4557,7 +4593,9 @@ namespace Slang OverloadCandidate candidate; candidate.flavor = OverloadCandidate::Flavor::Func; candidate.item = item; - candidate.resultType = GetResultType(funcDeclRef); + auto baseExpr = ConstructLookupResultExpr( + item, context.baseExpr, context.funcLoc); + candidate.resultType = baseExpr->type->As<FuncType>()->resultType; // GetResultType(funcDeclRef); AddOverloadCandidate(context, candidate); } @@ -5717,10 +5755,6 @@ namespace Slang RefPtr<Expr> visitInvokeExpr(InvokeExpr *expr) { - if (auto appExpr = expr->FunctionExpr->As<GenericAppExpr>()) - if (auto varExpr = appExpr->FunctionExpr->As<VarExpr>()) - if (varExpr->name->text == "test") - printf("break"); // check the base expression first expr->FunctionExpr = CheckExpr(expr->FunctionExpr); @@ -6453,7 +6487,7 @@ namespace Slang // When we access a constraint or an inheritance decl (as a member), // we are conceptually performing a "cast" to the given super-type, // with the declaration showing that such a cast is legal. - auto type = GetSup(constraintDeclRef); + auto type = new GenericConstraintDeclRefType(session, GetSub(constraintDeclRef), GetSup(constraintDeclRef)); return QualType(type); } else if (auto funcDeclRef = declRef.As<CallableDecl>()) @@ -6463,7 +6497,8 @@ namespace Slang } else if (auto assocTypeDeclRef = declRef.As<AssocTypeDecl>()) { - auto type = DeclRefType::Create(session, assocTypeDeclRef); + auto type = new AssocTypeDeclRefType(assocTypeDeclRef); + type->setSession(session); *outTypeResult = type; return QualType(getTypeType(type)); } diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 3454a3f85..9caad2e1a 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1054,7 +1054,11 @@ struct EmitVisitor void visitAssocTypeDeclRefType(AssocTypeDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) { - SLANG_UNREACHABLE("visitAssocTypeDeclRefType in EmitVisitor"); + //SLANG_UNREACHABLE("visitAssocTypeDeclRefType in EmitVisitor"); + } + void visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* /*type*/, TypeEmitArg const& /*arg*/) + { + //SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in EmitVisitor"); } void visitBasicExpressionType(BasicExpressionType* basicType, TypeEmitArg const& arg) diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h index f7bcc2eb2..587fe3cd2 100644 --- a/source/slang/ir-insts.h +++ b/source/slang/ir-insts.h @@ -346,10 +346,9 @@ struct IRBuilder IRValue* getBoolValue(bool value); IRValue* getIntValue(IRType* type, IRIntegerValue value); IRValue* getFloatValue(IRType* type, IRFloatingPointValue value); - IRValue* getDeclRefVal( DeclRefBase const& declRef); - + IRValue* getTypeVal(IRType* type); // create an IR value that represents a type IRValue* emitSpecializeInst( IRType* type, IRValue* genericVal, diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 5cc73a36b..84ab3d9a5 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -562,6 +562,16 @@ namespace Slang return irValue; } + IRValue * IRBuilder::getTypeVal(IRType * type) + { + auto irValue = createValue<IRDeclRef>( + this, + kIROp_TypeType, + nullptr); + irValue->type = type; + return irValue; + } + IRValue* IRBuilder::emitSpecializeInst( Type* type, IRValue* genericVal, @@ -3061,7 +3071,12 @@ namespace Slang return builder->getDeclRefVal(declRef); } break; - + case kIROp_TypeType: + { + IRValue* od = (IRValue*)originalValue; + return builder->getTypeVal(od->type); + } + break; default: SLANG_UNEXPECTED("no value registered for IR value"); return nullptr; diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 93b84ad31..998197279 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -2062,6 +2062,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> SLANG_UNIMPLEMENTED_X("decl catch-all"); } + LoweredValInfo visitTypeDefDecl(TypeDefDecl * decl) + { + return LoweredValInfo::simple(context->irBuilder->getTypeVal(decl->type.type)); + } + LoweredValInfo visitGenericTypeParamDecl(GenericTypeParamDecl* decl) { return LoweredValInfo(); @@ -2307,7 +2312,8 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // For now, we don't have an IR-level representation // for the type itself. - return LoweredValInfo(); + return LoweredValInfo::simple(context->irBuilder->getTypeVal(DeclRefType::Create(context->getSession(), + DeclRef<Decl>(decl, nullptr)))); } diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 776a55530..b810d9643 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -779,6 +779,13 @@ struct LoweringVisitor translateDeclRef(DeclRef<Decl>(type->declRef)).As<TypeDefDecl>()); } + RefPtr<Type> visitGenericConstraintDeclRefType(GenericConstraintDeclRefType* type) + { + // not supported by lowering + SLANG_UNREACHABLE("visitGenericConstraintDeclRefType in LowerVisitor"); + return nullptr; + } + RefPtr<Type> visitAssocTypeDeclRefType(AssocTypeDeclRefType* type) { // not supported by lowering diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index 63e54d065..cd90a0e41 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -117,6 +117,10 @@ namespace Slang { emitQualifiedName(context, declRefType->declRef); } + else if (auto assocTypeDeclRefType = dynamic_cast<AssocTypeDeclRefType*>(type)) + { + emitQualifiedName(context, assocTypeDeclRefType->declRef); + } else { SLANG_UNEXPECTED("unimplemented case in mangling"); diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 97f3cfb15..fd7fc0e14 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -959,15 +959,60 @@ void Type::accept(IValVisitor* visitor, void* extra) RefPtr<Val> AssocTypeDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) { - auto parentType = this->GetDeclRef().GetParent().SubstituteImpl(subst, ioDiff); - if (auto aggDeclRef = parentType.As<AggTypeDecl>()) + if (!sourceType) + return this; + if (auto parentDeclRefType = sourceType->As<DeclRefType>()) { - Decl* targetTypeDecl = nullptr; - if (aggDeclRef.getDecl()->memberDictionary.TryGetValue(this->GetDeclRef().decl->getName(), targetTypeDecl)) + auto parentDeclRef = parentDeclRefType->declRef; + DeclRef<AggTypeDecl> newParentDeclRef = parentDeclRef.As<AggTypeDecl>(); + // search for a substitution that might apply to us + for (auto s = subst; s; s = s->outer.Ptr()) { - return DeclRefType::Create(this->session, DeclRef<Decl>(targetTypeDecl, parentType.substitutions)); + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = s->genericDecl; + if (genericDecl != parentDeclRef.getDecl()->ParentDecl) + continue; + int index = 0; + for (auto m : genericDecl->Members) + { + if (m.Ptr() == parentDeclRef.getDecl()) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + if (auto declRef = s->args[index].As<DeclRefType>()) + { + newParentDeclRef = (*declRef).declRef.As<AggTypeDecl>(); + goto searchEnd; + } + } + else if (auto typeParam = m.As<GenericTypeParamDecl>()) + { + index++; + } + else if (auto valParam = m.As<GenericValueParamDecl>()) + { + index++; + } + else + { + } + } + } + searchEnd: + if (newParentDeclRef) + { + Decl* targetTypeDecl = nullptr; + if (newParentDeclRef.getDecl()->memberDictionary.TryGetValue(this->GetDeclRef().decl->getName(), targetTypeDecl)) + { + if (auto typeDefDecl = targetTypeDecl->As<TypeDefDecl>()) + return GetType(DeclRef<TypeDefDecl>(typeDefDecl, subst)); + else + return DeclRefType::Create(this->getSession(), DeclRef<Decl>(targetTypeDecl, subst)); + } } } + return this; } @@ -981,6 +1026,69 @@ void Type::accept(IValVisitor* visitor, void* extra) return this; } + // GenericConstraintDeclRefType + + String GenericConstraintDeclRefType::ToString() + { + // TODO: what is appropriate here? + return "<GenericConstraintType>"; + } + + bool GenericConstraintDeclRefType::EqualsImpl(Type * type) + { + if (auto other = type->As<GenericConstraintDeclRefType>()) + { + return supType->Equals(other->supType) && subType->Equals(other->subType); + } + return false; + } + + RefPtr<Val> GenericConstraintDeclRefType::SubstituteImpl(Substitutions* subst, int* ioDiff) + { + auto genParamDecl = subType.As<DeclRefType>()->declRef.As<GenericTypeParamDecl>(); + // search for a substitution that might apply to us + for (auto s = subst; s; s = s->outer.Ptr()) + { + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto genericDecl = s->genericDecl; + if (genericDecl != genParamDecl.getDecl()->ParentDecl) + continue; + int index = 0; + for (auto m : genericDecl->Members) + { + if (m.Ptr() == genParamDecl.getDecl()) + { + // We've found it, so return the corresponding specialization argument + (*ioDiff)++; + return s->args[index]; + } + else if (auto typeParam = m.As<GenericTypeParamDecl>()) + { + index++; + } + else if (auto valParam = m.As<GenericValueParamDecl>()) + { + index++; + } + else + { + } + } + } + return this; + } + + int GenericConstraintDeclRefType::GetHashCode() + { + return combineHash(subType.GetHashCode(), supType.GetHashCode()); + } + + Type* GenericConstraintDeclRefType::CreateCanonicalType() + { + return this; + } + // ArithmeticExpressionType // VectorExpressionType diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index 15dfe3e07..2052e1eb8 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -449,7 +449,6 @@ SYNTAX_CLASS(FuncType, Type) FIELD(List<RefPtr<Type>>, paramTypes) FIELD(RefPtr<Type>, resultType) - RAW( FuncType() {} @@ -495,7 +494,7 @@ END_SYNTAX_CLASS() // The "type" of an expression that references a asscoiated type decl (via 'assoctype' keyword). SYNTAX_CLASS(AssocTypeDeclRefType, Type) DECL_FIELD(DeclRef<AssocTypeDecl>, declRef) - + DECL_FIELD(RefPtr<Type>, sourceType) RAW( AssocTypeDeclRefType() {} @@ -515,4 +514,34 @@ SYNTAX_CLASS(AssocTypeDeclRefType, Type) virtual int GetHashCode() override; virtual Type* CreateCanonicalType() override; ) +END_SYNTAX_CLASS() + +// The "type" of an generic constraint, which wraps both the sub and sup (interface) type +// the sub type can be used in associated type substitution in later type evaluation +SYNTAX_CLASS(GenericConstraintDeclRefType, Type) + DECL_FIELD(RefPtr<Type>, subType) + DECL_FIELD(RefPtr<Type>, supType) +RAW( + GenericConstraintDeclRefType() + {} + GenericConstraintDeclRefType(Session* session, + RefPtr<Type> sub, + RefPtr<Type> sup) + : subType(sub), supType(sup) + { + setSession(session); + } + + + RefPtr<Type> const& GetSupType() const { return supType; } + RefPtr<Type> const& GetSubType() const { return subType; } + + virtual String ToString() override; + + protected: + virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual Type* CreateCanonicalType() override; +) END_SYNTAX_CLASS()
\ No newline at end of file |
