summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-type.cpp
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2024-10-29 14:49:26 +0800
committerGitHub <noreply@github.com>2024-10-29 14:49:26 +0800
commitf65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch)
treeea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-check-type.cpp
parenta729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff)
format
* format * Minor test fixes * enable checking cpp format in ci
Diffstat (limited to 'source/slang/slang-check-type.cpp')
-rw-r--r--source/slang/slang-check-type.cpp716
1 files changed, 361 insertions, 355 deletions
diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp
index eeee13561..34f16751b 100644
--- a/source/slang/slang-check-type.cpp
+++ b/source/slang/slang-check-type.cpp
@@ -6,467 +6,473 @@
namespace Slang
{
- Type* checkProperType(
- Linkage* linkage,
- TypeExp typeExp,
- DiagnosticSink* sink)
- {
- SharedSemanticsContext sharedSemanticsContext(
- linkage,
- nullptr,
- sink);
- SemanticsVisitor visitor(&sharedSemanticsContext);
+Type* checkProperType(Linkage* linkage, TypeExp typeExp, DiagnosticSink* sink)
+{
+ SharedSemanticsContext sharedSemanticsContext(linkage, nullptr, sink);
+ SemanticsVisitor visitor(&sharedSemanticsContext);
- SLANG_AST_BUILDER_RAII(linkage->getASTBuilder());
+ SLANG_AST_BUILDER_RAII(linkage->getASTBuilder());
- auto typeOut = visitor.CheckProperType(typeExp);
- return typeOut.type;
- }
+ auto typeOut = visitor.CheckProperType(typeExp);
+ return typeOut.type;
+}
- Type* getPointedToTypeIfCanImplicitDeref(Type* type)
+Type* getPointedToTypeIfCanImplicitDeref(Type* type)
+{
+ if (auto ptrLike = as<PointerLikeType>(type))
{
- if (auto ptrLike = as<PointerLikeType>(type))
- {
- return ptrLike->getElementType();
- }
- else if (auto ptrType = as<PtrType>(type))
- {
- return ptrType->getValueType();
- }
- else if (auto refType = as<RefType>(type))
- {
- return refType->getValueType();
- }
- return nullptr;
+ return ptrLike->getElementType();
}
-
- Expr* SemanticsVisitor::TranslateTypeNodeImpl(Expr* node)
+ else if (auto ptrType = as<PtrType>(type))
{
- if (!node) return nullptr;
-
- auto expr = CheckTerm(node);
- expr = ExpectATypeRepr(expr);
- return expr;
+ return ptrType->getValueType();
}
-
- Type* SemanticsVisitor::ExtractTypeFromTypeRepr(Expr* typeRepr)
+ else if (auto refType = as<RefType>(type))
{
- if (!typeRepr) return nullptr;
- if (auto typeType = as<TypeType>(typeRepr->type))
- {
- return typeType->getType();
- }
- return m_astBuilder->getErrorType();
+ return refType->getValueType();
}
+ return nullptr;
+}
+
+Expr* SemanticsVisitor::TranslateTypeNodeImpl(Expr* node)
+{
+ if (!node)
+ return nullptr;
+
+ auto expr = CheckTerm(node);
+ expr = ExpectATypeRepr(expr);
+ return expr;
+}
- Type* SemanticsVisitor::TranslateTypeNode(Expr* node)
+Type* SemanticsVisitor::ExtractTypeFromTypeRepr(Expr* typeRepr)
+{
+ if (!typeRepr)
+ return nullptr;
+ if (auto typeType = as<TypeType>(typeRepr->type))
{
- if (!node) return nullptr;
- auto typeRepr = TranslateTypeNodeImpl(node);
- return ExtractTypeFromTypeRepr(typeRepr);
+ return typeType->getType();
}
+ return m_astBuilder->getErrorType();
+}
- TypeExp SemanticsVisitor::TranslateTypeNodeForced(TypeExp const& typeExp)
- {
- auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
+Type* SemanticsVisitor::TranslateTypeNode(Expr* node)
+{
+ if (!node)
+ return nullptr;
+ auto typeRepr = TranslateTypeNodeImpl(node);
+ return ExtractTypeFromTypeRepr(typeRepr);
+}
- TypeExp result;
- result.exp = typeRepr;
- result.type = ExtractTypeFromTypeRepr(typeRepr);
- return result;
- }
+TypeExp SemanticsVisitor::TranslateTypeNodeForced(TypeExp const& typeExp)
+{
+ auto typeRepr = TranslateTypeNodeImpl(typeExp.exp);
+
+ TypeExp result;
+ result.exp = typeRepr;
+ result.type = ExtractTypeFromTypeRepr(typeRepr);
+ return result;
+}
- TypeExp SemanticsVisitor::TranslateTypeNode(TypeExp const& typeExp)
+TypeExp SemanticsVisitor::TranslateTypeNode(TypeExp const& typeExp)
+{
+ // HACK(tfoley): It seems that in some cases we end up re-checking
+ // syntax that we've already checked. We need to root-cause that
+ // issue, but for now a quick fix in this case is to early
+ // exist if we've already got a type associated here:
+ if (typeExp.type)
{
- // HACK(tfoley): It seems that in some cases we end up re-checking
- // syntax that we've already checked. We need to root-cause that
- // issue, but for now a quick fix in this case is to early
- // exist if we've already got a type associated here:
- if (typeExp.type)
- {
- return typeExp;
- }
- return TranslateTypeNodeForced(typeExp);
+ return typeExp;
}
+ return TranslateTypeNodeForced(typeExp);
+}
- Type* SemanticsVisitor::getRemovedModifierType(ModifiedType* modifiedType, ModifierVal* modifier)
+Type* SemanticsVisitor::getRemovedModifierType(ModifiedType* modifiedType, ModifierVal* modifier)
+{
+ if (modifiedType->getModifierCount() == 1)
+ return modifiedType->getBase();
+ List<Val*> newModifiers;
+ for (Index i = 0; i < modifiedType->getModifierCount(); i++)
{
- if (modifiedType->getModifierCount() == 1)
- return modifiedType->getBase();
- List<Val*> newModifiers;
- for (Index i = 0; i < modifiedType->getModifierCount(); i++)
- {
- auto m = modifiedType->getModifier(i);
- if (m == modifier)
- continue;
- newModifiers.add(m);
- }
- return m_astBuilder->getModifiedType(modifiedType->getBase(), newModifiers);
+ auto m = modifiedType->getModifier(i);
+ if (m == modifier)
+ continue;
+ newModifiers.add(m);
}
+ return m_astBuilder->getModifiedType(modifiedType->getBase(), newModifiers);
+}
- Expr* SemanticsVisitor::ExpectATypeRepr(Expr* expr)
+Expr* SemanticsVisitor::ExpectATypeRepr(Expr* expr)
+{
+ if (auto overloadedExpr = as<OverloadedExpr>(expr))
{
- if (auto overloadedExpr = as<OverloadedExpr>(expr))
- {
- expr = resolveOverloadedExpr(overloadedExpr, LookupMask::type);
- }
-
- if (const auto typeType = as<TypeType>(expr->type))
- {
- return expr;
- }
- else if (const auto errorType = as<ErrorType>(expr->type))
- {
- return expr;
- }
-
- getSink()->diagnose(expr, Diagnostics::expectedAType, expr->type);
- return CreateErrorExpr(expr);
+ expr = resolveOverloadedExpr(overloadedExpr, LookupMask::type);
}
- Type* SemanticsVisitor::ExpectAType(Expr* expr)
+ if (const auto typeType = as<TypeType>(expr->type))
{
- auto typeRepr = ExpectATypeRepr(expr);
- if (auto typeType = as<TypeType>(typeRepr->type))
- {
- return typeType->getType();
- }
- return m_astBuilder->getErrorType();
+ return expr;
}
-
- Type* SemanticsVisitor::ExtractGenericArgType(Expr* exp)
+ else if (const auto errorType = as<ErrorType>(expr->type))
{
- return ExpectAType(exp);
+ return expr;
}
- IntVal* SemanticsVisitor::ExtractGenericArgInteger(Expr* exp, Type* genericParamType, DiagnosticSink* sink)
+ getSink()->diagnose(expr, Diagnostics::expectedAType, expr->type);
+ return CreateErrorExpr(expr);
+}
+
+Type* SemanticsVisitor::ExpectAType(Expr* expr)
+{
+ auto typeRepr = ExpectATypeRepr(expr);
+ if (auto typeType = as<TypeType>(typeRepr->type))
{
- IntVal* val = CheckIntegerConstantExpression(
- exp,
- genericParamType ? IntegerConstantExpressionCoercionType::SpecificType
- : IntegerConstantExpressionCoercionType::AnyInteger,
- genericParamType,
- ConstantFoldingKind::LinkTime,
- sink);
- if(val) return val;
-
- // If the argument expression could not be coerced to an integer
- // constant expression in context, then we will instead construct
- // a dummy "error" value to represent the result.
- //
- val = m_astBuilder->getOrCreate<ErrorIntVal>(m_astBuilder->getIntType());
- return val;
+ return typeType->getType();
}
+ return m_astBuilder->getErrorType();
+}
+
+Type* SemanticsVisitor::ExtractGenericArgType(Expr* exp)
+{
+ return ExpectAType(exp);
+}
+
+IntVal* SemanticsVisitor::ExtractGenericArgInteger(
+ Expr* exp,
+ Type* genericParamType,
+ DiagnosticSink* sink)
+{
+ IntVal* val = CheckIntegerConstantExpression(
+ exp,
+ genericParamType ? IntegerConstantExpressionCoercionType::SpecificType
+ : IntegerConstantExpressionCoercionType::AnyInteger,
+ genericParamType,
+ ConstantFoldingKind::LinkTime,
+ sink);
+ if (val)
+ return val;
+
+ // If the argument expression could not be coerced to an integer
+ // constant expression in context, then we will instead construct
+ // a dummy "error" value to represent the result.
+ //
+ val = m_astBuilder->getOrCreate<ErrorIntVal>(m_astBuilder->getIntType());
+ return val;
+}
- IntVal* SemanticsVisitor::ExtractGenericArgInteger(Expr* exp, Type* genericParamType)
+IntVal* SemanticsVisitor::ExtractGenericArgInteger(Expr* exp, Type* genericParamType)
+{
+ return ExtractGenericArgInteger(exp, genericParamType, getSink());
+}
+
+Val* SemanticsVisitor::ExtractGenericArgVal(Expr* exp)
+{
+ if (auto overloadedExpr = as<OverloadedExpr>(exp))
{
- return ExtractGenericArgInteger(exp, genericParamType, getSink());
+ // assume that if it is overloaded, we want a type
+ exp = resolveOverloadedExpr(overloadedExpr, LookupMask::type);
}
-
- Val* SemanticsVisitor::ExtractGenericArgVal(Expr* exp)
+ if (auto typeType = as<TypeType>(exp->type))
{
- if (auto overloadedExpr = as<OverloadedExpr>(exp))
- {
- // assume that if it is overloaded, we want a type
- exp = resolveOverloadedExpr(overloadedExpr, LookupMask::type);
- }
- if (auto typeType = as<TypeType>(exp->type))
- {
- return typeType->getType();
- }
- else if (const auto errorType = as<ErrorType>(exp->type))
- {
- return exp->type.type;
- }
- else
+ return typeType->getType();
+ }
+ else if (const auto errorType = as<ErrorType>(exp->type))
+ {
+ return exp->type.type;
+ }
+ else
+ {
+ if (!exp->type.type)
{
- if (!exp->type.type)
- {
- CheckExpr(exp);
- }
- return ExtractGenericArgInteger(exp, nullptr);
+ CheckExpr(exp);
}
+ return ExtractGenericArgInteger(exp, nullptr);
}
+}
- Type* SemanticsVisitor::InstantiateGenericType(
- DeclRef<GenericDecl> genericDeclRef,
- List<Expr*> const& args)
+Type* SemanticsVisitor::InstantiateGenericType(
+ DeclRef<GenericDecl> genericDeclRef,
+ List<Expr*> const& args)
+{
+ List<Val*> evaledArgs;
+
+ for (auto argExpr : args)
{
- List<Val*> evaledArgs;
+ evaledArgs.add(ExtractGenericArgVal(argExpr));
+ }
- for (auto argExpr : args)
- {
- evaledArgs.add(ExtractGenericArgVal(argExpr));
- }
+ DeclRef<Decl> innerDeclRef =
+ m_astBuilder->getGenericAppDeclRef(genericDeclRef, evaledArgs.getArrayView());
+ return DeclRefType::create(m_astBuilder, innerDeclRef);
+}
- DeclRef<Decl> innerDeclRef = m_astBuilder->getGenericAppDeclRef(genericDeclRef, evaledArgs.getArrayView());
- return DeclRefType::create(m_astBuilder, innerDeclRef);
+bool isManagedType(Type* type)
+{
+ if (auto declRefValueType = as<DeclRefType>(type))
+ {
+ if (as<ClassDecl>(declRefValueType->getDeclRef().getDecl()))
+ return true;
+ if (as<InterfaceDecl>(declRefValueType->getDeclRef().getDecl()))
+ return true;
}
+ return false;
+}
- bool isManagedType(Type* type)
+bool SemanticsVisitor::CoerceToProperTypeImpl(
+ TypeExp const& typeExp,
+ Type** outProperType,
+ DiagnosticSink* diagSink)
+{
+ Type* result = nullptr;
+ Type* type = typeExp.type;
+ auto originalExpr = typeExp.exp;
+ auto expr = originalExpr;
+ if (!type && expr)
{
- if (auto declRefValueType = as<DeclRefType>(type))
+ expr = maybeResolveOverloadedExpr(expr, LookupMask::type, diagSink);
+
+ if (auto typeType = as<TypeType>(expr->type))
{
- if (as<ClassDecl>(declRefValueType->getDeclRef().getDecl()))
- return true;
- if (as<InterfaceDecl>(declRefValueType->getDeclRef().getDecl()))
- return true;
+ type = typeType->getType();
}
- return false;
}
- bool SemanticsVisitor::CoerceToProperTypeImpl(
- TypeExp const& typeExp,
- Type** outProperType,
- DiagnosticSink* diagSink)
+ if (!type)
{
- Type* result = nullptr;
- Type* type = typeExp.type;
- auto originalExpr = typeExp.exp;
- auto expr = originalExpr;
- if(!type && expr)
+ // Only output diagnostic if we have a sink.
+ if (diagSink)
{
- expr = maybeResolveOverloadedExpr(expr, LookupMask::type, diagSink);
-
- if(auto typeType = as<TypeType>(expr->type))
+ // This function *can* be called with typeExp with both exp and type = nullptr.
+ // Previous behavior didn't output a diagnostic if originalExpr was null, so this keeps
+ // that behavior.
+ //
+ // Additional we check for ErrorType on expr, because if it's set a diagnostic has
+ // already been output via previous code or via maybeResolveOverloadedExpr.
+ if (originalExpr && (expr == nullptr || as<ErrorType>(expr->type) == nullptr))
{
- type = typeType->getType();
+ // The diagnostic for expectedAType wants to say what it 'got'.
+ // The solution given here, currently is to just use the node name.
+ // How useful that might be could depend, and perhaps some other mechanism
+ // that catagorized 'what' the wrong thing was is. For now this seems sufficient.
+ //
+ // Note that use originalExpr (not expr) because we want original expr for
+ // diagnostic.
+
+ // Get the AST node type info, so we can output a 'got' name
+ auto info = ASTClassInfo::getInfo(originalExpr->astNodeType);
+ diagSink->diagnose(originalExpr, Diagnostics::expectedAType, info->m_name);
}
}
- if (!type)
+ if (outProperType)
{
- // Only output diagnostic if we have a sink.
- if (diagSink)
- {
- // This function *can* be called with typeExp with both exp and type = nullptr.
- // Previous behavior didn't output a diagnostic if originalExpr was null, so this keeps that behavior.
- //
- // Additional we check for ErrorType on expr, because if it's set a diagnostic has already been output via
- // previous code or via maybeResolveOverloadedExpr.
- if (originalExpr && (expr == nullptr || as<ErrorType>(expr->type) == nullptr))
- {
- // The diagnostic for expectedAType wants to say what it 'got'.
- // The solution given here, currently is to just use the node name.
- // How useful that might be could depend, and perhaps some other mechanism
- // that catagorized 'what' the wrong thing was is. For now this seems sufficient.
- //
- // Note that use originalExpr (not expr) because we want original expr for diagnostic.
-
- // Get the AST node type info, so we can output a 'got' name
- auto info = ASTClassInfo::getInfo(originalExpr->astNodeType);
- diagSink->diagnose(originalExpr, Diagnostics::expectedAType, info->m_name);
- }
- }
-
- if (outProperType)
- {
- *outProperType = nullptr;
- }
- return false;
+ *outProperType = nullptr;
}
+ return false;
+ }
- if (auto genericDeclRefType = as<GenericDeclRefType>(type))
- {
- // We are using a reference to a generic declaration as a concrete
- // type. This means we should substitute in any default parameter values
- // if they are available.
- //
- // TODO(tfoley): A more expressive type system would substitute in
- // "fresh" variables and then solve for their values...
- //
+ if (auto genericDeclRefType = as<GenericDeclRefType>(type))
+ {
+ // We are using a reference to a generic declaration as a concrete
+ // type. This means we should substitute in any default parameter values
+ // if they are available.
+ //
+ // TODO(tfoley): A more expressive type system would substitute in
+ // "fresh" variables and then solve for their values...
+ //
- auto genericDeclRef = genericDeclRefType->getDeclRef();
- ensureDecl(genericDeclRef, DeclCheckState::CanSpecializeGeneric);
- List<Val*> args;
- List<Val*> witnessArgs;
- for (Decl* member : genericDeclRef.getDecl()->members)
+ auto genericDeclRef = genericDeclRefType->getDeclRef();
+ ensureDecl(genericDeclRef, DeclCheckState::CanSpecializeGeneric);
+ List<Val*> args;
+ List<Val*> witnessArgs;
+ for (Decl* member : genericDeclRef.getDecl()->members)
+ {
+ if (auto typeParam = as<GenericTypeParamDecl>(member))
{
- if (auto typeParam = as<GenericTypeParamDecl>(member))
- {
- if (!typeParam->initType.exp)
- {
- if (diagSink)
- {
- diagSink->diagnose(typeExp.exp, Diagnostics::genericTypeNeedsArgs, typeExp);
- *outProperType = m_astBuilder->getErrorType();
- }
- return false;
- }
-
- // TODO: this is one place where syntax should get cloned!
- if (outProperType)
- args.add(ExtractGenericArgVal(typeParam->initType.exp));
- }
- else if (auto valParam = as<GenericValueParamDecl>(member))
+ if (!typeParam->initType.exp)
{
- if (!valParam->initExpr)
+ if (diagSink)
{
- if (diagSink)
- {
- diagSink->diagnose(typeExp.exp, Diagnostics::unimplemented, "can't fill in default for generic type parameter");
- *outProperType = m_astBuilder->getErrorType();
- }
- return false;
+ diagSink->diagnose(typeExp.exp, Diagnostics::genericTypeNeedsArgs, typeExp);
+ *outProperType = m_astBuilder->getErrorType();
}
- // TODO: this is one place where syntax should get cloned!
- if (outProperType)
- args.add(ExtractGenericArgVal(valParam->initExpr));
+ return false;
}
- else if (auto constraintParam = as<GenericTypeConstraintDecl>(member))
+
+ // TODO: this is one place where syntax should get cloned!
+ if (outProperType)
+ args.add(ExtractGenericArgVal(typeParam->initType.exp));
+ }
+ else if (auto valParam = as<GenericValueParamDecl>(member))
+ {
+ if (!valParam->initExpr)
{
- auto genericParam = as<DeclRefType>(constraintParam->sub.type)->getDeclRef();
- if (!genericParam)
- return false;
- auto genericTypeParamDecl = as<GenericTypeParamDecl>(genericParam.getDecl());
- if (!genericTypeParamDecl)
- return false;
- auto defaultType = CheckProperType(genericTypeParamDecl->initType);
- if (!defaultType)
- return false;
- auto witness = tryGetSubtypeWitness(defaultType, CheckProperType(constraintParam->sup));
- if (!witness)
+ if (diagSink)
{
- // diagnose
- getSink()->diagnose(
- genericTypeParamDecl->initType.exp,
- Diagnostics::typeArgumentDoesNotConformToInterface,
- defaultType,
- constraintParam->sup);
- return false;
+ diagSink->diagnose(
+ typeExp.exp,
+ Diagnostics::unimplemented,
+ "can't fill in default for generic type parameter");
+ *outProperType = m_astBuilder->getErrorType();
}
- witnessArgs.add(witness);
+ return false;
}
- else
+ // TODO: this is one place where syntax should get cloned!
+ if (outProperType)
+ args.add(ExtractGenericArgVal(valParam->initExpr));
+ }
+ else if (auto constraintParam = as<GenericTypeConstraintDecl>(member))
+ {
+ auto genericParam = as<DeclRefType>(constraintParam->sub.type)->getDeclRef();
+ if (!genericParam)
+ return false;
+ auto genericTypeParamDecl = as<GenericTypeParamDecl>(genericParam.getDecl());
+ if (!genericTypeParamDecl)
+ return false;
+ auto defaultType = CheckProperType(genericTypeParamDecl->initType);
+ if (!defaultType)
+ return false;
+ auto witness =
+ tryGetSubtypeWitness(defaultType, CheckProperType(constraintParam->sup));
+ if (!witness)
{
- // ignore non-parameter members
+ // diagnose
+ getSink()->diagnose(
+ genericTypeParamDecl->initType.exp,
+ Diagnostics::typeArgumentDoesNotConformToInterface,
+ defaultType,
+ constraintParam->sup);
+ return false;
}
+ witnessArgs.add(witness);
}
- // Combine args and witnessArgs
- args.addRange(witnessArgs);
-
- result = DeclRefType::create(getASTBuilder(),
- getASTBuilder()->getGenericAppDeclRef(genericDeclRef, args.getArrayView()));
- }
-
- // default case: we expect this to already be a proper type
- if (!result)
- {
- result = type;
- }
-
- // Check for invalid types.
- // We don't allow pointers to managed types.
- if (auto ptrType = as<PtrType>(result))
- {
- if (isManagedType(ptrType->getValueType()))
+ else
{
- getSink()->diagnose(typeExp.exp, Diagnostics::cannotDefinePtrTypeToManagedResource);
+ // ignore non-parameter members
}
}
+ // Combine args and witnessArgs
+ args.addRange(witnessArgs);
- *outProperType = result;
- return true;
+ result = DeclRefType::create(
+ getASTBuilder(),
+ getASTBuilder()->getGenericAppDeclRef(genericDeclRef, args.getArrayView()));
}
- TypeExp SemanticsVisitor::CoerceToProperType(TypeExp const& typeExp)
+ // default case: we expect this to already be a proper type
+ if (!result)
{
- TypeExp result = typeExp;
- CoerceToProperTypeImpl(typeExp, &result.type, getSink());
- return result;
+ result = type;
}
- TypeExp SemanticsVisitor::tryCoerceToProperType(TypeExp const& typeExp)
+ // Check for invalid types.
+ // We don't allow pointers to managed types.
+ if (auto ptrType = as<PtrType>(result))
{
- TypeExp result = typeExp;
- if(!CoerceToProperTypeImpl(typeExp, &result.type, nullptr))
- return TypeExp();
- return result;
+ if (isManagedType(ptrType->getValueType()))
+ {
+ getSink()->diagnose(typeExp.exp, Diagnostics::cannotDefinePtrTypeToManagedResource);
+ }
}
- TypeExp SemanticsVisitor::CheckProperType(TypeExp typeExp)
- {
- return CoerceToProperType(TranslateTypeNode(typeExp));
- }
+ *outProperType = result;
+ return true;
+}
- TypeExp SemanticsVisitor::CoerceToUsableType(TypeExp const& typeExp, Decl* decl)
- {
- TypeExp result = CoerceToProperType(typeExp);
- Type* type = result.type;
- if (auto basicType = as<BasicExpressionType>(type))
- {
- // TODO: `void` shouldn't be a basic type, to make this easier to avoid
- if (basicType->getBaseType() == BaseType::Void)
- {
- // TODO(tfoley): pick the right diagnostic message
- getSink()->diagnose(result.exp, Diagnostics::invalidTypeVoid);
- result.type = m_astBuilder->getErrorType();
- return result;
- }
- }
+TypeExp SemanticsVisitor::CoerceToProperType(TypeExp const& typeExp)
+{
+ TypeExp result = typeExp;
+ CoerceToProperTypeImpl(typeExp, &result.type, getSink());
+ return result;
+}
+
+TypeExp SemanticsVisitor::tryCoerceToProperType(TypeExp const& typeExp)
+{
+ TypeExp result = typeExp;
+ if (!CoerceToProperTypeImpl(typeExp, &result.type, nullptr))
+ return TypeExp();
+ return result;
+}
- // A type pack is not a usable type other than for defining parameters.
- if (!as<ParamDecl>(decl) && isTypePack(type))
+TypeExp SemanticsVisitor::CheckProperType(TypeExp typeExp)
+{
+ return CoerceToProperType(TranslateTypeNode(typeExp));
+}
+
+TypeExp SemanticsVisitor::CoerceToUsableType(TypeExp const& typeExp, Decl* decl)
+{
+ TypeExp result = CoerceToProperType(typeExp);
+ Type* type = result.type;
+ if (auto basicType = as<BasicExpressionType>(type))
+ {
+ // TODO: `void` shouldn't be a basic type, to make this easier to avoid
+ if (basicType->getBaseType() == BaseType::Void)
{
- getSink()->diagnose(typeExp.exp, Diagnostics::improperUseOfType, typeExp.type);
+ // TODO(tfoley): pick the right diagnostic message
+ getSink()->diagnose(result.exp, Diagnostics::invalidTypeVoid);
result.type = m_astBuilder->getErrorType();
return result;
}
- return result;
}
- TypeExp SemanticsVisitor::CheckUsableType(TypeExp typeExp, Decl* decl)
+ // A type pack is not a usable type other than for defining parameters.
+ if (!as<ParamDecl>(decl) && isTypePack(type))
{
- return CoerceToUsableType(TranslateTypeNode(typeExp), decl);
+ getSink()->diagnose(typeExp.exp, Diagnostics::improperUseOfType, typeExp.type);
+ result.type = m_astBuilder->getErrorType();
+ return result;
}
+ return result;
+}
- bool SemanticsVisitor::ValuesAreEqual(
- IntVal* left,
- IntVal* right)
- {
- if(left == right) return true;
+TypeExp SemanticsVisitor::CheckUsableType(TypeExp typeExp, Decl* decl)
+{
+ return CoerceToUsableType(TranslateTypeNode(typeExp), decl);
+}
+
+bool SemanticsVisitor::ValuesAreEqual(IntVal* left, IntVal* right)
+{
+ if (left == right)
+ return true;
- if(auto leftConst = as<ConstantIntVal>(left))
+ if (auto leftConst = as<ConstantIntVal>(left))
+ {
+ if (auto rightConst = as<ConstantIntVal>(right))
{
- if(auto rightConst = as<ConstantIntVal>(right))
- {
- return leftConst->getValue() == rightConst->getValue();
- }
+ return leftConst->getValue() == rightConst->getValue();
}
+ }
- if(auto leftVar = as<GenericParamIntVal>(left))
+ if (auto leftVar = as<GenericParamIntVal>(left))
+ {
+ if (auto rightVar = as<GenericParamIntVal>(right))
{
- if(auto rightVar = as<GenericParamIntVal>(right))
- {
- return leftVar->getDeclRef().equals(rightVar->getDeclRef());
- }
- else if (const auto rightPoly = as<PolynomialIntVal>(right))
- {
- return right->equals(leftVar);
- }
+ return leftVar->getDeclRef().equals(rightVar->getDeclRef());
}
- if (auto leftVar = as<PolynomialIntVal>(left))
+ else if (const auto rightPoly = as<PolynomialIntVal>(right))
{
- return leftVar->equals(right);
+ return right->equals(leftVar);
}
- return false;
}
-
- VectorExpressionType* SemanticsVisitor::createVectorType(
- Type* elementType,
- IntVal* elementCount)
+ if (auto leftVar = as<PolynomialIntVal>(left))
{
- return m_astBuilder->getVectorType(elementType, elementCount);
+ return leftVar->equals(right);
}
+ return false;
+}
+
+VectorExpressionType* SemanticsVisitor::createVectorType(Type* elementType, IntVal* elementCount)
+{
+ return m_astBuilder->getVectorType(elementType, elementCount);
+}
- Expr* SemanticsExprVisitor::visitSharedTypeExpr(SharedTypeExpr* expr)
+Expr* SemanticsExprVisitor::visitSharedTypeExpr(SharedTypeExpr* expr)
+{
+ if (!expr->type.Ptr())
{
- if (!expr->type.Ptr())
- {
- expr->base = CheckProperType(expr->base);
- expr->type = expr->base.exp->type;
- }
- return expr;
+ expr->base = CheckProperType(expr->base);
+ expr->type = expr->base.exp->type;
}
-
+ return expr;
}
+
+} // namespace Slang