summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/check.cpp83
-rw-r--r--source/slang/emit.cpp6
-rw-r--r--source/slang/ir-insts.h3
-rw-r--r--source/slang/ir.cpp17
-rw-r--r--source/slang/lower-to-ir.cpp8
-rw-r--r--source/slang/lower.cpp7
-rw-r--r--source/slang/mangle.cpp4
-rw-r--r--source/slang/syntax.cpp118
-rw-r--r--source/slang/type-defs.h33
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