private PackageIL CompileStdLib(AdamantCompiler compiler) { try { var sourceDir = Path.Combine(SolutionDirectory.Get(), @"stdlib\src"); var sourcePaths = Directory.EnumerateFiles(sourceDir, "*.ad", SearchOption.AllDirectories); var rootNamespace = FixedList <string> .Empty; var codeFiles = sourcePaths.Select(p => LoadCode(p, sourceDir, rootNamespace)) .ToList(); return(compiler.CompilePackage("adamant.stdlib", codeFiles, FixedDictionary <Name, PackageIL> .Empty)); } catch (FatalCompilationErrorException ex) { testOutput.WriteLine("Std Lib Compiler Errors:"); foreach (var diagnostic in ex.Diagnostics) { testOutput.WriteLine( $"{diagnostic.File.Reference}:{diagnostic.StartPosition.Line}:{diagnostic.StartPosition.Column} {diagnostic.Level} {diagnostic.ErrorCode}"); testOutput.WriteLine(diagnostic.Message); } Assert.True(false, "Compilation errors in standard library"); throw new UnreachableCodeException(); } }
private static Package CompileStdLib(AdamantCompiler compiler) { var sourceDir = Path.Combine(SolutionDirectory.Get(), @"stdlib\src"); var sourcePaths = Directory.EnumerateFiles(sourceDir, "*.ad", SearchOption.AllDirectories); var rootNamespace = FixedList <string> .Empty; var codeFiles = sourcePaths.Select(p => LoadCode(p, sourceDir, rootNamespace)).ToList(); return(compiler.CompilePackage("adamant.stdlib", codeFiles, FixedDictionary <string, Package> .Empty)); }
private static async Task <Package> Build( AdamantCompiler compiler, Project project, Task <FixedDictionary <Project, Task <Package> > > projectBuildsTask, object consoleLock) { var projectBuilds = await projectBuildsTask; var sourceDir = Path.Combine(project.Path, "src"); var sourcePaths = Directory.EnumerateFiles(sourceDir, "*.ad", SearchOption.AllDirectories); // Wait for the references, unfortunately, this requires an ugly loop. var referenceTasks = project.References.ToDictionary(r => r.Name, r => projectBuilds[r.Project]); var references = new Dictionary <string, Package>(); foreach (var referenceTask in referenceTasks) { references.Add(referenceTask.Key, await referenceTask.Value); } lock (consoleLock) { Console.WriteLine($"Compiling {project.Name} ({project.Path})..."); } var codeFiles = sourcePaths.Select(p => LoadCode(p, sourceDir, project.RootNamespace)).ToList(); var package = compiler.CompilePackage(project.Name, codeFiles, references.ToFixedDictionary()); // TODO switch to the async version of the compiler //var codeFiles = sourcePaths.Select(p => new CodePath(p)).ToList(); //var references = project.References.ToDictionary(r => r.Name, r => projectBuilds[r.Project]); //var package = await compiler.CompilePackageAsync(project.Name, codeFiles, references); if (OutputDiagnostics(project, package, consoleLock)) { return(package); } var cacheDir = PrepareCacheDir(project); var codePath = EmitCode(project, package, cacheDir); var success = CompileCode(project, cacheDir, codePath, consoleLock); lock (consoleLock) { Console.WriteLine(success ? $"Build SUCCEEDED {project.Name} ({project.Path})" : $"Build FAILED {project.Name} ({project.Path})"); } return(package); }
public void Test_cases(TestCase testCase) { // Setup var codeFile = CodeFile.Load(testCase.FullCodePath); var code = codeFile.Code.Text; var compiler = new AdamantCompiler(); var references = new Dictionary <string, Package>(); // Reference Standard Library var stdLibPackage = CompileStdLib(compiler); references.Add("adamant.stdlib", stdLibPackage); // Analyze var package = compiler.CompilePackage("testPackage", codeFile.Yield(), references.ToFixedDictionary()); // Check for compiler errors var expectedCompileErrorLines = ExpectedCompileErrorLines(codeFile, code); Assert.NotNull(package.Diagnostics); var diagnostics = package.Diagnostics; if (diagnostics.Any()) { testOutput.WriteLine("Compiler Errors:"); foreach (var diagnostic in diagnostics) { testOutput.WriteLine($"{testCase.RelativeCodePath}:{diagnostic.StartPosition.Line}:{diagnostic.StartPosition.Column} {diagnostic.Level} {diagnostic.ErrorCode}"); testOutput.WriteLine(diagnostic.Message); } } var errorDiagnostics = diagnostics .Where(d => d.Level >= DiagnosticLevel.CompilationError).ToList(); if (expectedCompileErrorLines.Any()) { foreach (var expectedCompileErrorLine in expectedCompileErrorLines) { // Assert a single error on the given line var errorsOnLine = errorDiagnostics.Count(e => e.StartPosition.Line == expectedCompileErrorLine); Assert.True(errorsOnLine == 1, $"Expected single error on line {expectedCompileErrorLine}, found {errorsOnLine}"); } } foreach (var error in errorDiagnostics) { var errorLine = error.StartPosition.Line; if (expectedCompileErrorLines.All(line => line != errorLine)) { Assert.True(false, $"Unexpected error on line {error.StartPosition.Line}"); } } // We got only expected errors, but need to not go one to emit code if (errorDiagnostics.Any()) { return; } // Emit Code var codePath = Path.ChangeExtension(testCase.FullCodePath, "c"); EmitCode(package, stdLibPackage, codePath); // Compile Code to Executable var exePath = CompileToExecutable(codePath); // Execute and check results var process = Execute(exePath); process.WaitForExit(); var stdout = process.StandardOutput.ReadToEnd(); testOutput.WriteLine("stdout:"); testOutput.WriteLine(stdout); Assert.Equal(ExpectedOutput(code, "stdout"), stdout); var stderr = process.StandardError.ReadToEnd(); testOutput.WriteLine("stderr:"); testOutput.WriteLine(stderr); Assert.Equal(ExpectedOutput(code, "stderr"), stderr); Assert.Equal(ExpectedExitCode(code), process.ExitCode); }
public void Test_cases(TestCase testCase) { // Setup var codeFile = CodeFile.Load(testCase.FullCodePath); var code = codeFile.Code.Text; var compiler = new AdamantCompiler() { SaveLivenessAnalysis = true, SaveReachabilityGraphs = true, }; var references = new Dictionary <Name, PackageIL>(); // Reference Standard Library var stdLibPackage = CompileStdLib(compiler); references.Add("adamant.stdlib", stdLibPackage); try { // Analyze var package = compiler.CompilePackage("testPackage", codeFile.Yield(), references.ToFixedDictionary()); // Check for compiler errors Assert.NotNull(package.Diagnostics); var diagnostics = package.Diagnostics; var errorDiagnostics = CheckErrorsExpected(testCase, codeFile, code, diagnostics); // Disassemble var ilAssembler = new ILAssembler(); testOutput.WriteLine(ilAssembler.Disassemble(package)); // We got only expected errors, but need to not go on to emit code if (errorDiagnostics.Any()) { return; } // Emit Code var codePath = Path.ChangeExtension(testCase.FullCodePath, "c"); EmitCode(package, stdLibPackage, codePath); // Compile Code to Executable var exePath = CompileToExecutable(codePath); // Execute and check results var process = Execute(exePath); process.WaitForExit(); var stdout = process.StandardOutput.ReadToEnd(); testOutput.WriteLine("stdout:"); testOutput.WriteLine(stdout); Assert.Equal(ExpectedOutput(code, "stdout", testCase.FullCodePath), stdout); var stderr = process.StandardError.ReadToEnd(); testOutput.WriteLine("stderr:"); testOutput.WriteLine(stderr); Assert.Equal(ExpectedOutput(code, "stderr", testCase.FullCodePath), stderr); Assert.Equal(ExpectedExitCode(code), process.ExitCode); } catch (FatalCompilationErrorException ex) { var diagnostics = ex.Diagnostics; CheckErrorsExpected(testCase, codeFile, code, diagnostics); } }