...
This commit is contained in:
@@ -581,9 +581,25 @@ public class SizeNode(List<Token> tokens, NubType targetType) : RValue(tokens, n
|
||||
}
|
||||
}
|
||||
|
||||
public class CastNode(List<Token> tokens, NubType type, ExpressionNode value) : RValue(tokens, type)
|
||||
public class CastNode(List<Token> tokens, NubType type, ExpressionNode value, CastNode.Conversion conversionType) : RValue(tokens, type)
|
||||
{
|
||||
public enum Conversion
|
||||
{
|
||||
IntToInt,
|
||||
FloatToFloat,
|
||||
IntToFloat,
|
||||
FloatToInt,
|
||||
|
||||
PointerToPointer,
|
||||
PointerToUInt64,
|
||||
UInt64ToPointer,
|
||||
|
||||
ConstArrayToArray,
|
||||
ConstArrayToSlice,
|
||||
}
|
||||
|
||||
public ExpressionNode Value { get; } = value;
|
||||
public Conversion ConversionType { get; } = conversionType;
|
||||
|
||||
public override IEnumerable<Node> Children()
|
||||
{
|
||||
|
||||
@@ -322,9 +322,9 @@ public sealed class TypeChecker
|
||||
return result;
|
||||
}
|
||||
|
||||
if (IsCastAllowed(result.Type, expectedType))
|
||||
if (IsCastAllowed(result.Type, expectedType, out var conversion))
|
||||
{
|
||||
return new CastNode(result.Tokens, expectedType, result);
|
||||
return new CastNode(result.Tokens, expectedType, result, conversion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,26 +354,39 @@ public sealed class TypeChecker
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!IsCastAllowed(value.Type, expectedType, false))
|
||||
if (!IsCastAllowed(value.Type, expectedType, out var conversion, false))
|
||||
{
|
||||
throw new CompileException(Diagnostic
|
||||
.Error($"Cannot cast from {value.Type} to {expectedType}")
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new CastNode(expression.Tokens, expectedType, value);
|
||||
return new CastNode(expression.Tokens, expectedType, value, conversion);
|
||||
}
|
||||
|
||||
private static bool IsCastAllowed(NubType from, NubType to, bool strict = true)
|
||||
private static bool IsCastAllowed(NubType from, NubType to, out CastNode.Conversion conversion, bool strict = true)
|
||||
{
|
||||
// note(nub31): Implicit casts
|
||||
switch (from)
|
||||
{
|
||||
case NubIntType fromInt when to is NubIntType toInt && fromInt.Width < toInt.Width:
|
||||
{
|
||||
conversion = CastNode.Conversion.IntToInt;
|
||||
return true;
|
||||
}
|
||||
case NubPointerType when to is NubPointerType { BaseType: NubVoidType }:
|
||||
{
|
||||
conversion = CastNode.Conversion.PointerToPointer;
|
||||
return true;
|
||||
}
|
||||
case NubConstArrayType constArrayType1 when to is NubArrayType arrayType && constArrayType1.ElementType == arrayType.ElementType:
|
||||
{
|
||||
conversion = CastNode.Conversion.ConstArrayToArray;
|
||||
return true;
|
||||
}
|
||||
case NubConstArrayType constArrayType3 when to is NubSliceType sliceType2 && constArrayType3.ElementType == sliceType2.ElementType:
|
||||
{
|
||||
conversion = CastNode.Conversion.ConstArrayToSlice;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -384,19 +397,44 @@ public sealed class TypeChecker
|
||||
switch (from)
|
||||
{
|
||||
case NubIntType when to is NubIntType:
|
||||
case NubIntType when to is NubFloatType:
|
||||
case NubFloatType when to is NubIntType:
|
||||
case NubFloatType when to is NubFloatType:
|
||||
case NubPointerType when to is NubPointerType:
|
||||
case NubPointerType when to is NubIntType:
|
||||
case NubIntType when to is NubPointerType:
|
||||
{
|
||||
conversion = CastNode.Conversion.IntToInt;
|
||||
return true;
|
||||
}
|
||||
case NubIntType when to is NubFloatType:
|
||||
{
|
||||
conversion = CastNode.Conversion.IntToFloat;
|
||||
return true;
|
||||
}
|
||||
case NubFloatType when to is NubIntType:
|
||||
{
|
||||
conversion = CastNode.Conversion.FloatToInt;
|
||||
return true;
|
||||
}
|
||||
case NubFloatType when to is NubFloatType:
|
||||
{
|
||||
conversion = CastNode.Conversion.FloatToFloat;
|
||||
return true;
|
||||
}
|
||||
case NubPointerType when to is NubPointerType:
|
||||
{
|
||||
conversion = CastNode.Conversion.PointerToPointer;
|
||||
return true;
|
||||
}
|
||||
case NubPointerType when to is NubIntType { Signed: false, Width: 64 }:
|
||||
{
|
||||
conversion = CastNode.Conversion.PointerToUInt64;
|
||||
return true;
|
||||
}
|
||||
case NubIntType { Signed: false, Width: 64 } when to is NubPointerType:
|
||||
{
|
||||
conversion = CastNode.Conversion.UInt64ToPointer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
conversion = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user