Compare commits
3 Commits
9da370e387
...
693b119781
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
693b119781 | ||
|
|
2b7eb56895 | ||
|
|
5f4a4172bf |
2
TODO.txt
2
TODO.txt
@@ -1,6 +1,4 @@
|
|||||||
Comma seperated function parameters and struct/enum mebers
|
|
||||||
Converting ^u8 to string
|
Converting ^u8 to string
|
||||||
string formatting
|
string formatting
|
||||||
string concatination
|
|
||||||
Dynamic arrays
|
Dynamic arrays
|
||||||
C-style arrays
|
C-style arrays
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
|
||||||
namespace Compiler;
|
namespace Compiler;
|
||||||
|
|
||||||
@@ -260,7 +262,12 @@ public class Generator
|
|||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
|
|
||||||
foreach (var variant in enumInfo.Variants)
|
foreach (var variant in enumInfo.Variants)
|
||||||
EmitTypeDefinitionIfNotEmitted(variant.Type);
|
{
|
||||||
|
if (variant.Type is not null)
|
||||||
|
{
|
||||||
|
EmitTypeDefinitionIfNotEmitted(variant.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writer.WriteLine($"struct {NameMangler.Mangle(enumType.Module, enumType.Name, enumType)}");
|
writer.WriteLine($"struct {NameMangler.Mangle(enumType.Module, enumType.Name, enumType)}");
|
||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
@@ -273,7 +280,10 @@ public class Generator
|
|||||||
{
|
{
|
||||||
foreach (var variant in enumInfo.Variants)
|
foreach (var variant in enumInfo.Variants)
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{CType(variant.Type, variant.Name)};");
|
if (variant.Type is not null)
|
||||||
|
{
|
||||||
|
writer.WriteLine($"{CType(variant.Type, variant.Name)};");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine("};");
|
writer.WriteLine("};");
|
||||||
@@ -453,7 +463,12 @@ public class Generator
|
|||||||
using (writer.Indent())
|
using (writer.Indent())
|
||||||
{
|
{
|
||||||
PushScope();
|
PushScope();
|
||||||
writer.WriteLine($"{CType(variantInfo.Type, @case.VariableName.Ident)} = {target}.{@case.Variant.Ident};");
|
if (@case.VariableName != null)
|
||||||
|
{
|
||||||
|
Debug.Assert(variantInfo.Type is not null);
|
||||||
|
writer.WriteLine($"{CType(variantInfo.Type, @case.VariableName.Ident)} = {target}.{@case.Variant.Ident};");
|
||||||
|
}
|
||||||
|
|
||||||
EmitStatement(@case.Body);
|
EmitStatement(@case.Body);
|
||||||
PopScope();
|
PopScope();
|
||||||
writer.WriteLine("break;");
|
writer.WriteLine("break;");
|
||||||
@@ -576,10 +591,19 @@ public class Generator
|
|||||||
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;
|
||||||
EmitCopyConstructor(value, expression.Value.Type);
|
if (expression.Value != null)
|
||||||
|
{
|
||||||
|
value = EmitExpression(expression.Value);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -710,14 +734,17 @@ public class Generator
|
|||||||
{
|
{
|
||||||
Module.TypeInfoEnum.Variant variant = enumInfo.Variants[i];
|
Module.TypeInfoEnum.Variant variant = enumInfo.Variants[i];
|
||||||
|
|
||||||
writer.WriteLine($"case {i}:");
|
if (variant.Type is not null)
|
||||||
writer.WriteLine("{");
|
|
||||||
using (writer.Indent())
|
|
||||||
{
|
{
|
||||||
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
|
writer.WriteLine($"case {i}:");
|
||||||
writer.WriteLine("break;");
|
writer.WriteLine("{");
|
||||||
|
using (writer.Indent())
|
||||||
|
{
|
||||||
|
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
|
||||||
|
writer.WriteLine("break;");
|
||||||
|
}
|
||||||
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
writer.WriteLine("}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
@@ -729,8 +756,9 @@ public class Generator
|
|||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
|
|
||||||
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
|
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
|
||||||
|
if (variant.Type is not null)
|
||||||
|
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
|
||||||
|
|
||||||
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -776,15 +804,17 @@ public class Generator
|
|||||||
for (int i = 0; i < enumInfo.Variants.Count; i++)
|
for (int i = 0; i < enumInfo.Variants.Count; i++)
|
||||||
{
|
{
|
||||||
var variant = enumInfo.Variants[i];
|
var variant = enumInfo.Variants[i];
|
||||||
|
if (variant.Type is not null)
|
||||||
writer.WriteLine($"case {i}:");
|
|
||||||
writer.WriteLine("{");
|
|
||||||
using (writer.Indent())
|
|
||||||
{
|
{
|
||||||
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
|
writer.WriteLine($"case {i}:");
|
||||||
writer.WriteLine("break;");
|
writer.WriteLine("{");
|
||||||
|
using (writer.Indent())
|
||||||
|
{
|
||||||
|
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
|
||||||
|
writer.WriteLine("break;");
|
||||||
|
}
|
||||||
|
writer.WriteLine("}");
|
||||||
}
|
}
|
||||||
writer.WriteLine("}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.WriteLine("}");
|
writer.WriteLine("}");
|
||||||
@@ -796,8 +826,9 @@ public class Generator
|
|||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
|
|
||||||
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
|
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
|
||||||
|
if (variant.Type is not null)
|
||||||
|
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
|
||||||
|
|
||||||
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class ModuleGraph
|
|||||||
|
|
||||||
if (typeInfo is Module.TypeInfoEnum enumType)
|
if (typeInfo is Module.TypeInfoEnum enumType)
|
||||||
{
|
{
|
||||||
var variants = enumDef.Variants.Select(v => new Module.TypeInfoEnum.Variant(v.Name.Ident, ResolveType(v.Type, module.Name))).ToList();
|
var variants = enumDef.Variants.Select(v => new Module.TypeInfoEnum.Variant(v.Name.Ident, v.Type == null ? null : ResolveType(v.Type, module.Name))).ToList();
|
||||||
enumType.SetVariants(variants);
|
enumType.SetVariants(variants);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,10 +435,10 @@ public class Module(string name)
|
|||||||
this.variants = variants;
|
this.variants = variants;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Variant(string name, NubType type)
|
public class Variant(string name, NubType? type)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public NubType Type { get; } = type;
|
public NubType? Type { get; } = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ public record Manifest(Dictionary<string, Manifest.Module> Modules)
|
|||||||
|
|
||||||
public record TypeInfoEnum(bool Exported, IReadOnlyList<TypeInfoEnum.Variant> Variants) : TypeInfo(Exported)
|
public record TypeInfoEnum(bool Exported, IReadOnlyList<TypeInfoEnum.Variant> Variants) : TypeInfo(Exported)
|
||||||
{
|
{
|
||||||
public record Variant(string Name, NubType Type);
|
public record Variant(string Name, NubType? Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,17 +86,7 @@ public class Parser
|
|||||||
throw BasicError("Invalid modifier for function", modifier.Value);
|
throw BasicError("Invalid modifier for function", modifier.Value);
|
||||||
|
|
||||||
var name = ExpectIdent();
|
var name = ExpectIdent();
|
||||||
var parameters = new List<NodeDefinitionFunc.Param>();
|
var parameters = ParseFuncParameters();
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
{
|
|
||||||
var paramStartIndex = index;
|
|
||||||
var parameterName = ExpectIdent();
|
|
||||||
ExpectSymbol(Symbol.Colon);
|
|
||||||
var parameterType = ParseType();
|
|
||||||
parameters.Add(new NodeDefinitionFunc.Param(TokensFrom(paramStartIndex), parameterName, parameterType));
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeType? returnType = null;
|
NodeType? returnType = null;
|
||||||
if (TryExpectSymbol(Symbol.Colon))
|
if (TryExpectSymbol(Symbol.Colon))
|
||||||
@@ -132,6 +122,7 @@ public class Parser
|
|||||||
var fieldName = ExpectIdent();
|
var fieldName = ExpectIdent();
|
||||||
ExpectSymbol(Symbol.Colon);
|
ExpectSymbol(Symbol.Colon);
|
||||||
var fieldType = ParseType();
|
var fieldType = ParseType();
|
||||||
|
TryExpectSymbol(Symbol.Comma);
|
||||||
fields.Add(new NodeDefinitionStruct.Field(TokensFrom(fieldStartIndex), fieldName, fieldType));
|
fields.Add(new NodeDefinitionStruct.Field(TokensFrom(fieldStartIndex), fieldName, fieldType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,8 +145,13 @@ public class Parser
|
|||||||
{
|
{
|
||||||
var variantsStartIndex = index;
|
var variantsStartIndex = index;
|
||||||
var variantName = ExpectIdent();
|
var variantName = ExpectIdent();
|
||||||
ExpectSymbol(Symbol.Colon);
|
|
||||||
var variantType = ParseType();
|
NodeType? variantType = null;
|
||||||
|
if (TryExpectSymbol(Symbol.Colon))
|
||||||
|
variantType = ParseType();
|
||||||
|
|
||||||
|
TryExpectSymbol(Symbol.Comma);
|
||||||
|
|
||||||
variants.Add(new NodeDefinitionEnum.Variant(TokensFrom(variantsStartIndex), variantName, variantType));
|
variants.Add(new NodeDefinitionEnum.Variant(TokensFrom(variantsStartIndex), variantName, variantType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +176,35 @@ public class Parser
|
|||||||
throw BasicError("Not a valid definition", Peek());
|
throw BasicError("Not a valid definition", Peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<NodeDefinitionFunc.Param> ParseFuncParameters()
|
||||||
|
{
|
||||||
|
var parameters = new List<NodeDefinitionFunc.Param>();
|
||||||
|
|
||||||
|
ExpectSymbol(Symbol.OpenParen);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (TryExpectSymbol(Symbol.CloseParen))
|
||||||
|
break;
|
||||||
|
|
||||||
|
var startIndex = index;
|
||||||
|
|
||||||
|
var name = ExpectIdent();
|
||||||
|
ExpectSymbol(Symbol.Colon);
|
||||||
|
var type = ParseType();
|
||||||
|
|
||||||
|
parameters.Add(new NodeDefinitionFunc.Param(TokensFrom(startIndex), name, type));
|
||||||
|
|
||||||
|
if (!TryExpectSymbol(Symbol.Comma))
|
||||||
|
{
|
||||||
|
ExpectSymbol(Symbol.CloseParen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
private NodeStatement ParseStatement()
|
private NodeStatement ParseStatement()
|
||||||
{
|
{
|
||||||
var startIndex = index;
|
var startIndex = index;
|
||||||
@@ -251,10 +276,10 @@ public class Parser
|
|||||||
while (!TryExpectSymbol(Symbol.CloseCurly))
|
while (!TryExpectSymbol(Symbol.CloseCurly))
|
||||||
{
|
{
|
||||||
var caseStartIndex = index;
|
var caseStartIndex = index;
|
||||||
var type = ExpectIdent();
|
var variant = ExpectIdent();
|
||||||
var variableName = ExpectIdent();
|
TryExpectIdent(out var variableName);
|
||||||
var body = ParseStatement();
|
var body = ParseStatement();
|
||||||
cases.Add(new NodeStatementMatch.Case(TokensFrom(caseStartIndex), type, variableName, body));
|
cases.Add(new NodeStatementMatch.Case(TokensFrom(caseStartIndex), variant, variableName, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NodeStatementMatch(TokensFrom(startIndex), target, cases);
|
return new NodeStatementMatch(TokensFrom(startIndex), target, cases);
|
||||||
@@ -380,30 +405,35 @@ public class Parser
|
|||||||
|
|
||||||
expr = new NodeExpressionIdent(TokensFrom(startIndex), sections);
|
expr = new NodeExpressionIdent(TokensFrom(startIndex), sections);
|
||||||
}
|
}
|
||||||
else if (TryExpectKeyword(Keyword.Struct))
|
else if (TryExpectKeyword(Keyword.New))
|
||||||
{
|
{
|
||||||
var type = ParseType();
|
var type = ParseType();
|
||||||
|
|
||||||
var initializers = new List<NodeExpressionStructLiteral.Initializer>();
|
if (TryExpectSymbol(Symbol.OpenParen))
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenCurly);
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseCurly))
|
|
||||||
{
|
{
|
||||||
var initializerStartIndex = startIndex;
|
var value = ParseExpression();
|
||||||
var fieldName = ExpectIdent();
|
ExpectSymbol(Symbol.CloseParen);
|
||||||
ExpectSymbol(Symbol.Equal);
|
|
||||||
var fieldValue = ParseExpression();
|
expr = new NodeExpressionEnumLiteral(TokensFrom(startIndex), type, value);
|
||||||
initializers.Add(new NodeExpressionStructLiteral.Initializer(TokensFrom(initializerStartIndex), fieldName, fieldValue));
|
|
||||||
}
|
}
|
||||||
|
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), type, initializers);
|
expr = new NodeExpressionStructLiteral(TokensFrom(startIndex), null, initializers);
|
||||||
}
|
}
|
||||||
else if (TryExpectKeyword(Keyword.Enum))
|
else
|
||||||
{
|
{
|
||||||
var type = ParseType();
|
expr = new NodeExpressionEnumLiteral(TokensFrom(startIndex), type, null);
|
||||||
var value = ParseExpression();
|
}
|
||||||
|
|
||||||
expr = new NodeExpressionEnumLiteral(TokensFrom(startIndex), type, value);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -769,10 +799,10 @@ public class NodeDefinitionEnum(List<Token> tokens, bool exported, TokenIdent na
|
|||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
public List<Variant> Variants { get; } = variants;
|
public List<Variant> Variants { get; } = variants;
|
||||||
|
|
||||||
public class Variant(List<Token> tokens, TokenIdent name, NodeType type) : Node(tokens)
|
public class Variant(List<Token> tokens, TokenIdent name, NodeType? type) : Node(tokens)
|
||||||
{
|
{
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
public NodeType Type { get; } = type;
|
public NodeType? Type { get; } = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,10 +868,10 @@ public class NodeStatementMatch(List<Token> tokens, NodeExpression target, List<
|
|||||||
public NodeExpression Target { get; } = target;
|
public NodeExpression Target { get; } = target;
|
||||||
public List<Case> Cases { get; } = cases;
|
public List<Case> Cases { get; } = cases;
|
||||||
|
|
||||||
public class Case(List<Token> tokens, TokenIdent type, TokenIdent variableName, NodeStatement body) : Node(tokens)
|
public class Case(List<Token> tokens, TokenIdent type, TokenIdent? variableName, NodeStatement body) : Node(tokens)
|
||||||
{
|
{
|
||||||
public TokenIdent Variant { get; } = type;
|
public TokenIdent Variant { get; } = type;
|
||||||
public TokenIdent VariableName { get; } = variableName;
|
public TokenIdent? VariableName { get; } = variableName;
|
||||||
public NodeStatement Body { get; } = body;
|
public NodeStatement Body { get; } = body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -875,10 +905,10 @@ public class NodeExpressionStructLiteral(List<Token> tokens, NodeType? type, Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NodeExpressionEnumLiteral(List<Token> tokens, NodeType type, NodeExpression value) : NodeExpression(tokens)
|
public class NodeExpressionEnumLiteral(List<Token> tokens, NodeType type, NodeExpression? value) : NodeExpression(tokens)
|
||||||
{
|
{
|
||||||
public NodeType Type { get; } = type;
|
public NodeType Type { get; } = type;
|
||||||
public NodeExpression Value { get; } = value;
|
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)
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ public class Tokenizer
|
|||||||
"struct" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Struct),
|
"struct" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Struct),
|
||||||
"packed" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Packed),
|
"packed" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Packed),
|
||||||
"enum" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Enum),
|
"enum" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Enum),
|
||||||
|
"new" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.New),
|
||||||
"match" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Match),
|
"match" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Match),
|
||||||
"let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let),
|
"let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let),
|
||||||
"if" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.If),
|
"if" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.If),
|
||||||
@@ -538,6 +539,7 @@ public enum Keyword
|
|||||||
Struct,
|
Struct,
|
||||||
Packed,
|
Packed,
|
||||||
Enum,
|
Enum,
|
||||||
|
New,
|
||||||
Match,
|
Match,
|
||||||
Let,
|
Let,
|
||||||
If,
|
If,
|
||||||
@@ -605,6 +607,7 @@ public static class TokenExtensions
|
|||||||
Keyword.Struct => "struct",
|
Keyword.Struct => "struct",
|
||||||
Keyword.Packed => "packed",
|
Keyword.Packed => "packed",
|
||||||
Keyword.Enum => "enum",
|
Keyword.Enum => "enum",
|
||||||
|
Keyword.New => "new",
|
||||||
Keyword.Match => "enum",
|
Keyword.Match => "enum",
|
||||||
Keyword.Let => "let",
|
Keyword.Let => "let",
|
||||||
Keyword.If => "if",
|
Keyword.If => "if",
|
||||||
|
|||||||
@@ -208,15 +208,24 @@ public class TypeChecker
|
|||||||
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))
|
var variant = enumInfo.Variants.FirstOrDefault(x => x.Name == @case.Variant.Ident);
|
||||||
|
if (variant == null)
|
||||||
throw BasicError($"Enum type'{enumType}' does not have a variant named '{@case.Variant.Ident}'", @case.Variant);
|
throw BasicError($"Enum type'{enumType}' does not have a variant named '{@case.Variant.Ident}'", @case.Variant);
|
||||||
|
|
||||||
uncoveredCases.Remove(@case.Variant.Ident);
|
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));
|
if (@case.VariableName != null)
|
||||||
|
{
|
||||||
|
if (variant.Type is null)
|
||||||
|
throw BasicError("Cannot capture variable for enum variant without type", @case.VariableName);
|
||||||
|
|
||||||
|
scope.DeclareIdentifier(@case.VariableName.Ident, variant.Type);
|
||||||
|
}
|
||||||
|
|
||||||
var body = CheckStatement(@case.Body);
|
var body = CheckStatement(@case.Body);
|
||||||
|
|
||||||
cases.Add(new TypedNodeStatementMatch.Case(@case.Tokens, @case.Variant, @case.VariableName, body));
|
cases.Add(new TypedNodeStatementMatch.Case(@case.Tokens, @case.Variant, @case.VariableName, body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,7 +627,14 @@ public class TypeChecker
|
|||||||
if (variant == null)
|
if (variant == null)
|
||||||
throw BasicError($"Enum '{variantType.EnumType}' does not have a variant named '{variantType.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)
|
||||||
|
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);
|
return new TypedNodeExpressionEnumLiteral(expression.Tokens, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,10 +876,10 @@ public class TypedNodeStatementMatch(List<Token> tokens, TypedNodeExpression tar
|
|||||||
public TypedNodeExpression Target { get; } = target;
|
public TypedNodeExpression Target { get; } = target;
|
||||||
public List<Case> Cases { get; } = cases;
|
public List<Case> Cases { get; } = cases;
|
||||||
|
|
||||||
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 Variant { 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -899,9 +915,9 @@ public class TypedNodeExpressionStructLiteral(List<Token> tokens, NubType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TypedNodeExpressionEnumLiteral(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)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module sys
|
module sys
|
||||||
|
|
||||||
export extern func read(fd: u32 buf: ^u8 count: u64): i64
|
export extern func read(fd: u32, buf: ^u8, count: u64): i64
|
||||||
export extern func write(fd: u32 buf: ^u8 count: u64): i64
|
export extern func write(fd: u32, buf: ^u8, count: u64): i64
|
||||||
export extern func open(fileName: ^u8 flags: i32 mode: u16): i64
|
export extern func open(fileName: ^u8, flags: i32, mode: u16): i64
|
||||||
@@ -1,7 +1,35 @@
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
|
struct Human {
|
||||||
|
name: string
|
||||||
|
age: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Message {
|
||||||
|
Quit
|
||||||
|
Say: string
|
||||||
|
}
|
||||||
|
|
||||||
func main(): i32 {
|
func main(): i32 {
|
||||||
core::println("Hello, world!")
|
core::println("Hello, world!")
|
||||||
core::println("Hello" + "World")
|
core::println("Hello" + "World")
|
||||||
|
|
||||||
|
let message = getMessage()
|
||||||
|
|
||||||
|
match message {
|
||||||
|
Quit
|
||||||
|
{
|
||||||
|
core::println("quit")
|
||||||
|
}
|
||||||
|
Say message
|
||||||
|
{
|
||||||
|
core::println(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMessage(): Message {
|
||||||
|
return new Message::Say("test")
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user