internal static bool HasImplicitConversionTo(this TypeSymbol left, TypeSymbol right)
{
if (left.Equals(right))
return true;
// TODO: Need to be able to implicitly cast classes to base class and interfaces?
if (left.IsUserDefined() || right.IsUserDefined())
return false;
if (left.Kind == SymbolKind.IntrinsicObjectType || right.Kind == SymbolKind.IntrinsicObjectType)
{
if (left.Kind == SymbolKind.IntrinsicObjectType && right.Kind == SymbolKind.IntrinsicObjectType)
{
var leftIntrinsicType = (IntrinsicObjectTypeSymbol) left;
var rightIntrinsicType = (IntrinsicObjectTypeSymbol) right;
if (leftIntrinsicType.PredefinedType == PredefinedObjectType.Sampler)
{
switch (rightIntrinsicType.PredefinedType)
{
case PredefinedObjectType.Sampler1D:
case PredefinedObjectType.Sampler2D:
case PredefinedObjectType.Sampler3D:
case PredefinedObjectType.SamplerCube:
case PredefinedObjectType.SamplerState:
return true;
}
}
}
return false;
}
switch (left.Kind)
{
case SymbolKind.Array:
switch (right.Kind)
{
case SymbolKind.Array:
{
var leftArray = (ArraySymbol) left;
var rightArray = (ArraySymbol) right;
return leftArray.ValueType.HasImplicitConversionTo(rightArray.ValueType);
}
default:
return false;
}
}
if (left.Kind == SymbolKind.IntrinsicScalarType || right.Kind == SymbolKind.IntrinsicScalarType)
return true;
switch (left.Kind)
{
case SymbolKind.IntrinsicVectorType:
switch (right.Kind)
{
case SymbolKind.IntrinsicScalarType:
return true;
case SymbolKind.IntrinsicVectorType:
return ((IntrinsicVectorTypeSymbol) left).NumComponents == 1 || ((IntrinsicVectorTypeSymbol) left).NumComponents >= ((IntrinsicVectorTypeSymbol) right).NumComponents;
case SymbolKind.IntrinsicMatrixType:
{
var leftVector = (IntrinsicVectorTypeSymbol) left;
var rightMatrix = (IntrinsicMatrixTypeSymbol) right;
return (leftVector.NumComponents >= rightMatrix.Cols && rightMatrix.Rows == 1)
|| (leftVector.NumComponents >= rightMatrix.Rows && rightMatrix.Cols == 1);
}
case SymbolKind.Array:
{
var leftVector = (IntrinsicVectorTypeSymbol) left;
var rightArray = (ArraySymbol) right;
if (!leftVector.HasImplicitConversionTo(rightArray.ValueType))
return false;
if (rightArray.Dimension == null)
return true;
return leftVector.NumComponents >= rightArray.Dimension.Value;
}
}
break;
case SymbolKind.IntrinsicMatrixType:
switch (right.Kind)
{
case SymbolKind.IntrinsicScalarType:
return true;
case SymbolKind.IntrinsicVectorType:
{
var leftMatrix = (IntrinsicMatrixTypeSymbol) left;
var rightVector = (IntrinsicVectorTypeSymbol) right;
return (leftMatrix.Rows >= rightVector.NumComponents && leftMatrix.Cols == 1)
|| (leftMatrix.Cols >= rightVector.NumComponents && leftMatrix.Rows == 1);
}
case SymbolKind.IntrinsicMatrixType:
{
var leftMatrix = (IntrinsicMatrixTypeSymbol) left;
var rightMatrix = (IntrinsicMatrixTypeSymbol) right;
return leftMatrix.Rows >= rightMatrix.Rows && leftMatrix.Cols >= rightMatrix.Cols;
}
}
break;
}
if (left.GetNumElements() >= right.GetNumElements())
return true;
return false;
}