...
This commit is contained in:
@@ -122,10 +122,14 @@ public record VariableIdentifierNode(List<Token> Tokens, NubType Type, string Na
|
||||
|
||||
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type);
|
||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, List<ExpressionNode> Values) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConstArrayInitializerNode(List<Token> Tokens, NubType Type, List<ExpressionNode> Values) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConstArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
||||
@@ -140,14 +144,14 @@ public record ConvertIntNode(List<Token> Tokens, ExpressionNode Value, int Start
|
||||
|
||||
public record ConvertFloatNode(List<Token> Tokens, ExpressionNode Value, int StartWidth, int TargetWidth) : RValueExpressionNode(Tokens, new NubFloatType(TargetWidth));
|
||||
|
||||
public record ConvertStringToCStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubCStringType());
|
||||
|
||||
public record ConvertCStringToStringNode(List<Token> Tokens, ExpressionNode Value) : RValueExpressionNode(Tokens, new NubStringType());
|
||||
|
||||
public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record FloatToIntBuiltinNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConstArrayToSliceNode(List<Token> Tokens, NubType Type, ExpressionNode Array) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record EnumReferenceIntermediateNode(List<Token> Tokens, string Module, string Name) : IntermediateExpression(Tokens);
|
||||
|
||||
#endregion
|
||||
@@ -272,8 +272,8 @@ public sealed class TypeChecker
|
||||
default:
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error($"For statement not supported for type {target.Type}")
|
||||
.At(forSyntax)
|
||||
.Error($"Cannot iterate over type {target.Type} which does not have size information")
|
||||
.At(forSyntax.Target)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
@@ -292,7 +292,7 @@ public sealed class TypeChecker
|
||||
|
||||
private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||
{
|
||||
return node switch
|
||||
var result = node switch
|
||||
{
|
||||
AddressOfSyntax expression => CheckAddressOf(expression, expectedType),
|
||||
ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression, expectedType),
|
||||
@@ -314,6 +314,40 @@ public sealed class TypeChecker
|
||||
FloatToIntBuiltinSyntax expression => CheckFloatToInt(expression, expectedType),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||
};
|
||||
|
||||
switch (expectedType)
|
||||
{
|
||||
// note(nub31): Implicit conversion of const array to unsized array
|
||||
case NubArrayType when result.Type is NubConstArrayType constArrayType:
|
||||
{
|
||||
return result with { Type = new NubArrayType(constArrayType.ElementType) };
|
||||
}
|
||||
// note(nub31): Implicit conversion of const array to slice
|
||||
case NubSliceType when result.Type is NubConstArrayType constArrayType:
|
||||
{
|
||||
return new ConstArrayToSliceNode(result.Tokens, new NubSliceType(constArrayType.ElementType), result);
|
||||
}
|
||||
// note(nub31): Implicit conversion of int to larger int
|
||||
case NubIntType expectedIntType when result.Type is NubIntType intType && expectedIntType.Width > intType.Width:
|
||||
{
|
||||
return new ConvertIntNode(result.Tokens, result, intType.Width, expectedIntType.Width, intType.Signed, expectedIntType.Signed);
|
||||
}
|
||||
// note(nub31): Implicit conversion of f32 to f64
|
||||
case NubFloatType expectedFloatType when result.Type is NubFloatType floatType && expectedFloatType.Width > floatType.Width:
|
||||
{
|
||||
return new ConvertFloatNode(result.Tokens, result, floatType.Width, expectedFloatType.Width);
|
||||
}
|
||||
// note(nub31): Implicit conversion of cstring to string
|
||||
case NubStringType when result.Type is NubCStringType:
|
||||
{
|
||||
return new ConvertCStringToStringNode(result.Tokens, result);
|
||||
}
|
||||
// note(nub31): No implicit conversion was possible or the result value was already the correct type
|
||||
default:
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo(nub31): Infer int type instead of explicit type syntax
|
||||
@@ -368,18 +402,61 @@ public sealed class TypeChecker
|
||||
return target.Type switch
|
||||
{
|
||||
NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index),
|
||||
NubConstArrayType constArrayType => new ConstArrayIndexAccessNode(expression.Tokens, constArrayType.ElementType, target, index),
|
||||
NubSliceType sliceType => new SliceIndexAccessNode(expression.Tokens, sliceType.ElementType, target, index),
|
||||
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
|
||||
};
|
||||
}
|
||||
|
||||
// todo(nub31): Allow type inference instead of specifying type in syntax. Something like just []
|
||||
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression, NubType? _)
|
||||
private ExpressionNode CheckArrayInitializer(ArrayInitializerSyntax expression, NubType? expectedType)
|
||||
{
|
||||
var elementType = ResolveType(expression.ElementType);
|
||||
var capacity = CheckExpression(expression.Capacity);
|
||||
var type = new NubArrayType(elementType);
|
||||
return new ArrayInitializerNode(expression.Tokens, type, capacity, elementType);
|
||||
var elementType = expectedType switch
|
||||
{
|
||||
NubArrayType arrayType => arrayType.ElementType,
|
||||
NubConstArrayType constArrayType => constArrayType.ElementType,
|
||||
NubSliceType sliceType => sliceType.ElementType,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (elementType == null)
|
||||
{
|
||||
var firstValue = expression.Values.FirstOrDefault();
|
||||
if (firstValue != null)
|
||||
{
|
||||
elementType = CheckExpression(firstValue).Type;
|
||||
}
|
||||
}
|
||||
|
||||
if (elementType == null)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Unable to infer type of array initializer")
|
||||
.At(expression)
|
||||
.WithHelp("Provide a type for a variable assignment")
|
||||
.Build());
|
||||
}
|
||||
|
||||
var values = new List<ExpressionNode>();
|
||||
foreach (var valueExpression in expression.Values)
|
||||
{
|
||||
var value = CheckExpression(valueExpression, elementType);
|
||||
if (value.Type != elementType)
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
.Error("Value in array initializer is not the same as the array type")
|
||||
.At(valueExpression)
|
||||
.Build());
|
||||
}
|
||||
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
return expectedType switch
|
||||
{
|
||||
NubArrayType => new ArrayInitializerNode(expression.Tokens, new NubArrayType(elementType), values),
|
||||
NubConstArrayType constArrayType => new ConstArrayInitializerNode(expression.Tokens, constArrayType, values),
|
||||
_ => new ConstArrayInitializerNode(expression.Tokens, new NubConstArrayType(elementType, expression.Values.Count), values)
|
||||
};
|
||||
}
|
||||
|
||||
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression, NubType? expectedType)
|
||||
|
||||
Reference in New Issue
Block a user