...
This commit is contained in:
@@ -249,7 +249,7 @@ public class TypeChecker
|
||||
NodeExpressionFuncCall expression => CheckExpressionFuncCall(expression, expectedType),
|
||||
NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression, expectedType),
|
||||
NodeExpressionStructLiteral expression => CheckExpressionStructLiteral(expression, expectedType),
|
||||
NodeExpressionNewNamedType expression => CheckExpressionNewNamedType(expression, expectedType),
|
||||
NodeExpressionEnumLiteral expression => CheckExpressionEnumLiteral(expression, expectedType),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||
};
|
||||
}
|
||||
@@ -526,7 +526,35 @@ public class TypeChecker
|
||||
|
||||
private TypedNodeExpressionStructLiteral CheckExpressionStructLiteral(NodeExpressionStructLiteral expression, NubType? expectedType)
|
||||
{
|
||||
if (expectedType is NubTypeStruct structType)
|
||||
if (expression.Type != null)
|
||||
{
|
||||
var type = ResolveType(expression.Type);
|
||||
if (type is not NubTypeStruct structType)
|
||||
throw BasicError("Type of struct literal is not a struct", expression);
|
||||
|
||||
if (!moduleGraph.TryResolveType(structType.Module, structType.Name, structType.Module == currentModule, out var info))
|
||||
throw BasicError($"Type '{structType}' struct literal not found", expression);
|
||||
|
||||
if (info is not Module.TypeInfoStruct structInfo)
|
||||
throw BasicError($"Type '{structType}' is not a struct", expression.Type);
|
||||
|
||||
var initializers = new List<TypedNodeExpressionStructLiteral.Initializer>();
|
||||
foreach (var initializer in expression.Initializers)
|
||||
{
|
||||
var field = structInfo.Fields.FirstOrDefault(x => x.Name == initializer.Name.Ident);
|
||||
if (field == null)
|
||||
throw BasicError($"Field '{initializer.Name.Ident}' does not exist on struct '{structType.Module}::{structType.Name}'", initializer.Name);
|
||||
|
||||
var value = CheckExpression(initializer.Value, field.Type);
|
||||
if (!value.Type.IsAssignableTo(field.Type))
|
||||
throw BasicError($"Type of assignment ({value.Type}) does not match expected type of field '{field.Name}' ({field.Type})", initializer.Name);
|
||||
|
||||
initializers.Add(new TypedNodeExpressionStructLiteral.Initializer(initializer.Tokens, initializer.Name, value));
|
||||
}
|
||||
|
||||
return new TypedNodeExpressionStructLiteral(expression.Tokens, structType, initializers);
|
||||
}
|
||||
else if (expectedType is NubTypeStruct structType)
|
||||
{
|
||||
if (!moduleGraph.TryResolveType(structType.Module, structType.Name, structType.Module == currentModule, out var info))
|
||||
throw BasicError($"Type '{structType}' struct literal not found", expression);
|
||||
@@ -583,36 +611,31 @@ public class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
private TypedNodeExpressionNewNamedType CheckExpressionNewNamedType(NodeExpressionNewNamedType expression, NubType? expectedType)
|
||||
private TypedNodeExpressionEnumLiteral CheckExpressionEnumLiteral(NodeExpressionEnumLiteral expression, NubType? expectedType)
|
||||
{
|
||||
var type = ResolveType(expression.Type);
|
||||
switch (type)
|
||||
{
|
||||
case NubTypeStruct structType:
|
||||
{
|
||||
var value = CheckExpression(expression.Value, structType);
|
||||
return new TypedNodeExpressionNewNamedType(expression.Tokens, structType, value);
|
||||
}
|
||||
case NubTypeEnumVariant enumVariantType:
|
||||
{
|
||||
if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, enumVariantType.EnumType.Module == currentModule, out var info))
|
||||
throw BasicError($"Type '{enumVariantType.EnumType}' not found", expression.Type);
|
||||
if (type is not NubTypeEnumVariant variantType)
|
||||
throw BasicError("Expected enum variant type", expression.Type);
|
||||
|
||||
if (info is not Module.TypeInfoEnum enumInfo)
|
||||
throw BasicError($"Type '{enumVariantType.EnumType}' is not an enum", expression.Type);
|
||||
if (!moduleGraph.TryResolveType(variantType.EnumType.Module, variantType.EnumType.Name, variantType.EnumType.Module == currentModule, out var info))
|
||||
throw BasicError($"Type '{variantType.EnumType}' not found", expression.Type);
|
||||
|
||||
var variant = enumInfo.Variants.FirstOrDefault(x => x.Name == enumVariantType.Variant);
|
||||
if (variant == null)
|
||||
throw BasicError($"Enum type '{enumVariantType.EnumType}' does not have a variant named '{enumVariantType.Variant}'", expression.Type);
|
||||
if (info is not Module.TypeInfoEnum enumInfo)
|
||||
throw BasicError($"Type '{variantType.EnumType}' is not an enum", expression.Type);
|
||||
|
||||
var value = CheckExpression(expression.Value, variant.Type);
|
||||
return new TypedNodeExpressionNewNamedType(expression.Tokens, enumVariantType, value);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw BasicError($"'{type}' is not a valid type for the new operator", expression);
|
||||
}
|
||||
}
|
||||
var variant = enumInfo.Variants.FirstOrDefault(x => x.Name == variantType.Variant);
|
||||
if (variant == null)
|
||||
throw BasicError($"Enum '{variantType.EnumType}' does not have a variant named '{variantType.Variant}'", expression.Type);
|
||||
|
||||
if (expression.Value == null && variant.Type is not null)
|
||||
throw BasicError($"Enum variant '{variantType.EnumType}' expects a value of type '{variant.Type}'", expression.Type);
|
||||
|
||||
if (expression.Value != null && variant.Type is null)
|
||||
throw BasicError($"Enum variant '{variantType.EnumType}' does not expect any data", expression.Value);
|
||||
|
||||
var value = expression.Value == null ? null : CheckExpression(expression.Value, variant.Type);
|
||||
|
||||
return new TypedNodeExpressionEnumLiteral(expression.Tokens, type, value);
|
||||
}
|
||||
|
||||
private NubType ResolveType(NodeType node)
|
||||
@@ -892,9 +915,9 @@ public class TypedNodeExpressionStructLiteral(List<Token> tokens, NubType type,
|
||||
}
|
||||
}
|
||||
|
||||
public class TypedNodeExpressionNewNamedType(List<Token> tokens, NubType type, TypedNodeExpression value) : TypedNodeExpression(tokens, type)
|
||||
public class TypedNodeExpressionEnumLiteral(List<Token> tokens, NubType type, TypedNodeExpression? value) : TypedNodeExpression(tokens, type)
|
||||
{
|
||||
public TypedNodeExpression Value { get; } = value;
|
||||
public TypedNodeExpression? Value { get; } = value;
|
||||
}
|
||||
|
||||
public class TypedNodeExpressionStructMemberAccess(List<Token> tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type)
|
||||
|
||||
Reference in New Issue
Block a user