From e195731b9e61cf158d75214420f69af1386124c3 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 5 Jul 2025 18:08:59 +0200 Subject: [PATCH] ... --- src/compiler/CLI/Program.cs | 28 +- src/compiler/Common/Optional.cs | 15 +- src/compiler/Generation/QBE/QBEGenerator.cs | 160 ++++++----- src/compiler/Syntax/Binding/Binder.cs | 284 ++++++++++++-------- src/compiler/Syntax/DefinitionTable.cs | 56 +++- src/compiler/Syntax/Node/Definition.cs | 4 +- src/compiler/Syntax/Node/Statement.cs | 4 +- src/compiler/Syntax/Node/SyntaxTree.cs | 8 +- src/compiler/Syntax/Parsing/Parser.cs | 150 ++++++----- 9 files changed, 413 insertions(+), 296 deletions(-) diff --git a/src/compiler/CLI/Program.cs b/src/compiler/CLI/Program.cs index 262a52b..a5c6ee6 100644 --- a/src/compiler/CLI/Program.cs +++ b/src/compiler/CLI/Program.cs @@ -2,7 +2,6 @@ using CLI; using Generation.QBE; using Syntax; -using Syntax.Binding; using Syntax.Diagnostics; using Syntax.Node; using Syntax.Parsing; @@ -83,13 +82,11 @@ foreach (var file in options.Files) var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics); diagnostics.AddRange(tokenizerDiagnostics); - var syntaxTree = Parser.ParseFile(tokenizeResult, out var parseDiagnostics); - diagnostics.AddRange(parseDiagnostics); + var parser = new Parser(tokenizeResult); + var syntaxTree = parser.Parse(); + diagnostics.AddRange(syntaxTree.Diagnostics); - if (syntaxTree != null) - { - syntaxTrees[file] = syntaxTree; - } + syntaxTrees[file] = syntaxTree; } var definitionTable = new DefinitionTable(syntaxTrees.Values); @@ -98,13 +95,12 @@ var boundSyntaxTrees = new Dictionary(); foreach (var (file, syntaxTree) in syntaxTrees) { - var boundSyntaxTree = Binder.Bind(syntaxTree, definitionTable, out var binderDiagnostics); - diagnostics.AddRange(binderDiagnostics); + var binder = new Binder(syntaxTree, definitionTable); + var boundSyntaxTree = binder.Bind(); + diagnostics.AddRange(boundSyntaxTree.Diagnostics); boundSyntaxTrees[file] = boundSyntaxTree; } -var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values); - foreach (var diagnostic in diagnostics) { Console.Error.WriteLine(diagnostic.FormatANSI()); @@ -115,6 +111,8 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro return 1; } +var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees.Values); + var objectFiles = new List(); foreach (var file in options.Files) @@ -124,7 +122,7 @@ foreach (var file in options.Files) var ssa = QBEGenerator.Emit(boundSyntaxTrees[file], boundDefinitionTable, file); // File.WriteAllText(Path.Join(INT_DEBUG_DIR, $"{outFileName}.ssa"), ssa); File.WriteAllText(Path.Join(INT_DEBUG_DIR, $"{Path.GetFileNameWithoutExtension(file)}.ssa"), ssa); - + var asm = await QBE.Invoke(ssa); if (asm == null) { @@ -162,7 +160,7 @@ else Console.Error.WriteLine($"file '{options.CustomRuntime}' does not exist'"); return 1; } - + objectFiles.Add(options.CustomRuntime); } @@ -195,7 +193,7 @@ async Task CreateBuiltinRuntime() var runtime = resources.First(r => r.EndsWith(RUNTIME_NAME)); await using var reader = Assembly.GetExecutingAssembly().GetManifestResourceStream(runtime); - + if (reader == null) { throw new RuntimeCreationException($"Cannot open stream to '{RUNTIME_NAME}'"); @@ -205,7 +203,7 @@ async Task CreateBuiltinRuntime() await using var writer = new FileStream(runtimePath, FileMode.Create); reader.CopyTo(writer); - + return runtimePath; } diff --git a/src/compiler/Common/Optional.cs b/src/compiler/Common/Optional.cs index 5cd9f29..c67d4bc 100644 --- a/src/compiler/Common/Optional.cs +++ b/src/compiler/Common/Optional.cs @@ -2,20 +2,25 @@ namespace Common; -public readonly struct Optional +public static class Optional { public static Optional Empty() => new(); /// - /// Alias for creating an Optional<TValue> which allows for implicit types + /// Alias for creating an Optional which allows for implicit types /// - /// - /// - /// public static Optional OfNullable(TValue? value) { return value ?? Optional.Empty(); } + + /// + /// Converts a nullable type to an Optional + /// + public static Optional ToOptional(this TValue? value) + { + return OfNullable(value); + } } public readonly struct Optional diff --git a/src/compiler/Generation/QBE/QBEGenerator.cs b/src/compiler/Generation/QBE/QBEGenerator.cs index 3604451..55d8864 100644 --- a/src/compiler/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/Generation/QBE/QBEGenerator.cs @@ -53,21 +53,21 @@ public static class QBEGenerator _implFuncNameIndex = 0; _codeIsReachable = true; - foreach (var structDef in _definitionTable.GetStructs()) - { - EmitStructDefinition(structDef); - _writer.NewLine(); - } - - foreach (var trait in _definitionTable.GetTraits()) - { - EmitTraitVTable(trait); - _writer.NewLine(); - } + // foreach (var structDef in _definitionTable.GetStructs()) + // { + // EmitStructDefinition(structDef); + // _writer.NewLine(); + // } + // + // foreach (var trait in _definitionTable.GetTraits()) + // { + // EmitTraitVTable(trait); + // _writer.NewLine(); + // } foreach (var funcDef in _syntaxTree.TopLevelNodes.OfType()) { - 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(); } @@ -117,16 +117,14 @@ public static class QBEGenerator return $"$string{++_stringLiteralIndex}"; } - private static string FuncName(BoundFuncDefinition funcDef) + private static string LocalFuncName(BoundLocalFuncNode funcDef) { - return funcDef switch - { - BoundExternFuncNode externFuncDefinition => $"${externFuncDefinition.CallName}", - BoundLocalFuncNode localFuncDefinition => localFuncDefinition.Exported - ? $"${localFuncDefinition.Name}" - : $"${localFuncDefinition.Namespace}_{localFuncDefinition.Name}", - _ => throw new ArgumentOutOfRangeException(nameof(funcDef)) - }; + return funcDef.Exported ? $"${funcDef.Name}" : $"${funcDef.Namespace}_{funcDef.Name}"; + } + + private static string ExternFuncName(BoundExternFuncNode funcDef) + { + return $"${funcDef.CallName}"; } private static string ImplFuncName(BoundTraitImplNode implDef, string funcName) @@ -586,65 +584,65 @@ public static class QBEGenerator _writer.EndFunction(); } - private static void EmitStructDefinition(BoundStructNode structDef) - { - var structType = new NubCustomType(structDef.Namespace, structDef.Name); - _writer.WriteLine($"type {CustomTypeName(structType)} = {{ "); - - var types = new Dictionary(); - - foreach (var field in structDef.Fields) - { - types.Add(field.Name, StructDefQBEType(field)); - } - - var longest = types.Values.Max(x => x.Length); - foreach (var (name, type) in types) - { - var padding = longest - type.Length; - _writer.Indented($"{type},{new string(' ', padding)} # {name}"); - } - - _writer.WriteLine("}"); - return; - - string StructDefQBEType(BoundStructFieldNode field) - { - return field.Type switch - { - NubCustomType customType => CustomTypeName(customType), - NubComplexType => "l", - NubSimpleType simpleType => simpleType switch - { - NubPointerType or NubFuncType => "l", - NubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "h", - PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "b", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - _ => throw new ArgumentOutOfRangeException() - }, - _ => throw new NotSupportedException($"'{field.Type}' type cannot be used in structs") - }, - _ => throw new UnreachableException() - }; - } - } - - private static void EmitTraitVTable(BoundTraitNode traitDef) - { - _writer.WriteLine($"type {CustomTypeName(new NubCustomType(traitDef.Namespace, traitDef.Name))} = {{"); - - 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.WriteLine("}"); - } + // private static void EmitStructDefinition(BoundStructNode structDef) + // { + // var structType = new NubCustomType(structDef.Namespace, structDef.Name); + // _writer.WriteLine($"type {CustomTypeName(structType)} = {{ "); + // + // var types = new Dictionary(); + // + // foreach (var field in structDef.Fields) + // { + // types.Add(field.Name, StructDefQBEType(field)); + // } + // + // var longest = types.Values.Max(x => x.Length); + // foreach (var (name, type) in types) + // { + // var padding = longest - type.Length; + // _writer.Indented($"{type},{new string(' ', padding)} # {name}"); + // } + // + // _writer.WriteLine("}"); + // return; + // + // string StructDefQBEType(BoundStructFieldNode field) + // { + // return field.Type switch + // { + // NubCustomType customType => CustomTypeName(customType), + // NubComplexType => "l", + // NubSimpleType simpleType => simpleType switch + // { + // NubPointerType or NubFuncType => "l", + // NubPrimitiveType primitiveType => primitiveType.Kind switch + // { + // PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", + // PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", + // PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "h", + // PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "b", + // PrimitiveTypeKind.F64 => "d", + // PrimitiveTypeKind.F32 => "s", + // _ => throw new ArgumentOutOfRangeException() + // }, + // _ => throw new NotSupportedException($"'{field.Type}' type cannot be used in structs") + // }, + // _ => throw new UnreachableException() + // }; + // } + // } + // + // private static void EmitTraitVTable(BoundTraitNode traitDef) + // { + // _writer.WriteLine($"type {CustomTypeName(new NubCustomType(traitDef.Namespace, traitDef.Name))} = {{"); + // + // 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.WriteLine("}"); + // } private static void EmitStatement(BoundStatementNode statement) { @@ -683,7 +681,7 @@ public static class QBEGenerator private static void EmitAssignment(BoundAssignmentNode assignment) { - var destination = EmitExpression(assignment.Expression); + var destination = EmitExpression(assignment.Target); Debug.Assert(destination.Kind == ValKind.Pointer); EmitCopyIntoOrInitialize(assignment.Value, destination.Name); } diff --git a/src/compiler/Syntax/Binding/Binder.cs b/src/compiler/Syntax/Binding/Binder.cs index 636968d..fd50575 100644 --- a/src/compiler/Syntax/Binding/Binder.cs +++ b/src/compiler/Syntax/Binding/Binder.cs @@ -7,34 +7,45 @@ using UnaryExpressionNode = Syntax.Node.UnaryExpressionNode; namespace Syntax.Binding; // TODO: Currently anonymous function does not get a new scope -public static class Binder +public sealed class Binder { - private static SyntaxTree _syntaxTree = null!; - private static DefinitionTable _definitionTable = null!; + private readonly SyntaxTree _syntaxTree; + private readonly DefinitionTable _definitionTable; - private static Dictionary _variables = new(); - private static NubType? _funcReturnType; + // TODO: Implement proper variable tracking and scoping + private Dictionary _variables = new(); + private NubType? _functionReturnType; - public static BoundSyntaxTree Bind(SyntaxTree syntaxTree, DefinitionTable definitionTable, out IEnumerable diagnostics) + public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable) { _syntaxTree = syntaxTree; _definitionTable = definitionTable; - - _variables = []; - _funcReturnType = null; - - var definitions = new List(); - - foreach (var topLevel in syntaxTree.TopLevelNodes) - { - definitions.Add(BindTopLevel(topLevel)); - } - - diagnostics = []; - return new BoundSyntaxTree(syntaxTree.Namespace, definitions); } - private static BoundTopLevelNode BindTopLevel(TopLevelNode node) + public BoundSyntaxTree Bind() + { + _variables = []; + _functionReturnType = null; + + var diagnostics = new List(); + var topLevelNodes = new List(); + + foreach (var topLevel in _syntaxTree.TopLevelNodes) + { + try + { + topLevelNodes.Add(BindTopLevel(topLevel)); + } + catch (BindException e) + { + diagnostics.Add(e.Diagnostic); + } + } + + return new BoundSyntaxTree(_syntaxTree.Namespace, topLevelNodes, diagnostics); + } + + private BoundTopLevelNode BindTopLevel(TopLevelNode node) { return node switch { @@ -47,7 +58,7 @@ public static class Binder }; } - private static BoundTraitImplNode BindTraitImplementation(TraitImplNode node) + private BoundTraitImplNode BindTraitImplementation(TraitImplNode node) { _variables.Clear(); var functions = new List(); @@ -65,7 +76,7 @@ public static class Binder 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(); @@ -77,46 +88,34 @@ public static class Binder 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(); - foreach (var structField in node.Fields) + foreach (var field in node.Fields) { var value = Optional.Empty(); - if (structField.Value.HasValue) + if (field.Value.HasValue) { - var definitionField = definition.Fields.FirstOrDefault(f => f.Name == structField.Name); - if (definitionField == null) - { - throw new NotImplementedException("Diagnostics not implemented"); - } - - value = BindExpression(structField.Value.Value, definitionField.Type); + value = BindExpression(field.Value.Value, field.Type); } - structFields.Add(new BoundStructFieldNode(structField.Tokens, structField.Name, structField.Type, value)); + structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, field.Type, value)); } 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); } - private static BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) + private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) { _variables.Clear(); - _funcReturnType = node.ReturnType; + _functionReturnType = node.ReturnType; 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); } - private static BoundBlock BindBlock(BlockNode node) + private BoundBlock BindBlock(BlockNode node) { var statements = new List(); @@ -140,7 +139,7 @@ public static class Binder return new BoundBlock(node.Tokens, statements); } - private static BoundStatementNode BindStatement(StatementNode node) + private BoundStatementNode BindStatement(StatementNode node) { 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); return new BoundAssignmentNode(statement.Tokens, expression, value); } - private static BoundBreakNode BindBreak(BreakNode statement) + private BoundBreakNode BindBreak(BreakNode statement) { return new BoundBreakNode(statement.Tokens); } - private static BoundContinueNode BindContinue(ContinueNode statement) + private BoundContinueNode BindContinue(ContinueNode statement) { return new BoundContinueNode(statement.Tokens); } - private static BoundIfNode BindIf(IfNode statement) + private BoundIfNode BindIf(IfNode statement) { var elseStatement = Optional.Empty>(); @@ -189,24 +188,24 @@ public static class Binder 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(); if (statement.Value.HasValue) { - value = BindExpression(statement.Value.Value, _funcReturnType); + value = BindExpression(statement.Value.Value, _functionReturnType); } 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)); } - private static BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) + private BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) { NubType? type = null; @@ -233,12 +232,12 @@ public static class Binder 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)); } - private static BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) + private BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) { 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); 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(); @@ -273,33 +272,33 @@ public static class Binder 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 elementType = ((NubArrayType)boundArray.Type).ElementType; 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); } - private static BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) + private BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) { var boundLeft = BindExpression(expression.Left); var boundRight = BindExpression(expression.Right, boundLeft.Type); 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 dereferencedType = ((NubPointerType)boundExpression.Type).BaseType; return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression); } - private static BoundFuncCallNode BindFuncCall(FuncCallNode expression) + private BoundFuncCallNode BindFuncCall(FuncCallNode expression) { var boundExpression = BindExpression(expression.Expression); @@ -323,30 +322,45 @@ public static class Binder return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters); } - private static BoundIdentifierNode BindIdentifier(IdentifierNode expression) + private BoundIdentifierNode BindIdentifier(IdentifierNode expression) { - NubType? type = null; - - var definition = _definitionTable.LookupFunction(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name); - if (definition.HasValue) + var localFuncs = _definitionTable.LookupLocalFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray(); + if (localFuncs.Length > 0) { - 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()); + } + + var localFunc = localFuncs[0]; + + var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList()); + return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); } - if (type == null && !expression.Namespace.HasValue) + var externFuncs = _definitionTable.LookupExternFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray(); + if (externFuncs.Length > 0) { - type = _variables[expression.Name]; + 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 (type == null) + if (!expression.Namespace.HasValue) { - throw new NotImplementedException("Diagnostics not implemented"); + return new BoundIdentifierNode(expression.Tokens, _variables[expression.Name], expression.Namespace, expression.Name); } - return new BoundIdentifierNode(expression.Tokens, type, 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 static BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) + private BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) { var type = expectedType ?? expression.Kind switch { @@ -360,81 +374,129 @@ public static class Binder 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 implementation = _definitionTable.LookupTraitImplementationForType(boundExpression.Type, expression.Member); - if (implementation.HasValue) + var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray(); + + 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); } if (boundExpression.Type is NubCustomType customType) { - var function = _definitionTable.LookupFunctionOnTrait(customType.Namespace, customType.Name, expression.Member); - if (function.HasValue) + var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray(); + if (traits.Length > 0) { - var type = new NubFuncType(function.Value.ReturnType, function.Value.Parameters.Select(p => p.Type).ToList()); - 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) + if (traits.Length > 1) { - throw new NotImplementedException("Diagnostics not implemented"); + throw new BindException(Diagnostic.Error($"Trait {customType.Namespace}::{customType.Name} has multiple definitions").Build()); } - if (matchingFields.Count == 1) + var trait = traits[0]; + + var traitFuncs = _definitionTable.LookupTraitFunc(trait, expression.Member).ToArray(); + if (traits.Length > 0) { - return new BoundMemberAccessNode(expression.Tokens, matchingFields[0].Type, boundExpression, expression.Member); + 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); + } + } + + var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray(); + if (structs.Length > 0) + { + 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") { - 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) { - 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); - if (!defOpt.TryGetValue(out var definition)) + var structs = _definitionTable.LookupStruct(structType.Namespace, structType.Name).ToArray(); + + 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(); - foreach (var (member, initializer) in expression.Initializers) + foreach (var (field, initializer) in expression.Initializers) { - var definitionField = definition.Fields.FirstOrDefault(x => x.Name == member); - if (definitionField == null) + var fields = _definitionTable.LookupStructField(@struct, field).ToArray(); + + 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); } - private static BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression) + private BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression) { var boundOperand = BindExpression(expression.Operand); @@ -469,4 +531,14 @@ public static class Binder 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; + } } \ No newline at end of file diff --git a/src/compiler/Syntax/DefinitionTable.cs b/src/compiler/Syntax/DefinitionTable.cs index ca84082..c2f3bac 100644 --- a/src/compiler/Syntax/DefinitionTable.cs +++ b/src/compiler/Syntax/DefinitionTable.cs @@ -2,7 +2,7 @@ using Syntax.Node; namespace Syntax; -public class DefinitionTable +public sealed class DefinitionTable { private readonly List _topLevelNodes; @@ -10,14 +10,54 @@ public class DefinitionTable { _topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList(); } -} -public class BoundDefinitionTable -{ - private readonly List _topLevelNodes; - - public BoundDefinitionTable(IEnumerable syntaxTrees) + public IEnumerable LookupLocalFunc(string @namespace, string name) { - _topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList(); + return _topLevelNodes + .OfType() + .Where(x => x.Namespace == @namespace && x.Name == name); + } + + public IEnumerable LookupExternFunc(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .Where(x => x.Namespace == @namespace && x.Name == name); + } + + public IEnumerable LookupStruct(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .Where(x => x.Namespace == @namespace && x.Name == name); + } + + public IEnumerable LookupStructField(StructNode structNode, string field) + { + return structNode.Fields.Where(x => x.Name == field); + } + + public IEnumerable LookupTraitImpl(NubType itemType) + { + return _topLevelNodes + .OfType() + .Where(x => x.TraitType == itemType); + } + + public IEnumerable LookupTraitFuncImpl(TraitImplNode traitImpl, string name) + { + return traitImpl.Functions.Where(x => x.Name == name); + } + + public IEnumerable LookupTrait(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .Where(x => x.Namespace == @namespace && x.Name == name); + } + + public IEnumerable LookupTraitFunc(TraitNode trait, string name) + { + return trait.Functions.Where(x => x.Name == name); } } \ No newline at end of file diff --git a/src/compiler/Syntax/Node/Definition.cs b/src/compiler/Syntax/Node/Definition.cs index 19c3e1e..8ef707d 100644 --- a/src/compiler/Syntax/Node/Definition.cs +++ b/src/compiler/Syntax/Node/Definition.cs @@ -17,10 +17,10 @@ public record BoundLocalFuncNode(IEnumerable Tokens, string Namespace, st public record ExternFuncNode(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace); public record BoundExternFuncNode(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : BoundTopLevelNode(Tokens, Namespace); -public record StructFieldNode(IEnumerable Tokens, string Name, NubType Type, Optional Value) : DefinitionNode(Tokens); +public record StructFieldNode(IEnumerable Tokens, int Index, string Name, NubType Type, Optional Value) : DefinitionNode(Tokens); public record StructNode(IEnumerable Tokens, string Namespace, string Name, List Fields) : TopLevelNode(Tokens, Namespace); -public record BoundStructFieldNode(IEnumerable Tokens, string Name, NubType Type, Optional Value) : BoundDefinitionNode(Tokens); +public record BoundStructFieldNode(IEnumerable Tokens, int Index, string Name, NubType Type, Optional Value) : BoundDefinitionNode(Tokens); public record BoundStructNode(IEnumerable Tokens, string Namespace, string Name, List Fields) : BoundTopLevelNode(Tokens, Namespace); public record TraitFuncNode(IEnumerable Tokens, string Name, List Parameters, NubType ReturnType) : DefinitionNode(Tokens); diff --git a/src/compiler/Syntax/Node/Statement.cs b/src/compiler/Syntax/Node/Statement.cs index c967fdc..250a294 100644 --- a/src/compiler/Syntax/Node/Statement.cs +++ b/src/compiler/Syntax/Node/Statement.cs @@ -13,8 +13,8 @@ public record BoundStatementExpressionNode(IEnumerable Tokens, BoundExpre public record ReturnNode(IEnumerable Tokens, Optional Value) : StatementNode(Tokens); public record BoundReturnNode(IEnumerable Tokens, Optional Value) : BoundStatementNode(Tokens); -public record AssignmentNode(IEnumerable Tokens, ExpressionNode Expression, ExpressionNode Value) : StatementNode(Tokens); -public record BoundAssignmentNode(IEnumerable Tokens, BoundExpressionNode Expression, BoundExpressionNode Value) : BoundStatementNode(Tokens); +public record AssignmentNode(IEnumerable Tokens, ExpressionNode Target, ExpressionNode Value) : StatementNode(Tokens); +public record BoundAssignmentNode(IEnumerable Tokens, BoundExpressionNode Target, BoundExpressionNode Value) : BoundStatementNode(Tokens); public record IfNode(IEnumerable Tokens, ExpressionNode Condition, BlockNode Body, Optional> Else) : StatementNode(Tokens); public record BoundIfNode(IEnumerable Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional> Else) : BoundStatementNode(Tokens); diff --git a/src/compiler/Syntax/Node/SyntaxTree.cs b/src/compiler/Syntax/Node/SyntaxTree.cs index d965c6c..b7acb68 100644 --- a/src/compiler/Syntax/Node/SyntaxTree.cs +++ b/src/compiler/Syntax/Node/SyntaxTree.cs @@ -1,4 +1,6 @@ -namespace Syntax.Node; +using Syntax.Diagnostics; -public record SyntaxTree(string Namespace, List TopLevelNodes); -public record BoundSyntaxTree(string Namespace, List TopLevelNodes); +namespace Syntax.Node; + +public record SyntaxTree(string Namespace, IEnumerable TopLevelNodes, IEnumerable Diagnostics); +public record BoundSyntaxTree(string Namespace, IEnumerable TopLevelNodes, IEnumerable Diagnostics); \ No newline at end of file diff --git a/src/compiler/Syntax/Parsing/Parser.cs b/src/compiler/Syntax/Parsing/Parser.cs index 07906c4..570528a 100644 --- a/src/compiler/Syntax/Parsing/Parser.cs +++ b/src/compiler/Syntax/Parsing/Parser.cs @@ -6,53 +6,53 @@ using Syntax.Tokenization; namespace Syntax.Parsing; -public static class Parser +public sealed class Parser { - private static string _namespace = null!; - private static NubType? _functionReturnType; - private static List _diagnostics = []; - private static IEnumerable _tokens = []; - private static int _index; + private string _namespace; + private readonly IEnumerable _tokens; - public static SyntaxTree? ParseFile(IEnumerable tokens, out IEnumerable diagnostics) + private readonly List _diagnostics = []; + private NubType? _functionReturnType; + private int _tokenIndex; + + public Parser(IEnumerable tokens) { - _tokens = tokens; _namespace = "global"; - _diagnostics = []; - _index = 0; + _tokens = tokens; + } + + public SyntaxTree Parse() + { + _diagnostics.Clear(); _functionReturnType = null; + _tokenIndex = 0; if (TryExpectSymbol(Symbol.Namespace)) { _namespace = ExpectIdentifier().Value; } - try - { - List definitions = []; + List topLevelNodes = []; - while (Peek().HasValue) + while (Peek().HasValue) + { + try { - var definition = ParseDefinition(); - definitions.Add(definition); + topLevelNodes.Add(ParseTopLevel()); + } + catch (ParseException ex) + { + _diagnostics.Add(ex.Diagnostic); + RecoverToNextDefinition(); } - - diagnostics = _diagnostics; - return new SyntaxTree(_namespace, definitions); - } - catch (ParseException ex) - { - _diagnostics.Add(ex.Diagnostic); - RecoverToNextDefinition(); } - diagnostics = _diagnostics; - return null; + return new SyntaxTree(_namespace, topLevelNodes, _diagnostics); } - private static TopLevelNode ParseDefinition() + private TopLevelNode ParseTopLevel() { - var startIndex = _index; + var startIndex = _tokenIndex; List modifiers = []; while (TryExpectModifier(out var modifier)) @@ -86,7 +86,7 @@ public static class Parser return node; } - private static TopLevelNode ParseFunc(int startIndex, List modifiers) + private TopLevelNode ParseFunc(int startIndex, List modifiers) { var name = ExpectIdentifier(); List parameters = []; @@ -138,7 +138,7 @@ public static class Parser 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; @@ -146,10 +146,12 @@ public static class Parser List variables = []; + var fieldIndex = 0; + while (!TryExpectSymbol(Symbol.CloseBrace)) { - var fieldStartIndex = _index; - + var fieldStartIndex = _tokenIndex; + var variableName = ExpectIdentifier().Value; ExpectSymbol(Symbol.Colon); var variableType = ParseType(); @@ -161,13 +163,13 @@ public static class Parser 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); } - private static TraitNode ParseTrait(int startIndex) + private TraitNode ParseTrait(int startIndex) { var name = ExpectIdentifier().Value; @@ -177,7 +179,7 @@ public static class Parser while (!TryExpectSymbol(Symbol.CloseBrace)) { - var funcStartIndex = _index; + var funcStartIndex = _tokenIndex; ExpectSymbol(Symbol.Func); @@ -207,7 +209,7 @@ public static class Parser return new TraitNode(GetTokensForNode(startIndex), _namespace, name, functions); } - private static TraitImplNode ParseImplementation(int startIndex) + private TraitImplNode ParseImplementation(int startIndex) { var traitType = ParseType(); ExpectSymbol(Symbol.For); @@ -218,7 +220,7 @@ public static class Parser ExpectSymbol(Symbol.OpenBrace); while (!TryExpectSymbol(Symbol.CloseBrace)) { - var funcStartIndex = _index; + var funcStartIndex = _tokenIndex; ExpectSymbol(Symbol.Func); var functionName = ExpectIdentifier().Value; var parameters = new List @@ -252,7 +254,7 @@ public static class Parser return new TraitImplNode(GetTokensForNode(startIndex), _namespace, traitType, forType, functions); } - private static FuncParameter ParseFuncParameter() + private FuncParameter ParseFuncParameter() { var name = ExpectIdentifier(); ExpectSymbol(Symbol.Colon); @@ -261,9 +263,9 @@ public static class Parser 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)) { throw new ParseException(Diagnostic @@ -294,7 +296,7 @@ public static class Parser return ParseStatementExpression(startIndex); } - private static StatementNode ParseStatementExpression(int startIndex) + private StatementNode ParseStatementExpression(int startIndex) { var expr = ParseExpression(); @@ -307,7 +309,7 @@ public static class Parser return new StatementExpressionNode(GetTokensForNode(startIndex), expr); } - private static VariableDeclarationNode ParseVariableDeclaration(int startIndex) + private VariableDeclarationNode ParseVariableDeclaration(int startIndex) { ExpectSymbol(Symbol.Let); var name = ExpectIdentifier().Value; @@ -327,20 +329,20 @@ public static class Parser return new VariableDeclarationNode(GetTokensForNode(startIndex), name, explicitType, assignment); } - private static StatementNode ParseBreak(int startIndex) + private StatementNode ParseBreak(int startIndex) { ExpectSymbol(Symbol.Break); Next(); return new BreakNode(GetTokensForNode(startIndex)); } - private static StatementNode ParseContinue(int startIndex) + private StatementNode ParseContinue(int startIndex) { ExpectSymbol(Symbol.Continue); return new ContinueNode(GetTokensForNode(startIndex)); } - private static ReturnNode ParseReturn(int startIndex) + private ReturnNode ParseReturn(int startIndex) { ExpectSymbol(Symbol.Return); @@ -353,7 +355,7 @@ public static class Parser return new ReturnNode(GetTokensForNode(startIndex), value); } - private static IfNode ParseIf(int startIndex) + private IfNode ParseIf(int startIndex) { ExpectSymbol(Symbol.If); var condition = ParseExpression(); @@ -362,7 +364,7 @@ public static class Parser var elseStatement = Optional>.Empty(); if (TryExpectSymbol(Symbol.Else)) { - var newStartIndex = _index; + var newStartIndex = _tokenIndex; elseStatement = TryExpectSymbol(Symbol.If) ? (Variant)ParseIf(newStartIndex) : (Variant)ParseBlock(); @@ -371,7 +373,7 @@ public static class Parser return new IfNode(GetTokensForNode(startIndex), condition, body, elseStatement); } - private static WhileNode ParseWhile(int startIndex) + private WhileNode ParseWhile(int startIndex) { ExpectSymbol(Symbol.While); var condition = ParseExpression(); @@ -379,9 +381,9 @@ public static class Parser 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(); while (true) @@ -402,7 +404,7 @@ public static class Parser return left; } - private static int GetBinaryOperatorPrecedence(BinaryExpressionOperator binaryExpressionOperator) + private int GetBinaryOperatorPrecedence(BinaryExpressionOperator binaryExpressionOperator) { 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) { @@ -460,9 +462,9 @@ public static class Parser } } - private static ExpressionNode ParsePrimaryExpression() + private ExpressionNode ParsePrimaryExpression() { - var startIndex = _index; + var startIndex = _tokenIndex; ExpressionNode expr; var token = ExpectToken(); @@ -583,7 +585,7 @@ public static class Parser return ParsePostfixOperators(startIndex, expr); } - private static ExpressionNode ParsePostfixOperators(int startIndex, ExpressionNode expr) + private ExpressionNode ParsePostfixOperators(int startIndex, ExpressionNode expr) { while (true) { @@ -640,9 +642,9 @@ public static class Parser return expr; } - private static BlockNode ParseBlock() + private BlockNode ParseBlock() { - var startIndex = _index; + var startIndex = _tokenIndex; ExpectSymbol(Symbol.OpenBrace); List statements = []; while (Peek().HasValue && !TryExpectSymbol(Symbol.CloseBrace)) @@ -661,7 +663,7 @@ public static class Parser return new BlockNode(GetTokensForNode(startIndex), statements); } - private static NubType ParseType() + private NubType ParseType() { if (TryExpectIdentifier(out var name)) { @@ -746,7 +748,7 @@ public static class Parser .Build()); } - private static Token ExpectToken() + private Token ExpectToken() { if (!Peek().TryGetValue(out var token)) { @@ -761,7 +763,7 @@ public static class Parser return token; } - private static SymbolToken ExpectSymbol() + private SymbolToken ExpectSymbol() { var token = ExpectToken(); if (token is not SymbolToken symbol) @@ -776,7 +778,7 @@ public static class Parser return symbol; } - private static void ExpectSymbol(Symbol expectedSymbol) + private void ExpectSymbol(Symbol expectedSymbol) { var token = ExpectSymbol(); 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) { @@ -800,7 +802,7 @@ public static class Parser 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 }) { @@ -813,7 +815,7 @@ public static class Parser 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 }) { @@ -826,7 +828,7 @@ public static class Parser return false; } - private static IdentifierToken ExpectIdentifier() + private IdentifierToken ExpectIdentifier() { var token = ExpectToken(); if (token is not IdentifierToken identifier) @@ -841,12 +843,12 @@ public static class Parser return identifier; } - private static void RecoverToNextDefinition() + private void RecoverToNextDefinition() { while (Peek().HasValue) { 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; } @@ -855,7 +857,7 @@ public static class Parser } } - private static void RecoverToNextStatement() + private void RecoverToNextStatement() { while (Peek().TryGetValue(out var token)) { @@ -871,9 +873,9 @@ public static class Parser } } - private static Optional Peek(int offset = 0) + private Optional Peek(int offset = 0) { - var peekIndex = _index + offset; + var peekIndex = _tokenIndex + offset; if (peekIndex < _tokens.Count()) { return _tokens.ElementAt(peekIndex); @@ -882,14 +884,14 @@ public static class Parser return Optional.Empty(); } - private static void Next() + private void Next() { - _index++; + _tokenIndex++; } - private static IEnumerable GetTokensForNode(int startIndex) + private IEnumerable 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); } }