This commit is contained in:
nub31
2025-07-05 18:08:59 +02:00
parent 5246e54ac9
commit e195731b9e
9 changed files with 413 additions and 296 deletions

View File

@@ -2,7 +2,6 @@
using CLI; using CLI;
using Generation.QBE; using Generation.QBE;
using Syntax; using Syntax;
using Syntax.Binding;
using Syntax.Diagnostics; using Syntax.Diagnostics;
using Syntax.Node; using Syntax.Node;
using Syntax.Parsing; using Syntax.Parsing;
@@ -83,13 +82,11 @@ foreach (var file in options.Files)
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics); var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
diagnostics.AddRange(tokenizerDiagnostics); diagnostics.AddRange(tokenizerDiagnostics);
var syntaxTree = Parser.ParseFile(tokenizeResult, out var parseDiagnostics); var parser = new Parser(tokenizeResult);
diagnostics.AddRange(parseDiagnostics); var syntaxTree = parser.Parse();
diagnostics.AddRange(syntaxTree.Diagnostics);
if (syntaxTree != null)
{
syntaxTrees[file] = syntaxTree; syntaxTrees[file] = syntaxTree;
}
} }
var definitionTable = new DefinitionTable(syntaxTrees.Values); var definitionTable = new DefinitionTable(syntaxTrees.Values);
@@ -98,13 +95,12 @@ var boundSyntaxTrees = new Dictionary<string, BoundSyntaxTree>();
foreach (var (file, syntaxTree) in syntaxTrees) foreach (var (file, syntaxTree) in syntaxTrees)
{ {
var boundSyntaxTree = Binder.Bind(syntaxTree, definitionTable, out var binderDiagnostics); var binder = new Binder(syntaxTree, definitionTable);
diagnostics.AddRange(binderDiagnostics); var boundSyntaxTree = binder.Bind();
diagnostics.AddRange(boundSyntaxTree.Diagnostics);
boundSyntaxTrees[file] = boundSyntaxTree; boundSyntaxTrees[file] = boundSyntaxTree;
} }
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values);
foreach (var diagnostic in diagnostics) foreach (var diagnostic in diagnostics)
{ {
Console.Error.WriteLine(diagnostic.FormatANSI()); Console.Error.WriteLine(diagnostic.FormatANSI());
@@ -115,6 +111,8 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
return 1; return 1;
} }
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values);
var objectFiles = new List<string>(); var objectFiles = new List<string>();
foreach (var file in options.Files) foreach (var file in options.Files)

View File

@@ -2,20 +2,25 @@
namespace Common; namespace Common;
public readonly struct Optional public static class Optional
{ {
public static Optional<TValue> Empty<TValue>() => new(); public static Optional<TValue> Empty<TValue>() => new();
/// <summary> /// <summary>
/// Alias for creating an Optional&lt;TValue&gt; which allows for implicit types /// Alias for creating an Optional which allows for implicit types
/// </summary> /// </summary>
/// <param name="value"></param>
/// <typeparam name="TValue"></typeparam>
/// <returns></returns>
public static Optional<TValue> OfNullable<TValue>(TValue? value) public static Optional<TValue> OfNullable<TValue>(TValue? value)
{ {
return value ?? Optional<TValue>.Empty(); return value ?? Optional<TValue>.Empty();
} }
/// <summary>
/// Converts a nullable type to an Optional
/// </summary>
public static Optional<TValue> ToOptional<TValue>(this TValue? value)
{
return OfNullable(value);
}
} }
public readonly struct Optional<TValue> public readonly struct Optional<TValue>

View File

@@ -53,21 +53,21 @@ public static class QBEGenerator
_implFuncNameIndex = 0; _implFuncNameIndex = 0;
_codeIsReachable = true; _codeIsReachable = true;
foreach (var structDef in _definitionTable.GetStructs()) // foreach (var structDef in _definitionTable.GetStructs())
{ // {
EmitStructDefinition(structDef); // EmitStructDefinition(structDef);
_writer.NewLine(); // _writer.NewLine();
} // }
//
foreach (var trait in _definitionTable.GetTraits()) // foreach (var trait in _definitionTable.GetTraits())
{ // {
EmitTraitVTable(trait); // EmitTraitVTable(trait);
_writer.NewLine(); // _writer.NewLine();
} // }
foreach (var funcDef in _syntaxTree.TopLevelNodes.OfType<BoundLocalFuncNode>()) foreach (var funcDef in _syntaxTree.TopLevelNodes.OfType<BoundLocalFuncNode>())
{ {
EmitFuncDefinition(funcDef, FuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported); EmitFuncDefinition(funcDef, LocalFuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported);
_writer.NewLine(); _writer.NewLine();
} }
@@ -117,16 +117,14 @@ public static class QBEGenerator
return $"$string{++_stringLiteralIndex}"; return $"$string{++_stringLiteralIndex}";
} }
private static string FuncName(BoundFuncDefinition funcDef) private static string LocalFuncName(BoundLocalFuncNode funcDef)
{ {
return funcDef switch return funcDef.Exported ? $"${funcDef.Name}" : $"${funcDef.Namespace}_{funcDef.Name}";
}
private static string ExternFuncName(BoundExternFuncNode funcDef)
{ {
BoundExternFuncNode externFuncDefinition => $"${externFuncDefinition.CallName}", return $"${funcDef.CallName}";
BoundLocalFuncNode localFuncDefinition => localFuncDefinition.Exported
? $"${localFuncDefinition.Name}"
: $"${localFuncDefinition.Namespace}_{localFuncDefinition.Name}",
_ => throw new ArgumentOutOfRangeException(nameof(funcDef))
};
} }
private static string ImplFuncName(BoundTraitImplNode implDef, string funcName) private static string ImplFuncName(BoundTraitImplNode implDef, string funcName)
@@ -586,65 +584,65 @@ public static class QBEGenerator
_writer.EndFunction(); _writer.EndFunction();
} }
private static void EmitStructDefinition(BoundStructNode structDef) // private static void EmitStructDefinition(BoundStructNode structDef)
{ // {
var structType = new NubCustomType(structDef.Namespace, structDef.Name); // var structType = new NubCustomType(structDef.Namespace, structDef.Name);
_writer.WriteLine($"type {CustomTypeName(structType)} = {{ "); // _writer.WriteLine($"type {CustomTypeName(structType)} = {{ ");
//
var types = new Dictionary<string, string>(); // var types = new Dictionary<string, string>();
//
foreach (var field in structDef.Fields) // foreach (var field in structDef.Fields)
{ // {
types.Add(field.Name, StructDefQBEType(field)); // types.Add(field.Name, StructDefQBEType(field));
} // }
//
var longest = types.Values.Max(x => x.Length); // var longest = types.Values.Max(x => x.Length);
foreach (var (name, type) in types) // foreach (var (name, type) in types)
{ // {
var padding = longest - type.Length; // var padding = longest - type.Length;
_writer.Indented($"{type},{new string(' ', padding)} # {name}"); // _writer.Indented($"{type},{new string(' ', padding)} # {name}");
} // }
//
_writer.WriteLine("}"); // _writer.WriteLine("}");
return; // return;
//
string StructDefQBEType(BoundStructFieldNode field) // string StructDefQBEType(BoundStructFieldNode field)
{ // {
return field.Type switch // return field.Type switch
{ // {
NubCustomType customType => CustomTypeName(customType), // NubCustomType customType => CustomTypeName(customType),
NubComplexType => "l", // NubComplexType => "l",
NubSimpleType simpleType => simpleType switch // NubSimpleType simpleType => simpleType switch
{ // {
NubPointerType or NubFuncType => "l", // NubPointerType or NubFuncType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch // NubPrimitiveType primitiveType => primitiveType.Kind switch
{ // {
PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", // PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", // PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "h", // PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "h",
PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "b", // PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "b",
PrimitiveTypeKind.F64 => "d", // PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s", // PrimitiveTypeKind.F32 => "s",
_ => throw new ArgumentOutOfRangeException() // _ => throw new ArgumentOutOfRangeException()
}, // },
_ => throw new NotSupportedException($"'{field.Type}' type cannot be used in structs") // _ => throw new NotSupportedException($"'{field.Type}' type cannot be used in structs")
}, // },
_ => throw new UnreachableException() // _ => throw new UnreachableException()
}; // };
} // }
} // }
//
private static void EmitTraitVTable(BoundTraitNode traitDef) // private static void EmitTraitVTable(BoundTraitNode traitDef)
{ // {
_writer.WriteLine($"type {CustomTypeName(new NubCustomType(traitDef.Namespace, traitDef.Name))} = {{"); // _writer.WriteLine($"type {CustomTypeName(new NubCustomType(traitDef.Namespace, traitDef.Name))} = {{");
//
foreach (var func in traitDef.Functions) // foreach (var func in traitDef.Functions)
{ // {
_writer.Indented($"l, # func {func.Name}({string.Join(", ", func.Parameters.Select(x => $"{x.Name}: {x.Type}"))}): {func.ReturnType}"); // _writer.Indented($"l, # func {func.Name}({string.Join(", ", func.Parameters.Select(x => $"{x.Name}: {x.Type}"))}): {func.ReturnType}");
} // }
//
_writer.WriteLine("}"); // _writer.WriteLine("}");
} // }
private static void EmitStatement(BoundStatementNode statement) private static void EmitStatement(BoundStatementNode statement)
{ {
@@ -683,7 +681,7 @@ public static class QBEGenerator
private static void EmitAssignment(BoundAssignmentNode assignment) private static void EmitAssignment(BoundAssignmentNode assignment)
{ {
var destination = EmitExpression(assignment.Expression); var destination = EmitExpression(assignment.Target);
Debug.Assert(destination.Kind == ValKind.Pointer); Debug.Assert(destination.Kind == ValKind.Pointer);
EmitCopyIntoOrInitialize(assignment.Value, destination.Name); EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
} }

View File

@@ -7,34 +7,45 @@ using UnaryExpressionNode = Syntax.Node.UnaryExpressionNode;
namespace Syntax.Binding; namespace Syntax.Binding;
// TODO: Currently anonymous function does not get a new scope // TODO: Currently anonymous function does not get a new scope
public static class Binder public sealed class Binder
{ {
private static SyntaxTree _syntaxTree = null!; private readonly SyntaxTree _syntaxTree;
private static DefinitionTable _definitionTable = null!; private readonly DefinitionTable _definitionTable;
private static Dictionary<string, NubType> _variables = new(); // TODO: Implement proper variable tracking and scoping
private static NubType? _funcReturnType; private Dictionary<string, NubType> _variables = new();
private NubType? _functionReturnType;
public static BoundSyntaxTree Bind(SyntaxTree syntaxTree, DefinitionTable definitionTable, out IEnumerable<Diagnostic> diagnostics) public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable)
{ {
_syntaxTree = syntaxTree; _syntaxTree = syntaxTree;
_definitionTable = definitionTable; _definitionTable = definitionTable;
}
_variables = []; public BoundSyntaxTree Bind()
_funcReturnType = null;
var definitions = new List<BoundTopLevelNode>();
foreach (var topLevel in syntaxTree.TopLevelNodes)
{ {
definitions.Add(BindTopLevel(topLevel)); _variables = [];
_functionReturnType = null;
var diagnostics = new List<Diagnostic>();
var topLevelNodes = new List<BoundTopLevelNode>();
foreach (var topLevel in _syntaxTree.TopLevelNodes)
{
try
{
topLevelNodes.Add(BindTopLevel(topLevel));
}
catch (BindException e)
{
diagnostics.Add(e.Diagnostic);
}
} }
diagnostics = []; return new BoundSyntaxTree(_syntaxTree.Namespace, topLevelNodes, diagnostics);
return new BoundSyntaxTree(syntaxTree.Namespace, definitions);
} }
private static BoundTopLevelNode BindTopLevel(TopLevelNode node) private BoundTopLevelNode BindTopLevel(TopLevelNode node)
{ {
return node switch return node switch
{ {
@@ -47,7 +58,7 @@ public static class Binder
}; };
} }
private static BoundTraitImplNode BindTraitImplementation(TraitImplNode node) private BoundTraitImplNode BindTraitImplementation(TraitImplNode node)
{ {
_variables.Clear(); _variables.Clear();
var functions = new List<BoundTraitFuncImplNode>(); var functions = new List<BoundTraitFuncImplNode>();
@@ -65,7 +76,7 @@ public static class Binder
return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions); return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions);
} }
private static BoundTraitNode BindTraitDefinition(TraitNode node) private BoundTraitNode BindTraitDefinition(TraitNode node)
{ {
var functions = new List<BoundTraitFuncNode>(); var functions = new List<BoundTraitFuncNode>();
@@ -77,46 +88,34 @@ public static class Binder
return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions); return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions);
} }
private static BoundStructNode BindStruct(StructNode node) private BoundStructNode BindStruct(StructNode node)
{ {
var defOpt = _definitionTable.LookupStruct(node.Namespace, node.Name);
if (!defOpt.TryGetValue(out var definition))
{
throw new NotImplementedException("Diagnostics not implemented");
}
var structFields = new List<BoundStructFieldNode>(); var structFields = new List<BoundStructFieldNode>();
foreach (var structField in node.Fields) foreach (var field in node.Fields)
{ {
var value = Optional.Empty<BoundExpressionNode>(); var value = Optional.Empty<BoundExpressionNode>();
if (structField.Value.HasValue) if (field.Value.HasValue)
{ {
var definitionField = definition.Fields.FirstOrDefault(f => f.Name == structField.Name); value = BindExpression(field.Value.Value, field.Type);
if (definitionField == null)
{
throw new NotImplementedException("Diagnostics not implemented");
} }
value = BindExpression(structField.Value.Value, definitionField.Type); structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, field.Type, value));
}
structFields.Add(new BoundStructFieldNode(structField.Tokens, structField.Name, structField.Type, value));
} }
return new BoundStructNode(node.Tokens, node.Namespace, node.Name, structFields); return new BoundStructNode(node.Tokens, node.Namespace, node.Name, structFields);
} }
private static BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node) private BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node)
{ {
return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, node.ReturnType); return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, node.ReturnType);
} }
private static BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node)
{ {
_variables.Clear(); _variables.Clear();
_funcReturnType = node.ReturnType; _functionReturnType = node.ReturnType;
foreach (var parameter in node.Parameters) foreach (var parameter in node.Parameters)
{ {
@@ -128,7 +127,7 @@ public static class Binder
return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, node.ReturnType, node.Exported); return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, node.ReturnType, node.Exported);
} }
private static BoundBlock BindBlock(BlockNode node) private BoundBlock BindBlock(BlockNode node)
{ {
var statements = new List<BoundStatementNode>(); var statements = new List<BoundStatementNode>();
@@ -140,7 +139,7 @@ public static class Binder
return new BoundBlock(node.Tokens, statements); return new BoundBlock(node.Tokens, statements);
} }
private static BoundStatementNode BindStatement(StatementNode node) private BoundStatementNode BindStatement(StatementNode node)
{ {
return node switch return node switch
{ {
@@ -156,24 +155,24 @@ public static class Binder
}; };
} }
private static BoundStatementNode BindAssignment(AssignmentNode statement) private BoundStatementNode BindAssignment(AssignmentNode statement)
{ {
var expression = BindExpression(statement.Expression); var expression = BindExpression(statement.Target);
var value = BindExpression(statement.Value, expression.Type); var value = BindExpression(statement.Value, expression.Type);
return new BoundAssignmentNode(statement.Tokens, expression, value); return new BoundAssignmentNode(statement.Tokens, expression, value);
} }
private static BoundBreakNode BindBreak(BreakNode statement) private BoundBreakNode BindBreak(BreakNode statement)
{ {
return new BoundBreakNode(statement.Tokens); return new BoundBreakNode(statement.Tokens);
} }
private static BoundContinueNode BindContinue(ContinueNode statement) private BoundContinueNode BindContinue(ContinueNode statement)
{ {
return new BoundContinueNode(statement.Tokens); return new BoundContinueNode(statement.Tokens);
} }
private static BoundIfNode BindIf(IfNode statement) private BoundIfNode BindIf(IfNode statement)
{ {
var elseStatement = Optional.Empty<Variant<BoundIfNode, BoundBlock>>(); var elseStatement = Optional.Empty<Variant<BoundIfNode, BoundBlock>>();
@@ -189,24 +188,24 @@ public static class Binder
return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement); return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement);
} }
private static BoundReturnNode BindReturn(ReturnNode statement) private BoundReturnNode BindReturn(ReturnNode statement)
{ {
var value = Optional.Empty<BoundExpressionNode>(); var value = Optional.Empty<BoundExpressionNode>();
if (statement.Value.HasValue) if (statement.Value.HasValue)
{ {
value = BindExpression(statement.Value.Value, _funcReturnType); value = BindExpression(statement.Value.Value, _functionReturnType);
} }
return new BoundReturnNode(statement.Tokens, value); return new BoundReturnNode(statement.Tokens, value);
} }
private static BoundStatementExpressionNode BindStatementExpression(StatementExpressionNode statement) private BoundStatementExpressionNode BindStatementExpression(StatementExpressionNode statement)
{ {
return new BoundStatementExpressionNode(statement.Tokens, BindExpression(statement.Expression)); return new BoundStatementExpressionNode(statement.Tokens, BindExpression(statement.Expression));
} }
private static BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) private BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement)
{ {
NubType? type = null; NubType? type = null;
@@ -233,12 +232,12 @@ public static class Binder
return new BoundVariableDeclarationNode(statement.Tokens, statement.Name, statement.ExplicitType, assignment, type); return new BoundVariableDeclarationNode(statement.Tokens, statement.Name, statement.ExplicitType, assignment, type);
} }
private static BoundWhileNode BindWhile(WhileNode statement) private BoundWhileNode BindWhile(WhileNode statement)
{ {
return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body)); return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body));
} }
private static BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) private BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null)
{ {
return node switch return node switch
{ {
@@ -258,13 +257,13 @@ public static class Binder
}; };
} }
private static BoundAddressOfNode BindAddressOf(AddressOfNode expression) private BoundAddressOfNode BindAddressOf(AddressOfNode expression)
{ {
var inner = BindExpression(expression.Expression); var inner = BindExpression(expression.Expression);
return new BoundAddressOfNode(expression.Tokens, new NubPointerType(inner.Type), inner); return new BoundAddressOfNode(expression.Tokens, new NubPointerType(inner.Type), inner);
} }
private static BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression) private BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression)
{ {
var parameterTypes = expression.Parameters.Select(x => x.Type).ToList(); var parameterTypes = expression.Parameters.Select(x => x.Type).ToList();
@@ -273,33 +272,33 @@ public static class Binder
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameterTypes), expression.Parameters, body, expression.ReturnType); return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameterTypes), expression.Parameters, body, expression.ReturnType);
} }
private static BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression) private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
{ {
var boundArray = BindExpression(expression.Array); var boundArray = BindExpression(expression.Array);
var elementType = ((NubArrayType)boundArray.Type).ElementType; var elementType = ((NubArrayType)boundArray.Type).ElementType;
return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, NubPrimitiveType.U64)); return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, NubPrimitiveType.U64));
} }
private static BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression) private BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression)
{ {
return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity, NubPrimitiveType.U64), expression.ElementType); return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity, NubPrimitiveType.U64), expression.ElementType);
} }
private static BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) private BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression)
{ {
var boundLeft = BindExpression(expression.Left); var boundLeft = BindExpression(expression.Left);
var boundRight = BindExpression(expression.Right, boundLeft.Type); var boundRight = BindExpression(expression.Right, boundLeft.Type);
return new BoundBinaryExpressionNode(expression.Tokens, boundLeft.Type, boundLeft, expression.Operator, boundRight); return new BoundBinaryExpressionNode(expression.Tokens, boundLeft.Type, boundLeft, expression.Operator, boundRight);
} }
private static BoundDereferenceNode BindDereference(DereferenceNode expression) private BoundDereferenceNode BindDereference(DereferenceNode expression)
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType; var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType;
return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression); return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression);
} }
private static BoundFuncCallNode BindFuncCall(FuncCallNode expression) private BoundFuncCallNode BindFuncCall(FuncCallNode expression)
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
@@ -323,30 +322,45 @@ public static class Binder
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters); return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters);
} }
private static BoundIdentifierNode BindIdentifier(IdentifierNode expression) private BoundIdentifierNode BindIdentifier(IdentifierNode expression)
{ {
NubType? type = null; var localFuncs = _definitionTable.LookupLocalFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray();
if (localFuncs.Length > 0)
var definition = _definitionTable.LookupFunction(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name);
if (definition.HasValue)
{ {
type = new NubFuncType(definition.Value.ReturnType, definition.Value.Parameters.Select(p => p.Type).ToList()); if (localFuncs.Length > 1)
{
throw new BindException(Diagnostic.Error($"Extern func {expression.Namespace}::{expression.Name} has multiple definitions").Build());
} }
if (type == null && !expression.Namespace.HasValue) var localFunc = localFuncs[0];
{
type = _variables[expression.Name];
}
if (type == null)
{
throw new NotImplementedException("Diagnostics not implemented");
}
var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList());
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name);
} }
private static BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) var externFuncs = _definitionTable.LookupExternFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray();
if (externFuncs.Length > 0)
{
if (externFuncs.Length > 1)
{
throw new BindException(Diagnostic.Error($"Extern func {expression.Namespace}::{expression.Name} has multiple definitions").Build());
}
var externFunc = externFuncs[0];
var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList());
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name);
}
if (!expression.Namespace.HasValue)
{
return new BoundIdentifierNode(expression.Tokens, _variables[expression.Name], expression.Namespace, expression.Name);
}
throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build());
}
private BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null)
{ {
var type = expectedType ?? expression.Kind switch var type = expectedType ?? expression.Kind switch
{ {
@@ -360,81 +374,129 @@ public static class Binder
return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind); return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind);
} }
private static BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression) private BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression)
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
var implementation = _definitionTable.LookupTraitImplementationForType(boundExpression.Type, expression.Member); var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray();
if (implementation.HasValue)
if (traitFuncImpls.Length > 0)
{ {
var type = new NubFuncType(implementation.Value.Item2.ReturnType, implementation.Value.Item2.Parameters.Select(p => p.Type).ToList()); if (traitFuncImpls.Length > 1)
{
throw new BindException(Diagnostic.Error($"Type {boundExpression.Type} implements multiple traits with the function {expression.Member}").Build());
}
var impl = traitFuncImpls[0];
var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList());
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member);
} }
if (boundExpression.Type is NubCustomType customType) if (boundExpression.Type is NubCustomType customType)
{ {
var function = _definitionTable.LookupFunctionOnTrait(customType.Namespace, customType.Name, expression.Member); var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray();
if (function.HasValue) if (traits.Length > 0)
{ {
var type = new NubFuncType(function.Value.ReturnType, function.Value.Parameters.Select(p => p.Type).ToList()); if (traits.Length > 1)
{
throw new BindException(Diagnostic.Error($"Trait {customType.Namespace}::{customType.Name} has multiple definitions").Build());
}
var trait = traits[0];
var traitFuncs = _definitionTable.LookupTraitFunc(trait, expression.Member).ToArray();
if (traits.Length > 0)
{
if (traits.Length > 1)
{
throw new BindException(Diagnostic.Error($"Trait {trait.Namespace}::{trait.Name} has multiple functions with the name {expression.Member}").Build());
}
var traitFunc = traitFuncs[0];
var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList());
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member);
} }
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
if (structDef.HasValue)
{
var matchingFields = structDef.Value.Fields.Where(f => f.Name == expression.Member).ToList();
if (matchingFields.Count > 1)
{
throw new NotImplementedException("Diagnostics not implemented");
} }
if (matchingFields.Count == 1) var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray();
if (structs.Length > 0)
{ {
return new BoundMemberAccessNode(expression.Tokens, matchingFields[0].Type, boundExpression, expression.Member); if (structs.Length > 1)
{
throw new BindException(Diagnostic.Error($"Struct {customType.Namespace}::{customType.Name} has multiple definitions").Build());
}
var @struct = structs[0];
var fields = _definitionTable.LookupStructField(@struct, customType.Name).ToArray();
if (fields.Length > 0)
{
if (fields.Length > 1)
{
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {expression.Member}").Build());
}
var field = fields[0];
return new BoundMemberAccessNode(expression.Tokens, field.Type, boundExpression, expression.Member);
} }
} }
} }
if (boundExpression.Type is NubStringType or NubCStringType or NubArrayType && expression.Member == "count") if (boundExpression.Type is NubStringType or NubCStringType or NubArrayType && expression.Member == "count")
{ {
return new BoundMemberAccessNode(expression.Tokens, NubPrimitiveType.I64, boundExpression, expression.Member); return new BoundMemberAccessNode(expression.Tokens, NubPrimitiveType.U64, boundExpression, expression.Member);
} }
throw new NotImplementedException("Diagnostics not implemented"); throw new BindException(Diagnostic.Error($"{boundExpression.Type} has not member with the name {expression.Member}").Build());
} }
private static BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression) private BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression)
{ {
if (expression.StructType is not NubCustomType structType) if (expression.StructType is not NubCustomType structType)
{ {
throw new NotImplementedException("Diagnostics not implemented"); throw new BindException(Diagnostic.Error($"Cannot initialize non-struct type {expression.StructType}").Build());
} }
var defOpt = _definitionTable.LookupStruct(structType.Namespace, structType.Name); var structs = _definitionTable.LookupStruct(structType.Namespace, structType.Name).ToArray();
if (!defOpt.TryGetValue(out var definition))
if (structs.Length == 0)
{ {
throw new NotImplementedException("Diagnostics not implemented"); throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} is not defined").Build());
} }
if (structs.Length > 1)
{
throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} has multiple definitions").Build());
}
var @struct = structs[0];
var initializers = new Dictionary<string, BoundExpressionNode>(); var initializers = new Dictionary<string, BoundExpressionNode>();
foreach (var (member, initializer) in expression.Initializers) foreach (var (field, initializer) in expression.Initializers)
{ {
var definitionField = definition.Fields.FirstOrDefault(x => x.Name == member); var fields = _definitionTable.LookupStructField(@struct, field).ToArray();
if (definitionField == null)
if (fields.Length == 0)
{ {
throw new NotImplementedException("Diagnostics not implemented"); throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} does not have a field with the name {field}").Build());
} }
initializers[member] = BindExpression(initializer, definitionField.Type); if (fields.Length > 1)
{
throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {field}").Build());
}
initializers[field] = BindExpression(initializer, fields[0].Type);
} }
return new BoundStructInitializerNode(expression.Tokens, structType, structType, initializers); return new BoundStructInitializerNode(expression.Tokens, structType, structType, initializers);
} }
private static BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression) private BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression)
{ {
var boundOperand = BindExpression(expression.Operand); var boundOperand = BindExpression(expression.Operand);
@@ -470,3 +532,13 @@ public static class Binder
return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand); return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand);
} }
} }
public class BindException : Exception
{
public Diagnostic Diagnostic { get; }
public BindException(Diagnostic diagnostic) : base(diagnostic.Message)
{
Diagnostic = diagnostic;
}
}

View File

@@ -2,7 +2,7 @@ using Syntax.Node;
namespace Syntax; namespace Syntax;
public class DefinitionTable public sealed class DefinitionTable
{ {
private readonly List<TopLevelNode> _topLevelNodes; private readonly List<TopLevelNode> _topLevelNodes;
@@ -10,14 +10,54 @@ public class DefinitionTable
{ {
_topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList(); _topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList();
} }
}
public class BoundDefinitionTable public IEnumerable<LocalFuncNode> LookupLocalFunc(string @namespace, string name)
{
private readonly List<BoundTopLevelNode> _topLevelNodes;
public BoundDefinitionTable(IEnumerable<BoundSyntaxTree> syntaxTrees)
{ {
_topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList(); return _topLevelNodes
.OfType<LocalFuncNode>()
.Where(x => x.Namespace == @namespace && x.Name == name);
}
public IEnumerable<ExternFuncNode> LookupExternFunc(string @namespace, string name)
{
return _topLevelNodes
.OfType<ExternFuncNode>()
.Where(x => x.Namespace == @namespace && x.Name == name);
}
public IEnumerable<StructNode> LookupStruct(string @namespace, string name)
{
return _topLevelNodes
.OfType<StructNode>()
.Where(x => x.Namespace == @namespace && x.Name == name);
}
public IEnumerable<StructFieldNode> LookupStructField(StructNode structNode, string field)
{
return structNode.Fields.Where(x => x.Name == field);
}
public IEnumerable<TraitImplNode> LookupTraitImpl(NubType itemType)
{
return _topLevelNodes
.OfType<TraitImplNode>()
.Where(x => x.TraitType == itemType);
}
public IEnumerable<TraitFuncImplNode> LookupTraitFuncImpl(TraitImplNode traitImpl, string name)
{
return traitImpl.Functions.Where(x => x.Name == name);
}
public IEnumerable<TraitNode> LookupTrait(string @namespace, string name)
{
return _topLevelNodes
.OfType<TraitNode>()
.Where(x => x.Namespace == @namespace && x.Name == name);
}
public IEnumerable<TraitFuncNode> LookupTraitFunc(TraitNode trait, string name)
{
return trait.Functions.Where(x => x.Name == name);
} }
} }

View File

@@ -17,10 +17,10 @@ public record BoundLocalFuncNode(IEnumerable<Token> Tokens, string Namespace, st
public record ExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace); public record ExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace);
public record BoundExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : BoundTopLevelNode(Tokens, Namespace); public record BoundExternFuncNode(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameter> Parameters, NubType ReturnType) : BoundTopLevelNode(Tokens, Namespace);
public record StructFieldNode(IEnumerable<Token> Tokens, string Name, NubType Type, Optional<ExpressionNode> Value) : DefinitionNode(Tokens); public record StructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<ExpressionNode> Value) : DefinitionNode(Tokens);
public record StructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldNode> Fields) : TopLevelNode(Tokens, Namespace); public record StructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldNode> Fields) : TopLevelNode(Tokens, Namespace);
public record BoundStructFieldNode(IEnumerable<Token> Tokens, string Name, NubType Type, Optional<BoundExpressionNode> Value) : BoundDefinitionNode(Tokens); public record BoundStructFieldNode(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<BoundExpressionNode> Value) : BoundDefinitionNode(Tokens);
public record BoundStructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructFieldNode> Fields) : BoundTopLevelNode(Tokens, Namespace); public record BoundStructNode(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructFieldNode> Fields) : BoundTopLevelNode(Tokens, Namespace);
public record TraitFuncNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType) : DefinitionNode(Tokens); public record TraitFuncNode(IEnumerable<Token> Tokens, string Name, List<FuncParameter> Parameters, NubType ReturnType) : DefinitionNode(Tokens);

View File

@@ -13,8 +13,8 @@ public record BoundStatementExpressionNode(IEnumerable<Token> Tokens, BoundExpre
public record ReturnNode(IEnumerable<Token> Tokens, Optional<ExpressionNode> Value) : StatementNode(Tokens); public record ReturnNode(IEnumerable<Token> Tokens, Optional<ExpressionNode> Value) : StatementNode(Tokens);
public record BoundReturnNode(IEnumerable<Token> Tokens, Optional<BoundExpressionNode> Value) : BoundStatementNode(Tokens); public record BoundReturnNode(IEnumerable<Token> Tokens, Optional<BoundExpressionNode> Value) : BoundStatementNode(Tokens);
public record AssignmentNode(IEnumerable<Token> Tokens, ExpressionNode Expression, ExpressionNode Value) : StatementNode(Tokens); public record AssignmentNode(IEnumerable<Token> Tokens, ExpressionNode Target, ExpressionNode Value) : StatementNode(Tokens);
public record BoundAssignmentNode(IEnumerable<Token> Tokens, BoundExpressionNode Expression, BoundExpressionNode Value) : BoundStatementNode(Tokens); public record BoundAssignmentNode(IEnumerable<Token> Tokens, BoundExpressionNode Target, BoundExpressionNode Value) : BoundStatementNode(Tokens);
public record IfNode(IEnumerable<Token> Tokens, ExpressionNode Condition, BlockNode Body, Optional<Variant<IfNode, BlockNode>> Else) : StatementNode(Tokens); public record IfNode(IEnumerable<Token> Tokens, ExpressionNode Condition, BlockNode Body, Optional<Variant<IfNode, BlockNode>> Else) : StatementNode(Tokens);
public record BoundIfNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional<Variant<BoundIfNode, BoundBlock>> Else) : BoundStatementNode(Tokens); public record BoundIfNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional<Variant<BoundIfNode, BoundBlock>> Else) : BoundStatementNode(Tokens);

View File

@@ -1,4 +1,6 @@
namespace Syntax.Node; using Syntax.Diagnostics;
public record SyntaxTree(string Namespace, List<TopLevelNode> TopLevelNodes); namespace Syntax.Node;
public record BoundSyntaxTree(string Namespace, List<BoundTopLevelNode> TopLevelNodes);
public record SyntaxTree(string Namespace, IEnumerable<TopLevelNode> TopLevelNodes, IEnumerable<Diagnostic> Diagnostics);
public record BoundSyntaxTree(string Namespace, IEnumerable<BoundTopLevelNode> TopLevelNodes, IEnumerable<Diagnostic> Diagnostics);

View File

@@ -6,53 +6,53 @@ using Syntax.Tokenization;
namespace Syntax.Parsing; namespace Syntax.Parsing;
public static class Parser public sealed class Parser
{ {
private static string _namespace = null!; private string _namespace;
private static NubType? _functionReturnType; private readonly IEnumerable<Token> _tokens;
private static List<Diagnostic> _diagnostics = [];
private static IEnumerable<Token> _tokens = [];
private static int _index;
public static SyntaxTree? ParseFile(IEnumerable<Token> tokens, out IEnumerable<Diagnostic> diagnostics) private readonly List<Diagnostic> _diagnostics = [];
private NubType? _functionReturnType;
private int _tokenIndex;
public Parser(IEnumerable<Token> tokens)
{ {
_tokens = tokens;
_namespace = "global"; _namespace = "global";
_diagnostics = []; _tokens = tokens;
_index = 0; }
public SyntaxTree Parse()
{
_diagnostics.Clear();
_functionReturnType = null; _functionReturnType = null;
_tokenIndex = 0;
if (TryExpectSymbol(Symbol.Namespace)) if (TryExpectSymbol(Symbol.Namespace))
{ {
_namespace = ExpectIdentifier().Value; _namespace = ExpectIdentifier().Value;
} }
try List<TopLevelNode> topLevelNodes = [];
{
List<TopLevelNode> definitions = [];
while (Peek().HasValue) while (Peek().HasValue)
{ {
var definition = ParseDefinition(); try
definitions.Add(definition); {
} topLevelNodes.Add(ParseTopLevel());
diagnostics = _diagnostics;
return new SyntaxTree(_namespace, definitions);
} }
catch (ParseException ex) catch (ParseException ex)
{ {
_diagnostics.Add(ex.Diagnostic); _diagnostics.Add(ex.Diagnostic);
RecoverToNextDefinition(); RecoverToNextDefinition();
} }
diagnostics = _diagnostics;
return null;
} }
private static TopLevelNode ParseDefinition() return new SyntaxTree(_namespace, topLevelNodes, _diagnostics);
}
private TopLevelNode ParseTopLevel()
{ {
var startIndex = _index; var startIndex = _tokenIndex;
List<ModifierToken> modifiers = []; List<ModifierToken> modifiers = [];
while (TryExpectModifier(out var modifier)) while (TryExpectModifier(out var modifier))
@@ -86,7 +86,7 @@ public static class Parser
return node; return node;
} }
private static TopLevelNode ParseFunc(int startIndex, List<ModifierToken> modifiers) private TopLevelNode ParseFunc(int startIndex, List<ModifierToken> modifiers)
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
List<FuncParameter> parameters = []; List<FuncParameter> parameters = [];
@@ -138,7 +138,7 @@ public static class Parser
return new LocalFuncNode(GetTokensForNode(startIndex), _namespace, name.Value, parameters, body, returnType, exported); return new LocalFuncNode(GetTokensForNode(startIndex), _namespace, name.Value, parameters, body, returnType, exported);
} }
private static StructNode ParseStruct(int startIndex) private StructNode ParseStruct(int startIndex)
{ {
var name = ExpectIdentifier().Value; var name = ExpectIdentifier().Value;
@@ -146,9 +146,11 @@ public static class Parser
List<StructFieldNode> variables = []; List<StructFieldNode> variables = [];
var fieldIndex = 0;
while (!TryExpectSymbol(Symbol.CloseBrace)) while (!TryExpectSymbol(Symbol.CloseBrace))
{ {
var fieldStartIndex = _index; var fieldStartIndex = _tokenIndex;
var variableName = ExpectIdentifier().Value; var variableName = ExpectIdentifier().Value;
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
@@ -161,13 +163,13 @@ public static class Parser
variableValue = ParseExpression(); variableValue = ParseExpression();
} }
variables.Add(new StructFieldNode(GetTokensForNode(fieldStartIndex), variableName, variableType, variableValue)); variables.Add(new StructFieldNode(GetTokensForNode(fieldStartIndex), fieldIndex++, variableName, variableType, variableValue));
} }
return new StructNode(GetTokensForNode(startIndex), _namespace, name, variables); return new StructNode(GetTokensForNode(startIndex), _namespace, name, variables);
} }
private static TraitNode ParseTrait(int startIndex) private TraitNode ParseTrait(int startIndex)
{ {
var name = ExpectIdentifier().Value; var name = ExpectIdentifier().Value;
@@ -177,7 +179,7 @@ public static class Parser
while (!TryExpectSymbol(Symbol.CloseBrace)) while (!TryExpectSymbol(Symbol.CloseBrace))
{ {
var funcStartIndex = _index; var funcStartIndex = _tokenIndex;
ExpectSymbol(Symbol.Func); ExpectSymbol(Symbol.Func);
@@ -207,7 +209,7 @@ public static class Parser
return new TraitNode(GetTokensForNode(startIndex), _namespace, name, functions); return new TraitNode(GetTokensForNode(startIndex), _namespace, name, functions);
} }
private static TraitImplNode ParseImplementation(int startIndex) private TraitImplNode ParseImplementation(int startIndex)
{ {
var traitType = ParseType(); var traitType = ParseType();
ExpectSymbol(Symbol.For); ExpectSymbol(Symbol.For);
@@ -218,7 +220,7 @@ public static class Parser
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
while (!TryExpectSymbol(Symbol.CloseBrace)) while (!TryExpectSymbol(Symbol.CloseBrace))
{ {
var funcStartIndex = _index; var funcStartIndex = _tokenIndex;
ExpectSymbol(Symbol.Func); ExpectSymbol(Symbol.Func);
var functionName = ExpectIdentifier().Value; var functionName = ExpectIdentifier().Value;
var parameters = new List<FuncParameter> var parameters = new List<FuncParameter>
@@ -252,7 +254,7 @@ public static class Parser
return new TraitImplNode(GetTokensForNode(startIndex), _namespace, traitType, forType, functions); return new TraitImplNode(GetTokensForNode(startIndex), _namespace, traitType, forType, functions);
} }
private static FuncParameter ParseFuncParameter() private FuncParameter ParseFuncParameter()
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();
ExpectSymbol(Symbol.Colon); ExpectSymbol(Symbol.Colon);
@@ -261,9 +263,9 @@ public static class Parser
return new FuncParameter(name.Value, type); return new FuncParameter(name.Value, type);
} }
private static StatementNode ParseStatement() private StatementNode ParseStatement()
{ {
var startIndex = _index; var startIndex = _tokenIndex;
if (!Peek().TryGetValue(out var token)) if (!Peek().TryGetValue(out var token))
{ {
throw new ParseException(Diagnostic throw new ParseException(Diagnostic
@@ -294,7 +296,7 @@ public static class Parser
return ParseStatementExpression(startIndex); return ParseStatementExpression(startIndex);
} }
private static StatementNode ParseStatementExpression(int startIndex) private StatementNode ParseStatementExpression(int startIndex)
{ {
var expr = ParseExpression(); var expr = ParseExpression();
@@ -307,7 +309,7 @@ public static class Parser
return new StatementExpressionNode(GetTokensForNode(startIndex), expr); return new StatementExpressionNode(GetTokensForNode(startIndex), expr);
} }
private static VariableDeclarationNode ParseVariableDeclaration(int startIndex) private VariableDeclarationNode ParseVariableDeclaration(int startIndex)
{ {
ExpectSymbol(Symbol.Let); ExpectSymbol(Symbol.Let);
var name = ExpectIdentifier().Value; var name = ExpectIdentifier().Value;
@@ -327,20 +329,20 @@ public static class Parser
return new VariableDeclarationNode(GetTokensForNode(startIndex), name, explicitType, assignment); return new VariableDeclarationNode(GetTokensForNode(startIndex), name, explicitType, assignment);
} }
private static StatementNode ParseBreak(int startIndex) private StatementNode ParseBreak(int startIndex)
{ {
ExpectSymbol(Symbol.Break); ExpectSymbol(Symbol.Break);
Next(); Next();
return new BreakNode(GetTokensForNode(startIndex)); return new BreakNode(GetTokensForNode(startIndex));
} }
private static StatementNode ParseContinue(int startIndex) private StatementNode ParseContinue(int startIndex)
{ {
ExpectSymbol(Symbol.Continue); ExpectSymbol(Symbol.Continue);
return new ContinueNode(GetTokensForNode(startIndex)); return new ContinueNode(GetTokensForNode(startIndex));
} }
private static ReturnNode ParseReturn(int startIndex) private ReturnNode ParseReturn(int startIndex)
{ {
ExpectSymbol(Symbol.Return); ExpectSymbol(Symbol.Return);
@@ -353,7 +355,7 @@ public static class Parser
return new ReturnNode(GetTokensForNode(startIndex), value); return new ReturnNode(GetTokensForNode(startIndex), value);
} }
private static IfNode ParseIf(int startIndex) private IfNode ParseIf(int startIndex)
{ {
ExpectSymbol(Symbol.If); ExpectSymbol(Symbol.If);
var condition = ParseExpression(); var condition = ParseExpression();
@@ -362,7 +364,7 @@ public static class Parser
var elseStatement = Optional<Variant<IfNode, BlockNode>>.Empty(); var elseStatement = Optional<Variant<IfNode, BlockNode>>.Empty();
if (TryExpectSymbol(Symbol.Else)) if (TryExpectSymbol(Symbol.Else))
{ {
var newStartIndex = _index; var newStartIndex = _tokenIndex;
elseStatement = TryExpectSymbol(Symbol.If) elseStatement = TryExpectSymbol(Symbol.If)
? (Variant<IfNode, BlockNode>)ParseIf(newStartIndex) ? (Variant<IfNode, BlockNode>)ParseIf(newStartIndex)
: (Variant<IfNode, BlockNode>)ParseBlock(); : (Variant<IfNode, BlockNode>)ParseBlock();
@@ -371,7 +373,7 @@ public static class Parser
return new IfNode(GetTokensForNode(startIndex), condition, body, elseStatement); return new IfNode(GetTokensForNode(startIndex), condition, body, elseStatement);
} }
private static WhileNode ParseWhile(int startIndex) private WhileNode ParseWhile(int startIndex)
{ {
ExpectSymbol(Symbol.While); ExpectSymbol(Symbol.While);
var condition = ParseExpression(); var condition = ParseExpression();
@@ -379,9 +381,9 @@ public static class Parser
return new WhileNode(GetTokensForNode(startIndex), condition, body); return new WhileNode(GetTokensForNode(startIndex), condition, body);
} }
private static ExpressionNode ParseExpression(int precedence = 0) private ExpressionNode ParseExpression(int precedence = 0)
{ {
var startIndex = _index; var startIndex = _tokenIndex;
var left = ParsePrimaryExpression(); var left = ParsePrimaryExpression();
while (true) while (true)
@@ -402,7 +404,7 @@ public static class Parser
return left; return left;
} }
private static int GetBinaryOperatorPrecedence(BinaryExpressionOperator binaryExpressionOperator) private int GetBinaryOperatorPrecedence(BinaryExpressionOperator binaryExpressionOperator)
{ {
return binaryExpressionOperator switch return binaryExpressionOperator switch
{ {
@@ -420,7 +422,7 @@ public static class Parser
}; };
} }
private static bool TryGetBinaryOperator(Symbol symbol, [NotNullWhen(true)] out BinaryExpressionOperator? binaryExpressionOperator) private bool TryGetBinaryOperator(Symbol symbol, [NotNullWhen(true)] out BinaryExpressionOperator? binaryExpressionOperator)
{ {
switch (symbol) switch (symbol)
{ {
@@ -460,9 +462,9 @@ public static class Parser
} }
} }
private static ExpressionNode ParsePrimaryExpression() private ExpressionNode ParsePrimaryExpression()
{ {
var startIndex = _index; var startIndex = _tokenIndex;
ExpressionNode expr; ExpressionNode expr;
var token = ExpectToken(); var token = ExpectToken();
@@ -583,7 +585,7 @@ public static class Parser
return ParsePostfixOperators(startIndex, expr); return ParsePostfixOperators(startIndex, expr);
} }
private static ExpressionNode ParsePostfixOperators(int startIndex, ExpressionNode expr) private ExpressionNode ParsePostfixOperators(int startIndex, ExpressionNode expr)
{ {
while (true) while (true)
{ {
@@ -640,9 +642,9 @@ public static class Parser
return expr; return expr;
} }
private static BlockNode ParseBlock() private BlockNode ParseBlock()
{ {
var startIndex = _index; var startIndex = _tokenIndex;
ExpectSymbol(Symbol.OpenBrace); ExpectSymbol(Symbol.OpenBrace);
List<StatementNode> statements = []; List<StatementNode> statements = [];
while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace)) while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace))
@@ -661,7 +663,7 @@ public static class Parser
return new BlockNode(GetTokensForNode(startIndex), statements); return new BlockNode(GetTokensForNode(startIndex), statements);
} }
private static NubType ParseType() private NubType ParseType()
{ {
if (TryExpectIdentifier(out var name)) if (TryExpectIdentifier(out var name))
{ {
@@ -746,7 +748,7 @@ public static class Parser
.Build()); .Build());
} }
private static Token ExpectToken() private Token ExpectToken()
{ {
if (!Peek().TryGetValue(out var token)) if (!Peek().TryGetValue(out var token))
{ {
@@ -761,7 +763,7 @@ public static class Parser
return token; return token;
} }
private static SymbolToken ExpectSymbol() private SymbolToken ExpectSymbol()
{ {
var token = ExpectToken(); var token = ExpectToken();
if (token is not SymbolToken symbol) if (token is not SymbolToken symbol)
@@ -776,7 +778,7 @@ public static class Parser
return symbol; return symbol;
} }
private static void ExpectSymbol(Symbol expectedSymbol) private void ExpectSymbol(Symbol expectedSymbol)
{ {
var token = ExpectSymbol(); var token = ExpectSymbol();
if (token.Symbol != expectedSymbol) if (token.Symbol != expectedSymbol)
@@ -789,7 +791,7 @@ public static class Parser
} }
} }
private static bool TryExpectSymbol(Symbol symbol) private bool TryExpectSymbol(Symbol symbol)
{ {
if (Peek() is { Value: SymbolToken symbolToken } && symbolToken.Symbol == symbol) if (Peek() is { Value: SymbolToken symbolToken } && symbolToken.Symbol == symbol)
{ {
@@ -800,7 +802,7 @@ public static class Parser
return false; return false;
} }
private static bool TryExpectModifier([NotNullWhen(true)] out ModifierToken? modifier) private bool TryExpectModifier([NotNullWhen(true)] out ModifierToken? modifier)
{ {
if (Peek() is { Value: ModifierToken modifierToken }) if (Peek() is { Value: ModifierToken modifierToken })
{ {
@@ -813,7 +815,7 @@ public static class Parser
return false; return false;
} }
private static bool TryExpectIdentifier([NotNullWhen(true)] out IdentifierToken? identifier) private bool TryExpectIdentifier([NotNullWhen(true)] out IdentifierToken? identifier)
{ {
if (Peek() is { Value: IdentifierToken identifierToken }) if (Peek() is { Value: IdentifierToken identifierToken })
{ {
@@ -826,7 +828,7 @@ public static class Parser
return false; return false;
} }
private static IdentifierToken ExpectIdentifier() private IdentifierToken ExpectIdentifier()
{ {
var token = ExpectToken(); var token = ExpectToken();
if (token is not IdentifierToken identifier) if (token is not IdentifierToken identifier)
@@ -841,12 +843,12 @@ public static class Parser
return identifier; return identifier;
} }
private static void RecoverToNextDefinition() private void RecoverToNextDefinition()
{ {
while (Peek().HasValue) while (Peek().HasValue)
{ {
var token = Peek().Value; var token = Peek().Value;
if (token is SymbolToken { Symbol: Symbol.Func or Symbol.Struct } or ModifierToken) if (token is SymbolToken { Symbol: Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl } or ModifierToken)
{ {
break; break;
} }
@@ -855,7 +857,7 @@ public static class Parser
} }
} }
private static void RecoverToNextStatement() private void RecoverToNextStatement()
{ {
while (Peek().TryGetValue(out var token)) while (Peek().TryGetValue(out var token))
{ {
@@ -871,9 +873,9 @@ public static class Parser
} }
} }
private static Optional<Token> Peek(int offset = 0) private Optional<Token> Peek(int offset = 0)
{ {
var peekIndex = _index + offset; var peekIndex = _tokenIndex + offset;
if (peekIndex < _tokens.Count()) if (peekIndex < _tokens.Count())
{ {
return _tokens.ElementAt(peekIndex); return _tokens.ElementAt(peekIndex);
@@ -882,14 +884,14 @@ public static class Parser
return Optional<Token>.Empty(); return Optional<Token>.Empty();
} }
private static void Next() private void Next()
{ {
_index++; _tokenIndex++;
} }
private static IEnumerable<Token> GetTokensForNode(int startIndex) private IEnumerable<Token> GetTokensForNode(int startIndex)
{ {
return _tokens.Skip(startIndex).Take(Math.Min(_index, _tokens.Count() - 1) - startIndex); return _tokens.Skip(startIndex).Take(Math.Min(_tokenIndex, _tokens.Count() - 1) - startIndex);
} }
} }