From 492b812f942e26ada4649a07b32337e99d1e46d1 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Wed, 27 Sep 2023 12:02:29 -0700 Subject: [PATCH 1/4] Support multiple targets in .pproj Adds support for multiple targets in .pproj file using field Adds field in .pproj --- Src/PCompiler/CompilerCore/Compiler.cs | 59 +++++++----- .../CompilerCore/CompilerConfiguration.cs | 18 ++-- .../CompilerCore/ICompilerConfiguration.cs | 8 +- .../PCommandLine/Options/PCompilerOptions.cs | 35 ++++--- .../PCommandLine/Parser/ParsePProjectFile.cs | 96 ++++++++++++------- Tst/UnitTests/Core/TestCaseFactory.cs | 3 +- Tst/UnitTests/Runners/CompileOnlyRunner.cs | 10 +- Tst/UnitTests/Runners/PCheckerRunner.cs | 3 +- Tst/UnitTests/Runners/PrtRunner.cs | 3 +- 9 files changed, 144 insertions(+), 91 deletions(-) diff --git a/Src/PCompiler/CompilerCore/Compiler.cs b/Src/PCompiler/CompilerCore/Compiler.cs index 690dafbdc..1fe201ff5 100644 --- a/Src/PCompiler/CompilerCore/Compiler.cs +++ b/Src/PCompiler/CompilerCore/Compiler.cs @@ -53,38 +53,49 @@ public int Compile(ICompilerConfiguration job) IRTransformer.SimplifyMethod(fun); } - job.Output.WriteInfo($"Code generation ..."); - // Run the selected backend on the project and write the files. - var compiledFiles = job.Backend.GenerateCode(job, scope); - foreach (var file in compiledFiles) - { - job.Output.WriteInfo($"Generated {file.FileName}."); - job.Output.WriteFile(file); - } - - // Not every backend has a compilation stage following code generation. - // For those that do, execute that stage. - if (job.Backend.HasCompilationStage) + foreach (var entry in job.OutputLanguages) { + job.OutputDirectory = Directory.CreateDirectory(Path.Combine(job.OutputDirectory.FullName, entry.Key)); + job.Output = new DefaultCompilerOutput(job.OutputDirectory); + job.Backend = TargetLanguage.GetCodeGenerator(entry.Value); + job.Output.WriteInfo($"----------------------------------------"); - job.Output.WriteInfo($"Compiling {job.ProjectName}..."); - try + job.Output.WriteInfo($"Code generation for {entry.Key}..."); + + // Run the selected backend on the project and write the files. + var compiledFiles = job.Backend.GenerateCode(job, scope); + foreach (var file in compiledFiles) { - job.Backend.Compile(job); + job.Output.WriteInfo($"Generated {file.FileName}."); + job.Output.WriteFile(file); } - catch (TranslationException e) + + // Not every backend has a compilation stage following code generation. + // For those that do, execute that stage. + if (job.Backend.HasCompilationStage) { - job.Output.WriteError("[Compiling Generated Code:]\n" + e.Message); - job.Output.WriteError("[THIS SHOULD NOT HAVE HAPPENED, please report it to the P team or create a GitHub issue]\n" + e.Message); - Environment.ExitCode = 2; - return Environment.ExitCode; + job.Output.WriteInfo($"Compiling generated code..."); + try + { + job.Backend.Compile(job); + } + catch (TranslationException e) + { + job.Output.WriteError($"[{entry.Key} Compiling Generated Code:]\n" + e.Message); + job.Output.WriteError("[THIS SHOULD NOT HAVE HAPPENED, please report it to the P team or create a GitHub issue]\n" + e.Message); + Environment.ExitCode = 2; + return Environment.ExitCode; + } + } + else + { + job.Output.WriteInfo($"Build succeeded."); } } - else - { - job.Output.WriteInfo("Build succeeded."); - } + job.Output.WriteInfo($"----------------------------------------"); + job.Output.WriteInfo($"Compilation succeeded."); + Environment.ExitCode = 0; return Environment.ExitCode; } diff --git a/Src/PCompiler/CompilerCore/CompilerConfiguration.cs b/Src/PCompiler/CompilerCore/CompilerConfiguration.cs index 2af8de98f..355077408 100644 --- a/Src/PCompiler/CompilerCore/CompilerConfiguration.cs +++ b/Src/PCompiler/CompilerCore/CompilerConfiguration.cs @@ -20,12 +20,12 @@ public CompilerConfiguration() ProjectRootPath = new DirectoryInfo(Directory.GetCurrentDirectory()); LocationResolver = new DefaultLocationResolver(); Handler = new DefaultTranslationErrorHandler(LocationResolver); - OutputLanguage = CompilerOutput.CSharp; - Backend = TargetLanguage.GetCodeGenerator(OutputLanguage); + OutputLanguages = new Dictionary{{"CSharp", CompilerOutput.CSharp}}; + Backend = null; ProjectDependencies = new List(); } - public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, CompilerOutput outputLanguage, IList inputFiles, - string projectName, DirectoryInfo projectRoot = null, IList projectDependencies = null) + public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, IDictionary outputLanguages, IList inputFiles, + string projectName, DirectoryInfo projectRoot = null, IList projectDependencies = null, string pObservePackageName = null) { if (!inputFiles.Any()) { @@ -48,18 +48,18 @@ public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, Co } } ProjectName = projectName ?? Path.GetFileNameWithoutExtension(inputFiles[0]); - PObservePackageName = $"{ProjectName}.pobserve"; + PObservePackageName = pObservePackageName ?? $"{ProjectName}.pobserve"; ProjectRootPath = projectRoot; LocationResolver = new DefaultLocationResolver(); Handler = new DefaultTranslationErrorHandler(LocationResolver); - OutputLanguage = outputLanguage; - Backend = TargetLanguage.GetCodeGenerator(outputLanguage); + OutputLanguages = outputLanguages; + Backend = null; ProjectDependencies = projectDependencies ?? new List(); } public ICompilerOutput Output { get; set; } public DirectoryInfo OutputDirectory { get; set; } - public CompilerOutput OutputLanguage { get; set; } + public IDictionary OutputLanguages { get; set; } public string ProjectName { get; set; } public string PObservePackageName { get; set; } public DirectoryInfo ProjectRootPath { get; set; } @@ -83,7 +83,7 @@ public void Copy(CompilerConfiguration parsedConfig) ProjectDependencies = parsedConfig.ProjectDependencies; ProjectName = parsedConfig.ProjectName; PObservePackageName = parsedConfig.PObservePackageName; - OutputLanguage = parsedConfig.OutputLanguage; + OutputLanguages = parsedConfig.OutputLanguages; ProjectRootPath = parsedConfig.ProjectRootPath; } } diff --git a/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs b/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs index 2f524166c..7a88ee616 100644 --- a/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs +++ b/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs @@ -10,10 +10,10 @@ public interface ICompilerConfiguration string ProjectName { get; } string PObservePackageName { get; } DirectoryInfo ProjectRootPath { get; } - CompilerOutput OutputLanguage { get; } - ICompilerOutput Output { get; } - DirectoryInfo OutputDirectory { get; } - ICodeGenerator Backend { get; } + public IDictionary OutputLanguages { get; } + ICompilerOutput Output { get; set; } + DirectoryInfo OutputDirectory { get; set; } + ICodeGenerator Backend { get; set; } IList InputPFiles { get; } IList InputForeignFiles { get; } IList ProjectDependencies { get; } diff --git a/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs b/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs index 02b8441d0..dd38efed3 100644 --- a/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs +++ b/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs @@ -158,17 +158,29 @@ private static void UpdateConfigurationWithParsedArgument(CompilerConfiguration compilerConfiguration.ProjectName = (string)option.Value; break; case "mode": + compilerConfiguration.OutputLanguages = new Dictionary(); + switch (((string)option.Value).ToLowerInvariant()) { - compilerConfiguration.OutputLanguage = (string)option.Value switch - { - "bugfinding" => CompilerOutput.CSharp, - "verification" => CompilerOutput.Symbolic, - "coverage" => CompilerOutput.Symbolic, - "pobserve" => CompilerOutput.Java, - "stately" => CompilerOutput.Stately, - _ => compilerConfiguration.OutputLanguage - }; - compilerConfiguration.Backend = TargetLanguage.GetCodeGenerator(compilerConfiguration.OutputLanguage); + case "bugfinding": + case "csharp": + compilerConfiguration.OutputLanguages["CSharp"] = CompilerOutput.CSharp; + break; + case "verification": + case "coverage": + case "symbolic": + case "psym": + case "pcover": + compilerConfiguration.OutputLanguages["Symbolic"] = CompilerOutput.Symbolic; + break; + case "pobserve": + case "java": + compilerConfiguration.OutputLanguages["Java"] = CompilerOutput.Java; + break; + case "stately": + compilerConfiguration.OutputLanguages["Stately"] = CompilerOutput.Stately; + break; + default: + throw new Exception($"Unexpected mode: '{option.Value}'"); } break; case "pobserve-package": @@ -234,9 +246,6 @@ private static void SanitizeConfiguration(CompilerConfiguration compilerConfigur compilerConfiguration.OutputDirectory = Directory.CreateDirectory("PGenerated"); compilerConfiguration.Output = new DefaultCompilerOutput(compilerConfiguration.OutputDirectory); } - - compilerConfiguration.OutputDirectory = Directory.CreateDirectory(Path.Combine(compilerConfiguration.OutputDirectory.FullName, compilerConfiguration.OutputLanguage.ToString())); - compilerConfiguration.Output = new DefaultCompilerOutput(compilerConfiguration.OutputDirectory); } diff --git a/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs b/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs index 3f6c1ae3d..4e4edeec3 100644 --- a/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs +++ b/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs @@ -6,6 +6,7 @@ using PChecker; using PChecker.IO.Debugging; using Plang.Compiler; +using Debug = System.Diagnostics.Debug; namespace Plang.Parser { @@ -30,7 +31,6 @@ public void ParseProjectFileForCompiler(string projectFile, out CompilerConfigur CommandLineOutput.WriteInfo($"----------------------------------------"); CommandLineOutput.WriteInfo($"==== Loading project file: {projectFile}"); - var outputLanguage = CompilerOutput.CSharp; var inputFiles = new HashSet(); var projectDependencies = new HashSet(); @@ -50,9 +50,17 @@ public void ParseProjectFileForCompiler(string projectFile, out CompilerConfigur // get output directory var outputDirectory = GetOutputDirectory(projectFilePath); + + // get targets + var outputLanguages = GetTargetLanguages(projectFilePath); + + // get pobserve package name + var pObservePackageName = GetPObservePackage(projectFilePath); job = new CompilerConfiguration(output: new DefaultCompilerOutput(outputDirectory), outputDir: outputDirectory, - outputLanguage: outputLanguage, inputFiles: inputFiles.ToList(), projectName: projectName, projectRoot: projectFilePath.Directory, projectDependencies: projectDependencies.ToList()); + outputLanguages: outputLanguages, inputFiles: inputFiles.ToList(), projectName: projectName, + projectRoot: projectFilePath.Directory, projectDependencies: projectDependencies.ToList(), + pObservePackageName: pObservePackageName); CommandLineOutput.WriteInfo($"----------------------------------------"); } @@ -155,6 +163,23 @@ private string GetProjectName(FileInfo projectFullPath) return projectName; } + /// + /// Parse the PObserve package name from the pproj file + /// + /// Path to the pproj file + /// pobserve package name + private string GetPObservePackage(FileInfo projectFullPath) + { + string pObservePackageName = null; + var projectXml = XElement.Load(projectFullPath.FullName); + if (projectXml.Elements("pobserve-package").Any()) + { + pObservePackageName = projectXml.Element("pobserve-package")?.Value; + } + + return pObservePackageName; + } + /// /// Parse the output directory information from the pproj file /// @@ -183,43 +208,48 @@ private string GetOutputDirectoryName(FileInfo fullPathName) return Directory.GetCurrentDirectory(); } - private void GetTargetLanguage(FileInfo fullPathName, ref CompilerOutput outputLanguage, ref bool generateSourceMaps) + private IDictionary GetTargetLanguages(FileInfo fullPathName) { + var outputLanguages = new Dictionary(); var projectXml = XElement.Load(fullPathName.FullName); - if (!projectXml.Elements("Target").Any()) return; - switch (projectXml.Element("Target")?.Value.ToLowerInvariant()) + if (!projectXml.Elements("Target").Any()) { - case "c": - outputLanguage = CompilerOutput.C; - // check for generate source maps attribute - try - { - if (projectXml.Element("Target")!.Attributes("sourcemaps").Any()) - { - generateSourceMaps = bool.Parse(projectXml.Element("Target")?.Attribute("sourcemaps")?.Value ?? string.Empty); - } - } - catch (Exception) + outputLanguages["CSharp"] = CompilerOutput.CSharp; + } + else + { + string[] values = projectXml.Element("Target")?.Value.Split(new[] { ',', ' ' }, + StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < values!.Length; i++) + { + switch (values[i].ToLowerInvariant()) { - throw new CommandlineParsingError($"Expected true or false, received {projectXml.Element("Target")?.Attribute("sourcemaps")?.Value}"); + case "bugfinding": + case "csharp": + outputLanguages["CSharp"] = CompilerOutput.CSharp; + break; + case "verification": + case "coverage": + case "symbolic": + case "psym": + case "pcover": + outputLanguages["Symbolic"] = CompilerOutput.Symbolic; + break; + case "pobserve": + case "java": + outputLanguages["Java"] = CompilerOutput.Java; + break; + case "stately": + outputLanguages["Stately"] = CompilerOutput.Stately; + break; + default: + throw new CommandlineParsingError( + $"Expected CSharp, Java, Stately, or Symbolic as target, received {projectXml.Element("Target")?.Value}"); } - break; - - case "csharp": - outputLanguage = CompilerOutput.CSharp; - break; - - case "java": - outputLanguage = CompilerOutput.Java; - break; - - case "symbolic": - outputLanguage = CompilerOutput.Symbolic; - break; - - default: - throw new CommandlineParsingError($"Expected c, csharp, java, or symbolic as target, received {projectXml.Element("Target")?.Value}"); + } } + + return outputLanguages; } /// diff --git a/Tst/UnitTests/Core/TestCaseFactory.cs b/Tst/UnitTests/Core/TestCaseFactory.cs index 53e5b4edf..787107ad8 100644 --- a/Tst/UnitTests/Core/TestCaseFactory.cs +++ b/Tst/UnitTests/Core/TestCaseFactory.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Plang.Compiler; @@ -86,7 +87,7 @@ public CompilerTestCase CreateTestCase(DirectoryInfo testDir) ICompilerTestRunner runner; ITestResultsValidator validator; - var output = CompilerOutput.C; + var output = new Dictionary{{"C", CompilerOutput.C}}; runner = new CompileOnlyRunner(output, inputFiles.Select(x => x.FullName).ToList()); // TODO: validate information about the particular kind of compiler error diff --git a/Tst/UnitTests/Runners/CompileOnlyRunner.cs b/Tst/UnitTests/Runners/CompileOnlyRunner.cs index 9f908bc73..0bc11f5e5 100644 --- a/Tst/UnitTests/Runners/CompileOnlyRunner.cs +++ b/Tst/UnitTests/Runners/CompileOnlyRunner.cs @@ -14,18 +14,18 @@ namespace UnitTests.Runners /// public class CompileOnlyRunner : ICompilerTestRunner { - private readonly CompilerOutput compilerOutput; + private readonly IDictionary compilerOutputs; private readonly IList inputFiles; /// /// Box a new compile runner /// - /// + /// /// The P source files to compile - public CompileOnlyRunner(CompilerOutput compilerOutput, IList inputFiles) + public CompileOnlyRunner(IDictionary compilerOutputs, IList inputFiles) { this.inputFiles = inputFiles; - this.compilerOutput = compilerOutput; + this.compilerOutputs = compilerOutputs; } /// @@ -45,7 +45,7 @@ public CompileOnlyRunner(CompilerOutput compilerOutput, IList inputFiles var stderrWriter = new StringWriter(); var outputStream = new TestCaseOutputStream(stdoutWriter, stderrWriter); - var job = new CompilerConfiguration(outputStream, scratchDirectory, compilerOutput, inputFiles, Path.GetFileNameWithoutExtension(inputFiles.First())); + var job = new CompilerConfiguration(outputStream, scratchDirectory, compilerOutputs, inputFiles, Path.GetFileNameWithoutExtension(inputFiles.First())); try { diff --git a/Tst/UnitTests/Runners/PCheckerRunner.cs b/Tst/UnitTests/Runners/PCheckerRunner.cs index 98c4dfa13..b723e8cd3 100644 --- a/Tst/UnitTests/Runners/PCheckerRunner.cs +++ b/Tst/UnitTests/Runners/PCheckerRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Plang.Compiler; @@ -155,7 +156,7 @@ private int DoCompile(DirectoryInfo scratchDirectory) { var compiler = new Compiler(); var outputStream = new TestExecutionStream(scratchDirectory); - var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, CompilerOutput.CSharp, sources.Select(x => x.FullName).ToList(), "Main", scratchDirectory); + var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, new Dictionary{{"CSharp", CompilerOutput.CSharp}}, sources.Select(x => x.FullName).ToList(), "Main", scratchDirectory); try { return compiler.Compile(compilerConfiguration); diff --git a/Tst/UnitTests/Runners/PrtRunner.cs b/Tst/UnitTests/Runners/PrtRunner.cs index 4f2e4f330..28bb2aea2 100644 --- a/Tst/UnitTests/Runners/PrtRunner.cs +++ b/Tst/UnitTests/Runners/PrtRunner.cs @@ -78,7 +78,8 @@ private void DoCompile(DirectoryInfo scratchDirectory) { var compiler = new Compiler(); var outputStream = new TestExecutionStream(scratchDirectory); - var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, CompilerOutput.C, sources.Select(x => x.FullName).ToList(), "main"); + var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, + new Dictionary{{"C", CompilerOutput.C}}, sources.Select(x => x.FullName).ToList(), "main"); compiler.Compile(compilerConfiguration); } From 7a98e3b79efe29a8d37123d4484f14a54058b132 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Wed, 27 Sep 2023 16:40:59 -0700 Subject: [PATCH 2/4] Correct output paths with multiple targets --- Src/PCompiler/CompilerCore/Compiler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Src/PCompiler/CompilerCore/Compiler.cs b/Src/PCompiler/CompilerCore/Compiler.cs index 1fe201ff5..29984e80f 100644 --- a/Src/PCompiler/CompilerCore/Compiler.cs +++ b/Src/PCompiler/CompilerCore/Compiler.cs @@ -53,9 +53,10 @@ public int Compile(ICompilerConfiguration job) IRTransformer.SimplifyMethod(fun); } + DirectoryInfo parentDirectory = job.OutputDirectory; foreach (var entry in job.OutputLanguages) { - job.OutputDirectory = Directory.CreateDirectory(Path.Combine(job.OutputDirectory.FullName, entry.Key)); + job.OutputDirectory = Directory.CreateDirectory(Path.Combine(parentDirectory.FullName, entry.Key)); job.Output = new DefaultCompilerOutput(job.OutputDirectory); job.Backend = TargetLanguage.GetCodeGenerator(entry.Value); From 6b9ac11d44af69799dfbf6e8d79666faf8dc8b10 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Wed, 27 Sep 2023 17:13:00 -0700 Subject: [PATCH 3/4] Correct C# test runner path --- Tst/UnitTests/Runners/PCheckerRunner.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Tst/UnitTests/Runners/PCheckerRunner.cs b/Tst/UnitTests/Runners/PCheckerRunner.cs index b723e8cd3..eb3c88ffb 100644 --- a/Tst/UnitTests/Runners/PCheckerRunner.cs +++ b/Tst/UnitTests/Runners/PCheckerRunner.cs @@ -50,22 +50,25 @@ private void FileCopy(string src, string target, bool overwrite) { stdout = ""; stderr = ""; + + // path to generated code + DirectoryInfo scratchDirectoryGenerated = Directory.CreateDirectory(Path.Combine(scratchDirectory.FullName, "CSharp")); // Do not want to use the auto-generated Test.cs file - CreateFileWithMainFunction(scratchDirectory); + CreateFileWithMainFunction(scratchDirectoryGenerated); // Do not want to use the auto-generated csproj file - CreateCSProjFile(scratchDirectory); + CreateCSProjFile(scratchDirectoryGenerated); // copy the foreign code to the folder foreach (var nativeFile in nativeSources) { - FileCopy(nativeFile.FullName, Path.Combine(scratchDirectory.FullName, nativeFile.Name), true); + FileCopy(nativeFile.FullName, Path.Combine(scratchDirectoryGenerated.FullName, nativeFile.Name), true); } var exitCode = DoCompile(scratchDirectory); if (exitCode == 0) { - exitCode = RunPChecker(scratchDirectory.FullName, - Path.Combine(scratchDirectory.FullName, "./net6.0/Main.dll"), out var testStdout, out var testStderr); + exitCode = RunPChecker(scratchDirectoryGenerated.FullName, + Path.Combine(scratchDirectoryGenerated.FullName, "./net6.0/Main.dll"), out var testStdout, out var testStderr); stdout += testStdout; stderr += testStderr; } From dd21650774c9819d57d32cb8ad91eda2a1b1ac03 Mon Sep 17 00:00:00 2001 From: Aman Goel Date: Tue, 3 Oct 2023 09:01:03 -0700 Subject: [PATCH 4/4] [CLI] Update backend targets from dict to list --- Src/PCompiler/CompilerCore/Compiler.cs | 10 +++++----- .../CompilerCore/CompilerConfiguration.cs | 6 +++--- .../CompilerCore/ICompilerConfiguration.cs | 2 +- .../PCommandLine/Options/PCompilerOptions.cs | 10 +++++----- .../PCommandLine/Parser/ParsePProjectFile.cs | 14 +++++++------- Tst/UnitTests/Core/TestCaseFactory.cs | 2 +- Tst/UnitTests/Runners/CompileOnlyRunner.cs | 4 ++-- Tst/UnitTests/Runners/PCheckerRunner.cs | 2 +- Tst/UnitTests/Runners/PrtRunner.cs | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Src/PCompiler/CompilerCore/Compiler.cs b/Src/PCompiler/CompilerCore/Compiler.cs index 29984e80f..179d56e29 100644 --- a/Src/PCompiler/CompilerCore/Compiler.cs +++ b/Src/PCompiler/CompilerCore/Compiler.cs @@ -54,14 +54,14 @@ public int Compile(ICompilerConfiguration job) } DirectoryInfo parentDirectory = job.OutputDirectory; - foreach (var entry in job.OutputLanguages) + foreach (var entry in job.OutputLanguages.Distinct()) { - job.OutputDirectory = Directory.CreateDirectory(Path.Combine(parentDirectory.FullName, entry.Key)); + job.OutputDirectory = Directory.CreateDirectory(Path.Combine(parentDirectory.FullName, entry.ToString())); job.Output = new DefaultCompilerOutput(job.OutputDirectory); - job.Backend = TargetLanguage.GetCodeGenerator(entry.Value); + job.Backend = TargetLanguage.GetCodeGenerator(entry); job.Output.WriteInfo($"----------------------------------------"); - job.Output.WriteInfo($"Code generation for {entry.Key}..."); + job.Output.WriteInfo($"Code generation for {entry}..."); // Run the selected backend on the project and write the files. var compiledFiles = job.Backend.GenerateCode(job, scope); @@ -82,7 +82,7 @@ public int Compile(ICompilerConfiguration job) } catch (TranslationException e) { - job.Output.WriteError($"[{entry.Key} Compiling Generated Code:]\n" + e.Message); + job.Output.WriteError($"[{entry} Compiling Generated Code:]\n" + e.Message); job.Output.WriteError("[THIS SHOULD NOT HAVE HAPPENED, please report it to the P team or create a GitHub issue]\n" + e.Message); Environment.ExitCode = 2; return Environment.ExitCode; diff --git a/Src/PCompiler/CompilerCore/CompilerConfiguration.cs b/Src/PCompiler/CompilerCore/CompilerConfiguration.cs index 355077408..9afd92bef 100644 --- a/Src/PCompiler/CompilerCore/CompilerConfiguration.cs +++ b/Src/PCompiler/CompilerCore/CompilerConfiguration.cs @@ -20,11 +20,11 @@ public CompilerConfiguration() ProjectRootPath = new DirectoryInfo(Directory.GetCurrentDirectory()); LocationResolver = new DefaultLocationResolver(); Handler = new DefaultTranslationErrorHandler(LocationResolver); - OutputLanguages = new Dictionary{{"CSharp", CompilerOutput.CSharp}}; + OutputLanguages = new List{CompilerOutput.CSharp}; Backend = null; ProjectDependencies = new List(); } - public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, IDictionary outputLanguages, IList inputFiles, + public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, IList outputLanguages, IList inputFiles, string projectName, DirectoryInfo projectRoot = null, IList projectDependencies = null, string pObservePackageName = null) { if (!inputFiles.Any()) @@ -59,7 +59,7 @@ public CompilerConfiguration(ICompilerOutput output, DirectoryInfo outputDir, ID public ICompilerOutput Output { get; set; } public DirectoryInfo OutputDirectory { get; set; } - public IDictionary OutputLanguages { get; set; } + public IList OutputLanguages { get; set; } public string ProjectName { get; set; } public string PObservePackageName { get; set; } public DirectoryInfo ProjectRootPath { get; set; } diff --git a/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs b/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs index 7a88ee616..36df61c9a 100644 --- a/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs +++ b/Src/PCompiler/CompilerCore/ICompilerConfiguration.cs @@ -10,7 +10,7 @@ public interface ICompilerConfiguration string ProjectName { get; } string PObservePackageName { get; } DirectoryInfo ProjectRootPath { get; } - public IDictionary OutputLanguages { get; } + IList OutputLanguages { get; } ICompilerOutput Output { get; set; } DirectoryInfo OutputDirectory { get; set; } ICodeGenerator Backend { get; set; } diff --git a/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs b/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs index dd38efed3..3953a69cf 100644 --- a/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs +++ b/Src/PCompiler/PCommandLine/Options/PCompilerOptions.cs @@ -158,26 +158,26 @@ private static void UpdateConfigurationWithParsedArgument(CompilerConfiguration compilerConfiguration.ProjectName = (string)option.Value; break; case "mode": - compilerConfiguration.OutputLanguages = new Dictionary(); + compilerConfiguration.OutputLanguages = new List(); switch (((string)option.Value).ToLowerInvariant()) { case "bugfinding": case "csharp": - compilerConfiguration.OutputLanguages["CSharp"] = CompilerOutput.CSharp; + compilerConfiguration.OutputLanguages.Add(CompilerOutput.CSharp); break; case "verification": case "coverage": case "symbolic": case "psym": case "pcover": - compilerConfiguration.OutputLanguages["Symbolic"] = CompilerOutput.Symbolic; + compilerConfiguration.OutputLanguages.Add(CompilerOutput.Symbolic); break; case "pobserve": case "java": - compilerConfiguration.OutputLanguages["Java"] = CompilerOutput.Java; + compilerConfiguration.OutputLanguages.Add(CompilerOutput.Java); break; case "stately": - compilerConfiguration.OutputLanguages["Stately"] = CompilerOutput.Stately; + compilerConfiguration.OutputLanguages.Add(CompilerOutput.Stately); break; default: throw new Exception($"Unexpected mode: '{option.Value}'"); diff --git a/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs b/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs index 4e4edeec3..32ba18363 100644 --- a/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs +++ b/Src/PCompiler/PCommandLine/Parser/ParsePProjectFile.cs @@ -208,13 +208,13 @@ private string GetOutputDirectoryName(FileInfo fullPathName) return Directory.GetCurrentDirectory(); } - private IDictionary GetTargetLanguages(FileInfo fullPathName) + private IList GetTargetLanguages(FileInfo fullPathName) { - var outputLanguages = new Dictionary(); + var outputLanguages = new List(); var projectXml = XElement.Load(fullPathName.FullName); if (!projectXml.Elements("Target").Any()) { - outputLanguages["CSharp"] = CompilerOutput.CSharp; + outputLanguages.Add(CompilerOutput.CSharp); } else { @@ -226,21 +226,21 @@ private IDictionary GetTargetLanguages(FileInfo fullPath { case "bugfinding": case "csharp": - outputLanguages["CSharp"] = CompilerOutput.CSharp; + outputLanguages.Add(CompilerOutput.CSharp); break; case "verification": case "coverage": case "symbolic": case "psym": case "pcover": - outputLanguages["Symbolic"] = CompilerOutput.Symbolic; + outputLanguages.Add(CompilerOutput.Symbolic); break; case "pobserve": case "java": - outputLanguages["Java"] = CompilerOutput.Java; + outputLanguages.Add(CompilerOutput.Java); break; case "stately": - outputLanguages["Stately"] = CompilerOutput.Stately; + outputLanguages.Add(CompilerOutput.Stately); break; default: throw new CommandlineParsingError( diff --git a/Tst/UnitTests/Core/TestCaseFactory.cs b/Tst/UnitTests/Core/TestCaseFactory.cs index 787107ad8..d731c9d42 100644 --- a/Tst/UnitTests/Core/TestCaseFactory.cs +++ b/Tst/UnitTests/Core/TestCaseFactory.cs @@ -87,7 +87,7 @@ public CompilerTestCase CreateTestCase(DirectoryInfo testDir) ICompilerTestRunner runner; ITestResultsValidator validator; - var output = new Dictionary{{"C", CompilerOutput.C}}; + var output = new List{CompilerOutput.C}; runner = new CompileOnlyRunner(output, inputFiles.Select(x => x.FullName).ToList()); // TODO: validate information about the particular kind of compiler error diff --git a/Tst/UnitTests/Runners/CompileOnlyRunner.cs b/Tst/UnitTests/Runners/CompileOnlyRunner.cs index 0bc11f5e5..718a80c01 100644 --- a/Tst/UnitTests/Runners/CompileOnlyRunner.cs +++ b/Tst/UnitTests/Runners/CompileOnlyRunner.cs @@ -14,7 +14,7 @@ namespace UnitTests.Runners /// public class CompileOnlyRunner : ICompilerTestRunner { - private readonly IDictionary compilerOutputs; + private readonly IList compilerOutputs; private readonly IList inputFiles; /// @@ -22,7 +22,7 @@ public class CompileOnlyRunner : ICompilerTestRunner /// /// /// The P source files to compile - public CompileOnlyRunner(IDictionary compilerOutputs, IList inputFiles) + public CompileOnlyRunner(IList compilerOutputs, IList inputFiles) { this.inputFiles = inputFiles; this.compilerOutputs = compilerOutputs; diff --git a/Tst/UnitTests/Runners/PCheckerRunner.cs b/Tst/UnitTests/Runners/PCheckerRunner.cs index eb3c88ffb..a158fcac3 100644 --- a/Tst/UnitTests/Runners/PCheckerRunner.cs +++ b/Tst/UnitTests/Runners/PCheckerRunner.cs @@ -159,7 +159,7 @@ private int DoCompile(DirectoryInfo scratchDirectory) { var compiler = new Compiler(); var outputStream = new TestExecutionStream(scratchDirectory); - var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, new Dictionary{{"CSharp", CompilerOutput.CSharp}}, sources.Select(x => x.FullName).ToList(), "Main", scratchDirectory); + var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, new List{CompilerOutput.CSharp}, sources.Select(x => x.FullName).ToList(), "Main", scratchDirectory); try { return compiler.Compile(compilerConfiguration); diff --git a/Tst/UnitTests/Runners/PrtRunner.cs b/Tst/UnitTests/Runners/PrtRunner.cs index 28bb2aea2..cacbf5e43 100644 --- a/Tst/UnitTests/Runners/PrtRunner.cs +++ b/Tst/UnitTests/Runners/PrtRunner.cs @@ -79,7 +79,7 @@ private void DoCompile(DirectoryInfo scratchDirectory) var compiler = new Compiler(); var outputStream = new TestExecutionStream(scratchDirectory); var compilerConfiguration = new CompilerConfiguration(outputStream, scratchDirectory, - new Dictionary{{"C", CompilerOutput.C}}, sources.Select(x => x.FullName).ToList(), "main"); + new List{CompilerOutput.C}, sources.Select(x => x.FullName).ToList(), "main"); compiler.Compile(compilerConfiguration); }