WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
4 changed files with 122 additions and 69 deletions
Showing only changes of commit 693b119781 - Show all commits

View File

@@ -489,7 +489,7 @@ public class Generator
TypedNodeExpressionIntLiteral expression => expression.Value.Value.ToString(), TypedNodeExpressionIntLiteral expression => expression.Value.Value.ToString(),
TypedNodeExpressionStringLiteral expression => EmitExpressionStringLiteral(expression), TypedNodeExpressionStringLiteral expression => EmitExpressionStringLiteral(expression),
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression), TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
TypedNodeExpressionNewNamedType expression => EmitNodeExpressionNewNamedType(expression), TypedNodeExpressionEnumLiteral expression => EmitExpressionEnumLiteral(expression),
TypedNodeExpressionStructMemberAccess expression => EmitExpressionMemberAccess(expression), TypedNodeExpressionStructMemberAccess expression => EmitExpressionMemberAccess(expression),
TypedNodeExpressionStringLength expression => EmitExpressionStringLength(expression), TypedNodeExpressionStringLength expression => EmitExpressionStringLength(expression),
TypedNodeExpressionStringPointer expression => EmitExpressionStringPointer(expression), TypedNodeExpressionStringPointer expression => EmitExpressionStringPointer(expression),
@@ -578,36 +578,35 @@ public class Generator
return name; return name;
} }
private string EmitNodeExpressionNewNamedType(TypedNodeExpressionNewNamedType expression) private string EmitExpressionEnumLiteral(TypedNodeExpressionEnumLiteral expression)
{
switch (expression.Type)
{
case NubTypeEnumVariant enumVariantType:
{ {
var name = TmpName(); var name = TmpName();
scopes.Peek().DeconstructableNames.Add((name, expression.Type)); scopes.Peek().DeconstructableNames.Add((name, expression.Type));
var enumVariantType = (NubTypeEnumVariant)expression.Type;
if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info)) if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info))
throw new UnreachableException(); throw new UnreachableException();
var enumInfo = (Module.TypeInfoEnum)info; var enumInfo = (Module.TypeInfoEnum)info;
var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == enumVariantType.Variant); var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == enumVariantType.Variant);
var value = EmitExpression(expression.Value); string? value = null;
if (expression.Value != null)
{
value = EmitExpression(expression.Value);
EmitCopyConstructor(value, expression.Value.Type); EmitCopyConstructor(value, expression.Value.Type);
}
writer.WriteLine($"{CType(expression.Type, name)} = ({CType(expression.Type)}){{ .tag = {tag}, .{enumVariantType.Variant} = {value} }};"); writer.Write($"{CType(expression.Type, name)} = ({CType(expression.Type)}){{ .tag = {tag}");
if (value != null)
writer.WriteLine($", .{enumVariantType.Variant} = {value} }};");
else
writer.WriteLine(" }};");
return name; return name;
} }
case NubTypeStruct structType:
{
return EmitExpression(expression.Value);
}
default:
throw new UnreachableException();
}
}
private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression) private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression)
{ {

View File

@@ -375,7 +375,7 @@ public class Parser
initializers.Add(new NodeExpressionStructLiteral.Initializer(TokensFrom(initializerStartIndex), fieldName, fieldValue)); initializers.Add(new NodeExpressionStructLiteral.Initializer(TokensFrom(initializerStartIndex), fieldName, fieldValue));
} }
expr = new NodeExpressionStructLiteral(TokensFrom(startIndex), initializers); expr = new NodeExpressionStructLiteral(TokensFrom(startIndex), null, initializers);
} }
else if (TryExpectSymbol(Symbol.Bang)) else if (TryExpectSymbol(Symbol.Bang))
{ {
@@ -408,8 +408,32 @@ public class Parser
else if (TryExpectKeyword(Keyword.New)) else if (TryExpectKeyword(Keyword.New))
{ {
var type = ParseType(); var type = ParseType();
if (TryExpectSymbol(Symbol.OpenParen))
{
var value = ParseExpression(); var value = ParseExpression();
return new NodeExpressionNewNamedType(TokensFrom(startIndex), type, value); ExpectSymbol(Symbol.CloseParen);
expr = new NodeExpressionEnumLiteral(TokensFrom(startIndex), type, value);
}
else if (TryExpectSymbol(Symbol.OpenCurly))
{
var initializers = new List<NodeExpressionStructLiteral.Initializer>();
while (!TryExpectSymbol(Symbol.CloseCurly))
{
var initializerStartIndex = startIndex;
var fieldName = ExpectIdent();
ExpectSymbol(Symbol.Equal);
var fieldValue = ParseExpression();
initializers.Add(new NodeExpressionStructLiteral.Initializer(TokensFrom(initializerStartIndex), fieldName, fieldValue));
}
expr = new NodeExpressionStructLiteral(TokensFrom(startIndex), null, initializers);
}
else
{
expr = new NodeExpressionEnumLiteral(TokensFrom(startIndex), type, null);
}
} }
else else
{ {
@@ -869,14 +893,9 @@ public class NodeExpressionBoolLiteral(List<Token> tokens, TokenBoolLiteral valu
public TokenBoolLiteral Value { get; } = value; public TokenBoolLiteral Value { get; } = value;
} }
public class NodeExpressionNewNamedType(List<Token> tokens, NodeType type, NodeExpression value) : NodeExpression(tokens) public class NodeExpressionStructLiteral(List<Token> tokens, NodeType? type, List<NodeExpressionStructLiteral.Initializer> initializers) : NodeExpression(tokens)
{
public NodeType Type { get; } = type;
public NodeExpression Value { get; } = value;
}
public class NodeExpressionStructLiteral(List<Token> tokens, List<NodeExpressionStructLiteral.Initializer> initializers) : NodeExpression(tokens)
{ {
public NodeType? Type { get; } = type;
public List<Initializer> Initializers { get; } = initializers; public List<Initializer> Initializers { get; } = initializers;
public class Initializer(List<Token> tokens, TokenIdent name, NodeExpression value) : Node(tokens) public class Initializer(List<Token> tokens, TokenIdent name, NodeExpression value) : Node(tokens)
@@ -886,6 +905,12 @@ public class NodeExpressionStructLiteral(List<Token> tokens, List<NodeExpression
} }
} }
public class NodeExpressionEnumLiteral(List<Token> tokens, NodeType type, NodeExpression? value) : NodeExpression(tokens)
{
public NodeType Type { get; } = type;
public NodeExpression? Value { get; } = value;
}
public class NodeExpressionMemberAccess(List<Token> tokens, NodeExpression target, TokenIdent name) : NodeExpression(tokens) public class NodeExpressionMemberAccess(List<Token> tokens, NodeExpression target, TokenIdent name) : NodeExpression(tokens)
{ {
public NodeExpression Target { get; } = target; public NodeExpression Target { get; } = target;

View File

@@ -249,7 +249,7 @@ public class TypeChecker
NodeExpressionFuncCall expression => CheckExpressionFuncCall(expression, expectedType), NodeExpressionFuncCall expression => CheckExpressionFuncCall(expression, expectedType),
NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression, expectedType), NodeExpressionStringLiteral expression => CheckExpressionStringLiteral(expression, expectedType),
NodeExpressionStructLiteral expression => CheckExpressionStructLiteral(expression, expectedType), NodeExpressionStructLiteral expression => CheckExpressionStructLiteral(expression, expectedType),
NodeExpressionNewNamedType expression => CheckExpressionNewNamedType(expression, expectedType), NodeExpressionEnumLiteral expression => CheckExpressionEnumLiteral(expression, expectedType),
_ => throw new ArgumentOutOfRangeException(nameof(node)) _ => throw new ArgumentOutOfRangeException(nameof(node))
}; };
} }
@@ -526,7 +526,35 @@ public class TypeChecker
private TypedNodeExpressionStructLiteral CheckExpressionStructLiteral(NodeExpressionStructLiteral expression, NubType? expectedType) 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)) if (!moduleGraph.TryResolveType(structType.Module, structType.Name, structType.Module == currentModule, out var info))
throw BasicError($"Type '{structType}' struct literal not found", expression); 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); var type = ResolveType(expression.Type);
switch (type) if (type is not NubTypeEnumVariant variantType)
{ throw BasicError("Expected enum variant type", expression.Type);
case NubTypeStruct structType:
{ if (!moduleGraph.TryResolveType(variantType.EnumType.Module, variantType.EnumType.Name, variantType.EnumType.Module == currentModule, out var info))
var value = CheckExpression(expression.Value, structType); throw BasicError($"Type '{variantType.EnumType}' not found", expression.Type);
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 (info is not Module.TypeInfoEnum enumInfo) if (info is not Module.TypeInfoEnum enumInfo)
throw BasicError($"Type '{enumVariantType.EnumType}' is not an enum", expression.Type); throw BasicError($"Type '{variantType.EnumType}' is not an enum", expression.Type);
var variant = enumInfo.Variants.FirstOrDefault(x => x.Name == enumVariantType.Variant); var variant = enumInfo.Variants.FirstOrDefault(x => x.Name == variantType.Variant);
if (variant == null) if (variant == null)
throw BasicError($"Enum type '{enumVariantType.EnumType}' does not have a variant named '{enumVariantType.Variant}'", expression.Type); throw BasicError($"Enum '{variantType.EnumType}' does not have a variant named '{variantType.Variant}'", expression.Type);
var value = CheckExpression(expression.Value, variant.Type); if (expression.Value == null && variant.Type is not null)
return new TypedNodeExpressionNewNamedType(expression.Tokens, enumVariantType, value); throw BasicError($"Enum variant '{variantType.EnumType}' expects a value of type '{variant.Type}'", expression.Type);
}
default: if (expression.Value != null && variant.Type is null)
{ throw BasicError($"Enum variant '{variantType.EnumType}' does not expect any data", expression.Value);
throw BasicError($"'{type}' is not a valid type for the new operator", expression);
} var value = expression.Value == null ? null : CheckExpression(expression.Value, variant.Type);
}
return new TypedNodeExpressionEnumLiteral(expression.Tokens, type, value);
} }
private NubType ResolveType(NodeType node) 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) public class TypedNodeExpressionStructMemberAccess(List<Token> tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type)

View File

@@ -14,16 +14,22 @@ func main(): i32 {
core::println("Hello, world!") core::println("Hello, world!")
core::println("Hello" + "World") core::println("Hello" + "World")
let message: Message = new Message::Say "test" let message = getMessage()
match message { match message {
Quit { Quit
{
core::println("quit") core::println("quit")
} }
Say message { Say message
{
core::println(message) core::println(message)
} }
} }
return 0 return 0
} }
func getMessage(): Message {
return new Message::Say("test")
}