WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
3 changed files with 37 additions and 40 deletions
Showing only changes of commit b7dc77cb1c - Show all commits

View File

@@ -301,13 +301,13 @@ public class Generator
{ {
foreach (var @case in statement.Cases) foreach (var @case in statement.Cases)
{ {
var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == @case.Type.Ident); var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == @case.Variant.Ident);
writer.WriteLine($"case {tag}:"); writer.WriteLine($"case {tag}:");
writer.WriteLine("{"); writer.WriteLine("{");
using (writer.Indent()) using (writer.Indent())
{ {
writer.WriteLine($"auto {@case.VariableName.Ident} = {target}.{@case.Type.Ident};"); writer.WriteLine($"auto {@case.VariableName.Ident} = {target}.{@case.Variant.Ident};");
EmitStatement(@case.Body); EmitStatement(@case.Body);
} }
writer.WriteLine("}"); writer.WriteLine("}");

View File

@@ -191,9 +191,22 @@ public class TypeChecker
if (target.Type is not NubTypeEnum enumType) if (target.Type is not NubTypeEnum enumType)
throw BasicError("A match statement can only be used on enum types", target); throw BasicError("A match statement can only be used on enum types", target);
if (!moduleGraph.TryResolveType(enumType.Module, enumType.Name, enumType.Module == currentModule, out var info))
throw BasicError($"Type '{enumType}' not found", target);
if (info is not Module.TypeInfoEnum enumInfo)
throw BasicError($"Type '{enumType}' is not an enum", target);
var uncoveredCases = enumInfo.Variants.Select(x => x.Name).ToList();
var cases = new List<TypedNodeStatementMatch.Case>(); var cases = new List<TypedNodeStatementMatch.Case>();
foreach (var @case in statement.Cases) foreach (var @case in statement.Cases)
{ {
if (!enumInfo.Variants.Any(x => x.Name == @case.Variant.Ident))
throw BasicError($"Enum type'{enumType}' does not have a variant named '{@case.Variant.Ident}'", @case.Variant);
uncoveredCases.Remove(@case.Variant.Ident);
using (scope.EnterScope()) using (scope.EnterScope())
{ {
scope.DeclareIdentifier(@case.VariableName.Ident, NubTypeEnumVariant.Get(NubTypeEnum.Get(enumType.Module, enumType.Name), @case.Variant.Ident)); scope.DeclareIdentifier(@case.VariableName.Ident, NubTypeEnumVariant.Get(NubTypeEnum.Get(enumType.Module, enumType.Name), @case.Variant.Ident));
@@ -202,6 +215,9 @@ public class TypeChecker
} }
} }
if (uncoveredCases.Any())
throw BasicError($"Match statement does not cover the following cases: {string.Join(", ", uncoveredCases)}", statement);
return new TypedNodeStatementMatch(statement.Tokens, target, cases); return new TypedNodeStatementMatch(statement.Tokens, target, cases);
} }
@@ -791,7 +807,7 @@ public class TypedNodeStatementMatch(List<Token> tokens, TypedNodeExpression tar
public class Case(List<Token> tokens, TokenIdent type, TokenIdent variableName, TypedNodeStatement body) : Node(tokens) public class Case(List<Token> tokens, TokenIdent type, TokenIdent variableName, TypedNodeStatement body) : Node(tokens)
{ {
public TokenIdent Type { get; } = type; public TokenIdent Variant { get; } = type;
public TokenIdent VariableName { get; } = variableName; public TokenIdent VariableName { get; } = variableName;
public TypedNodeStatement Body { get; } = body; public TypedNodeStatement Body { get; } = body;
} }

View File

@@ -1,53 +1,34 @@
module math module math
export struct vec2 { export struct Human {
name: string
age: i32
}
export struct Pos {
x: i32 x: i32
y: i32 y: i32
} }
export struct vec3 { export enum Message {
x: i32 Quit: {}
y: i32 Move: Pos
z: i32
}
export struct color {
r: i32
g: i32
b: i32
a: i32
}
export struct example {
b: color
}
export enum message {
quit: {}
move: color
} }
export func add(a: i32 b: i32): i32 export func add(a: i32 b: i32): i32
{ {
let message: message = enum message::move { let msg: Message = enum Message::Move {
r = 23 x = 10
g = 46 y = 10
b = 56
} }
match message { match msg {
quit q {} Quit q {
move m { // quit
m.r = 23
m.g = 23
m.b = 23
} }
Move m {
// move
} }
let color: color = {
r = 23
g = 23
b = 23
} }
return add_internal(a b) return add_internal(a b)