diff --git a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundConditionalStatementTests.cs b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundConditionalStatementTests.cs index 74f96c6..cc63a04 100644 --- a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundConditionalStatementTests.cs +++ b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundConditionalStatementTests.cs @@ -114,11 +114,8 @@ void func() { } b = a + 5; }"; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + var func = TestUtils.BindMember(inputText); - var func = boundModule.EntryPointType.BoundMembers[0].As(); var conditionalStatement = func.Body.Statements[2].As(); var consequence = conditionalStatement.Consequence.As(); consequence.Scope.Parent.Should().Be(func.FunctionScope); diff --git a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionCallExpressionTests.cs b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionCallExpressionTests.cs index 8ad2962..61aadb8 100644 --- a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionCallExpressionTests.cs +++ b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionCallExpressionTests.cs @@ -90,9 +90,8 @@ void Main() { Console.WriteLine(); } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + + TestUtils.BindModule(inputText).Should().NotBeNull(); } [Fact] @@ -109,10 +108,8 @@ int Main() { return 0; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + TestUtils.BindModule(inputText).Should().NotBeNull(); } [Fact] @@ -129,10 +126,8 @@ int Main() { return 0; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + TestUtils.BindModule(inputText).Should().NotBeNull(); } [Fact] @@ -151,9 +146,7 @@ int Main() { return 0; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + TestUtils.BindModule(inputText).Should().NotBeNull(); } } diff --git a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionMemberTests.cs b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionMemberTests.cs index 449df9d..be409ed 100644 --- a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionMemberTests.cs +++ b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/BoundFunctionMemberTests.cs @@ -6,6 +6,7 @@ using Todl.Compiler.CodeAnalysis.Symbols; using Todl.Compiler.Diagnostics; using Xunit; +using Xunit.Sdk; namespace Todl.Compiler.Tests.CodeAnalysis; @@ -140,10 +141,8 @@ public void TestOverloadedFunctionDeclarationMember() int func() { return 20; } int func(int a) { return a; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - boundModule.GetDiagnostics().Should().BeEmpty(); + TestUtils.BindModule(inputText).Should().NotBeNull(); } [Theory] @@ -151,10 +150,10 @@ public void TestOverloadedFunctionDeclarationMember() [InlineData("void func(int a, string a) { }")] public void FunctionParametersShouldHaveDistinctNames(string inputText) { - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); + var diagnosticBuilder = new DiagnosticBag.Builder(); + TestUtils.BindModule(inputText, diagnosticBuilder).Should().NotBeNull(); - var diagnostics = boundModule.GetDiagnostics().ToList(); + var diagnostics = diagnosticBuilder.Build().ToList(); diagnostics.Should().NotBeEmpty(); diagnostics[0].ErrorCode.Should().Be(ErrorCode.DuplicateParameterName); } @@ -166,10 +165,11 @@ public void FunctionsWithSameArgumentsShouldBeAmbiguous() int func(int a, string b) { return b.Length + a; } int func(int a, string b) { return b.Length + a + 1; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - var diagnostics = boundModule.GetDiagnostics().ToList(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + TestUtils.BindModule(inputText, diagnosticBuilder).Should().NotBeNull(); + + var diagnostics = diagnosticBuilder.Build().ToList(); diagnostics.Count.Should().Be(1); diagnostics[0].ErrorCode.Should().Be(ErrorCode.AmbiguousFunctionDeclaration); } @@ -185,10 +185,11 @@ public void FunctionsWithSameArgumentsInDifferentOrderShouldBeAmbiguous() int func(int a, string b) { return b.Length + a; } int func(string b, int a) { return b.Length + a + 1; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - var diagnostics = boundModule.GetDiagnostics().ToList(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + TestUtils.BindModule(inputText, diagnosticBuilder).Should().NotBeNull(); + + var diagnostics = diagnosticBuilder.Build().ToList(); diagnostics.Count.Should().Be(1); diagnostics[0].ErrorCode.Should().Be(ErrorCode.AmbiguousFunctionDeclaration); } @@ -200,10 +201,11 @@ public void FunctionsWithSameArgumentsButDifferentNamesShouldBeAmbiguous() int func(int a, string b) { return b.Length + a; } int func(int b, string a) { return a.Length + b + 1; } "; - var syntaxTree = TestUtils.ParseSyntaxTree(inputText); - var boundModule = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - var diagnostics = boundModule.GetDiagnostics().ToList(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + TestUtils.BindModule(inputText, diagnosticBuilder).Should().NotBeNull(); + + var diagnostics = diagnosticBuilder.Build().ToList(); diagnostics.Count.Should().Be(1); diagnostics[0].ErrorCode.Should().Be(ErrorCode.AmbiguousFunctionDeclaration); } @@ -217,7 +219,6 @@ public void FunctionsThatReturnsVoidShouldNotHaveDuplicateReturnStatements(strin { var function = TestUtils.BindMember(inputText); function.Body.Statements.Should().NotBeEmpty(); - function.Body.Statements.OfType().Should().HaveCount(1); var lastStatement = function.Body.Statements[^1]; diff --git a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/ConstantFoldingTests.cs b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/ConstantFoldingTests.cs index e30c93b..9e694cb 100644 --- a/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/ConstantFoldingTests.cs +++ b/src/Todl.Compiler.Tests/CodeAnalysis/BinderTests/ConstantFoldingTests.cs @@ -4,6 +4,7 @@ using Todl.Compiler.CodeAnalysis.Binding.BoundTree; using Todl.Compiler.CodeAnalysis.Syntax; using Todl.Compiler.CodeAnalysis.Text; +using Todl.Compiler.Diagnostics; using Xunit; namespace Todl.Compiler.Tests.CodeAnalysis; @@ -30,9 +31,10 @@ public sealed class ConstantFoldingTests [InlineData("const a = ~10UL;", ~10UL)] public void ConstantFoldingUnaryOperatorTest(string inputText, object expectedValue) { - var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, new()); - var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - module.GetDiagnostics().Should().BeEmpty(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, diagnosticBuilder); + var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, [syntaxTree], diagnosticBuilder); + diagnosticBuilder.Build().Should().BeEmpty(); var variableMember = module.EntryPointType.Variables.ToList()[^1].As(); variableMember.BoundVariableDeclarationStatement.Variable.Constant.Should().Be(true); @@ -54,9 +56,10 @@ public void ConstantFoldingUnaryOperatorTest(string inputText, object expectedVa [InlineData("const a = -20;", -20)] public void BasicConstantFoldingTests(string inputText, object expectedValue) { - var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, new()); - var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - module.GetDiagnostics().Should().BeEmpty(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, diagnosticBuilder); + var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, [syntaxTree], diagnosticBuilder); + diagnosticBuilder.Build().Should().BeEmpty(); var variableMember = module.EntryPointType.Variables.ToList()[^1].As(); variableMember.BoundVariableDeclarationStatement.Variable.Constant.Should().Be(true); @@ -76,9 +79,10 @@ public void BasicConstantFoldingTests(string inputText, object expectedValue) [InlineData("const a = 10; let b = a + 10; const c = a + b;")] public void BasicConstantFoldingNegativeTests(string inputText) { - var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, new()); - var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - module.GetDiagnostics().Should().BeEmpty(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + var syntaxTree = SyntaxTree.Parse(SourceText.FromString(inputText), TestDefaults.DefaultClrTypeCache, diagnosticBuilder); + var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, [syntaxTree], diagnosticBuilder); + diagnosticBuilder.Build().Should().BeEmpty(); var variableMember = module.EntryPointType.Variables.ToList()[^1].As(); var boundVariableDeclarationStatement = variableMember.BoundVariableDeclarationStatement; @@ -88,9 +92,10 @@ public void BasicConstantFoldingNegativeTests(string inputText) [Fact] public void PartiallyFoldedConstantTests() { - var syntaxTree = SyntaxTree.Parse(SourceText.FromString("let a = 10 + 10;"), TestDefaults.DefaultClrTypeCache, new()); - var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, new[] { syntaxTree }); - module.GetDiagnostics().Should().BeEmpty(); + var diagnosticBuilder = new DiagnosticBag.Builder(); + var syntaxTree = SyntaxTree.Parse(SourceText.FromString("let a = 10 + 10;"), TestDefaults.DefaultClrTypeCache, diagnosticBuilder); + var module = BoundModule.Create(TestDefaults.DefaultClrTypeCache, [syntaxTree], diagnosticBuilder); + diagnosticBuilder.Build().Should().BeEmpty(); var statement = module.EntryPointType.Variables.ToList()[^1].As().BoundVariableDeclarationStatement; statement.Variable.Constant.Should().Be(false); diff --git a/src/Todl.Compiler.Tests/TestUtils.cs b/src/Todl.Compiler.Tests/TestUtils.cs index 4941ca7..528f3a9 100644 --- a/src/Todl.Compiler.Tests/TestUtils.cs +++ b/src/Todl.Compiler.Tests/TestUtils.cs @@ -6,6 +6,7 @@ using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; +using Todl.Compiler.CodeAnalysis.Binding; using Todl.Compiler.CodeAnalysis.Binding.BoundTree; using Todl.Compiler.CodeAnalysis.Symbols; using Todl.Compiler.CodeAnalysis.Syntax; @@ -78,6 +79,20 @@ internal static TBoundMember BindMember(string inputText) return boundMember; } + internal static BoundModule BindModule(string inputText, DiagnosticBag.Builder diagnosticBuilder) + { + var syntaxTree = ParseSyntaxTree(inputText, diagnosticBuilder); + return BoundModule.Create(TestDefaults.DefaultClrTypeCache, [syntaxTree], diagnosticBuilder); + } + + internal static BoundModule BindModule(string inputText) + { + var diagnosticBuilder = new DiagnosticBag.Builder(); + var boundModule = BindModule(inputText, diagnosticBuilder); + diagnosticBuilder.Build().Should().BeEmpty(); + return boundModule; + } + internal static void EmitExpressionAndVerify(string input, params TestInstruction[] expectedInstructions) { var diagnosticBuilder = new DiagnosticBag.Builder(); diff --git a/src/Todl.Compiler/CodeAnalysis/Binding/BoundModule.cs b/src/Todl.Compiler/CodeAnalysis/Binding/BoundModule.cs index 501a64f..62cf7e6 100644 --- a/src/Todl.Compiler/CodeAnalysis/Binding/BoundModule.cs +++ b/src/Todl.Compiler/CodeAnalysis/Binding/BoundModule.cs @@ -7,18 +7,13 @@ namespace Todl.Compiler.CodeAnalysis.Binding; -internal sealed class BoundModule : IDiagnosable +internal sealed class BoundModule { public IReadOnlyCollection SyntaxTrees { get; private init; } public BoundEntryPointTypeDefinition EntryPointType { get; private init; } public BoundFunctionMember EntryPoint => EntryPointType.EntryPointFunctionMember; public DiagnosticBag.Builder DiagnosticBuilder { get; private init; } - public static BoundModule Create( - ClrTypeCache clrTypeCache, - IReadOnlyList syntaxTrees) - => Create(clrTypeCache, syntaxTrees, new()); - public static BoundModule Create( ClrTypeCache clrTypeCache, IReadOnlyList syntaxTrees, @@ -48,7 +43,4 @@ public static BoundModule Create( DiagnosticBuilder = diagnosticBuilder }; } - - public IEnumerable GetDiagnostics() - => DiagnosticBuilder.Build(); } diff --git a/src/Todl.Compiler/CodeGeneration/Compilation.cs b/src/Todl.Compiler/CodeGeneration/Compilation.cs index 5275a24..7f0d6e2 100644 --- a/src/Todl.Compiler/CodeGeneration/Compilation.cs +++ b/src/Todl.Compiler/CodeGeneration/Compilation.cs @@ -51,7 +51,7 @@ public Compilation( ClrTypeCache = ClrTypeCache.FromAssemblies(metadataLoadContext.GetAssemblies(), metadataLoadContext.CoreAssembly); var syntaxTrees = sourceTexts.Select(s => SyntaxTree.Parse(s, ClrTypeCache, diagnosticBuilder)); - MainModule = BoundModule.Create(ClrTypeCache, syntaxTrees.ToImmutableList()); + MainModule = BoundModule.Create(ClrTypeCache, syntaxTrees.ToImmutableList(), diagnosticBuilder); if (MainModule.EntryPoint is null) { @@ -77,8 +77,5 @@ public void Dispose() } public IEnumerable GetDiagnostics() - { - diagnosticBuilder.Add(MainModule); - return diagnosticBuilder.Build(); - } + => diagnosticBuilder.Build(); }