Skip to content

Commit

Permalink
Merge branch 'master' into fix-2068-resolver-crash
Browse files Browse the repository at this point in the history
  • Loading branch information
MikaelMayer authored Nov 8, 2022
2 parents 94bc4dd + 4a119ae commit 944c359
Show file tree
Hide file tree
Showing 30 changed files with 260 additions and 204 deletions.
2 changes: 1 addition & 1 deletion Source/DafnyCore/AST/TopLevelDeclarations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public void Set(ModuleDecl m) {
this.Sig = null;
} else {
this.Decl = m;
this.Def = ((LiteralModuleDecl)m).ModuleDef;
this.Def = m.Signature.ModuleDef;
this.Sig = m.Signature;
}
}
Expand Down
75 changes: 18 additions & 57 deletions Source/DafnyCore/Compilers/Compiler-cpp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2464,67 +2464,28 @@ public override bool CompileTargetProgram(string dafnyProgramName, string target
var codebase = System.IO.Path.GetDirectoryName(assemblyLocation);
Contract.Assert(codebase != null);
compilationResult = null;
var psi = new ProcessStartInfo("g++") {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
ArgumentList = {
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wno-unused-variable",
"-Wno-deprecated-copy",
"-Wno-unused-label",
"-Wno-unused-but-set-variable",
"-Wno-unknown-warning-option",
"-g",
"-std=c++17",
"-I", codebase,
"-o", ComputeExeName(targetFilename),
targetFilename
}
};
var proc = Process.Start(psi);
while (!proc.StandardOutput.EndOfStream) {
outputWriter.WriteLine(proc.StandardOutput.ReadLine());
}
while (!proc.StandardError.EndOfStream) {
outputWriter.WriteLine(proc.StandardError.ReadLine());
}
proc.WaitForExit();
if (proc.ExitCode != 0) {
outputWriter.WriteLine($"Error while compiling C++ files. Process exited with exit code {proc.ExitCode}");
return false;
}
return true;
var psi = PrepareProcessStartInfo("g++", new List<string> {
"-Wall",
"-Wextra",
"-Wpedantic",
"-Wno-unused-variable",
"-Wno-deprecated-copy",
"-Wno-unused-label",
"-Wno-unused-but-set-variable",
"-Wno-unknown-warning-option",
"-g",
"-std=c++17",
"-I", codebase,
"-o", ComputeExeName(targetFilename),
targetFilename
});
return 0 == RunProcess(psi, outputWriter, "Error while compiling C++ files.");
}

public override bool RunTargetProgram(string dafnyProgramName, string targetProgramText, string/*?*/ callToMain, string targetFilename, ReadOnlyCollection<string> otherFileNames,
object compilationResult, TextWriter outputWriter) {
var psi = new ProcessStartInfo(ComputeExeName(targetFilename)) {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
foreach (var arg in DafnyOptions.O.MainArgs) {
psi.ArgumentList.Add(arg);
}

var proc = Process.Start(psi);
while (!proc.StandardOutput.EndOfStream) {
outputWriter.WriteLine(proc.StandardOutput.ReadLine());
}
while (!proc.StandardError.EndOfStream) {
outputWriter.WriteLine(proc.StandardError.ReadLine());
}
proc.WaitForExit();
if (proc.ExitCode != 0) {
outputWriter.WriteLine($"Error while running C++ file {targetFilename}. Process exited with exit code {proc.ExitCode}");
return false;
}
return true;
var psi = PrepareProcessStartInfo(ComputeExeName(targetFilename), DafnyOptions.O.MainArgs);
return 0 == RunProcess(psi, outputWriter);
}
}
}
48 changes: 11 additions & 37 deletions Source/DafnyCore/Compilers/Compiler-go.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3618,9 +3618,9 @@ private bool SendToNewGoProcess(string dafnyProgramName, string targetFilename,
}
}

List<string> verb = new();
List<string> goArgs = new();
if (run) {
verb.Add("run");
goArgs.Add("run");
} else {
string output;
var outputToFile = !DafnyOptions.O.RunAfterCompile;
Expand Down Expand Up @@ -3655,48 +3655,22 @@ private bool SendToNewGoProcess(string dafnyProgramName, string targetFilename,
}
}

verb.Add("build");
verb.Add("-o");
verb.Add(output);
goArgs.Add("build");
goArgs.Add("-o");
goArgs.Add(output);
}

var psi = new ProcessStartInfo("go") {
CreateNoWindow = Environment.OSVersion.Platform != PlatformID.Win32NT,
UseShellExecute = false,
RedirectStandardInput = false,
RedirectStandardOutput = false,
RedirectStandardError = false,
};
foreach (var verbArg in verb) {
psi.ArgumentList.Add(verbArg);
}
psi.ArgumentList.Add(targetFilename);
foreach (var arg in DafnyOptions.O.MainArgs) {
psi.ArgumentList.Add(arg);
}
goArgs.Add(targetFilename);
goArgs.AddRange(DafnyOptions.O.MainArgs);

var psi = PrepareProcessStartInfo("go", goArgs);

psi.EnvironmentVariables["GOPATH"] = GoPath(targetFilename);
// Dafny compiles to the old Go package system, whereas Go has moved on to a module
// system. Until Dafny's Go compiler catches up, the GO111MODULE variable has to be set.
psi.EnvironmentVariables["GO111MODULE"] = "auto";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
// On Windows, Path.GetTempPath() returns "c:\Windows" which, being not writable, crashes Go.
// Hence we set up a local temporary directory
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
psi.EnvironmentVariables["GOTMPDIR"] = localAppData + @"\Temp";
psi.EnvironmentVariables["LOCALAPPDATA"] = localAppData + @"\go-build";
}

try {
using var process = Process.Start(psi);
if (process == null) {
return false;
}
process.WaitForExit();
return process.ExitCode == 0;
} catch (System.ComponentModel.Win32Exception e) {
outputWriter.WriteLine("Error: Unable to start go ({0}): {1}", psi.FileName, e.Message);
return false;
}
return 0 == RunProcess(psi, outputWriter);
}

static string GoPath(string filename) {
Expand Down
65 changes: 13 additions & 52 deletions Source/DafnyCore/Compilers/Compiler-java.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2273,68 +2273,29 @@ public override bool CompileTargetProgram(string dafnyProgramName, string target

var files = new List<string>();
foreach (string file in Directory.EnumerateFiles(targetDirectory, "*.java", SearchOption.AllDirectories)) {
files.Add($"\"{Path.GetFullPath(file)}\"");
}
var classpath = GetClassPath(targetFilename);
var psi = new ProcessStartInfo("javac", "-encoding UTF8 " + string.Join(" ", files)) {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = Path.GetFullPath(Path.GetDirectoryName(targetFilename))
};
psi.EnvironmentVariables["CLASSPATH"] = classpath;
var proc = Process.Start(psi)!;
DataReceivedEventHandler printer = (sender, e) => {
if (e.Data is not null) {
outputWriter.WriteLine(e.Data);
}
};
proc.ErrorDataReceived += printer;
proc.OutputDataReceived += printer;
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();

if (proc.ExitCode != 0) {
outputWriter.WriteLine($"Error while compiling Java files. Process exited with exit code {proc.ExitCode}");
return false;
files.Add(Path.GetFullPath(file));
}
return true;

var psi = PrepareProcessStartInfo("javac", new List<string> { "-encoding", "UTF8" }.Concat(files));
psi.WorkingDirectory = Path.GetFullPath(Path.GetDirectoryName(targetFilename));
psi.EnvironmentVariables["CLASSPATH"] = GetClassPath(targetFilename);
return 0 == RunProcess(psi, outputWriter, "Error while compiling Java files.");
}

public override bool RunTargetProgram(string dafnyProgramName, string targetProgramText, string callToMain, string /*?*/ targetFilename,
ReadOnlyCollection<string> otherFileNames, object compilationResult, TextWriter outputWriter) {
var psi = new ProcessStartInfo("java") {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = Path.GetFullPath(Path.GetDirectoryName(targetFilename))
};
psi.ArgumentList.Add(Path.GetFileNameWithoutExtension(targetFilename));
foreach (var arg in DafnyOptions.O.MainArgs) {
psi.ArgumentList.Add(arg);
}
var psi = PrepareProcessStartInfo("java",
args: DafnyOptions.O.MainArgs.Prepend(Path.GetFileNameWithoutExtension(targetFilename)));
psi.WorkingDirectory = Path.GetFullPath(Path.GetDirectoryName(targetFilename));
psi.EnvironmentVariables["CLASSPATH"] = GetClassPath(targetFilename);
var proc = Process.Start(psi);
while (!proc.StandardOutput.EndOfStream) {
outputWriter.WriteLine(proc.StandardOutput.ReadLine());
}
while (!proc.StandardError.EndOfStream) {
outputWriter.WriteLine(proc.StandardError.ReadLine());
}
proc.WaitForExit();
if (proc.ExitCode != 0) {
outputWriter.WriteLine($"Error while running Java file {targetFilename}. Process exited with exit code {proc.ExitCode}");
return false;
}
return true;
return 0 == RunProcess(psi, outputWriter);
}

protected string GetClassPath(string targetFilename) {
var targetDirectory = Path.GetFullPath(Path.GetDirectoryName(targetFilename));
return "." + Path.PathSeparator + targetDirectory + Path.PathSeparator + Path.Combine(targetDirectory, "DafnyRuntime.jar");
var classpath = Environment.GetEnvironmentVariable("CLASSPATH"); // String.join converts null to ""
// Note that the items in the CLASSPATH must have absolute paths because the compilation is performed in a subfolder of where the command-line is executed
return string.Join(Path.PathSeparator, ".", targetDirectory, Path.Combine(targetDirectory, "DafnyRuntime.jar"), classpath);
}

static bool CopyExternLibraryIntoPlace(string externFilename, string mainProgram, TextWriter outputWriter) {
Expand Down
30 changes: 4 additions & 26 deletions Source/DafnyCore/Compilers/Compiler-js.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace Microsoft.Dafny.Compilers {
Expand Down Expand Up @@ -2477,17 +2476,11 @@ bool SendToNewNodeProcess(string dafnyProgramName, string targetProgramText, str
TextWriter outputWriter) {
Contract.Requires(targetFilename != null || otherFileNames.Count == 0);

var psi = new ProcessStartInfo("node", "") {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
var psi = PrepareProcessStartInfo("node");
psi.RedirectStandardInput = true;

try {
Process nodeProcess = new Process { StartInfo = psi };
nodeProcess.Start();
Process nodeProcess = Process.Start(psi);
foreach (var filename in otherFileNames) {
WriteFromFile(filename, nodeProcess.StandardInput);
}
Expand All @@ -2498,27 +2491,12 @@ bool SendToNewNodeProcess(string dafnyProgramName, string targetProgramText, str
}
nodeProcess.StandardInput.Flush();
nodeProcess.StandardInput.Close();
// Fixes a problem of Node on Windows, where Node does not prints to the parent console its standard outputs.
var errorProcessing = Task.Run(() => {
PassthroughBuffer(nodeProcess.StandardError, Console.Error);
});
PassthroughBuffer(nodeProcess.StandardOutput, Console.Out);
nodeProcess.WaitForExit();
errorProcessing.Wait();
return nodeProcess.ExitCode == 0;
return 0 == WaitForExit(nodeProcess, outputWriter);
} catch (System.ComponentModel.Win32Exception e) {
outputWriter.WriteLine("Error: Unable to start node.js ({0}): {1}", psi.FileName, e.Message);
return false;
}
}

// We read character by character because we did not find a way to ensure
// final newlines are kept when reading line by line
void PassthroughBuffer(StreamReader input, TextWriter output) {
int current;
while ((current = input.Read()) != -1) {
output.Write((char)current);
}
}
}
}
23 changes: 2 additions & 21 deletions Source/DafnyCore/Compilers/Compiler-python.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1743,27 +1743,8 @@ public override bool CompileTargetProgram(string dafnyProgramName, string target
public override bool RunTargetProgram(string dafnyProgramName, string targetProgramText, string /*?*/ callToMain,
string targetFilename, ReadOnlyCollection<string> otherFileNames, object compilationResult, TextWriter outputWriter) {
Contract.Requires(targetFilename != null || otherFileNames.Count == 0);
var psi = new ProcessStartInfo("python3") {
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = false,
RedirectStandardError = false,
};
psi.ArgumentList.Add(targetFilename);
foreach (var arg in DafnyOptions.O.MainArgs) {
psi.ArgumentList.Add(arg);
}

try {
using var pythonProcess = Process.Start(psi);
pythonProcess.StandardInput.Close();
pythonProcess.WaitForExit();
return pythonProcess.ExitCode == 0;
} catch (Exception e) {
outputWriter.WriteLine("Error: Unable to start python ({0}): {1}", psi.FileName, e.Message);
return false;
}
var psi = PrepareProcessStartInfo("python3", DafnyOptions.O.MainArgs.Prepend(targetFilename));
return 0 == RunProcess(psi, outputWriter);
}
}
}
41 changes: 41 additions & 0 deletions Source/DafnyCore/Compilers/SinglePassCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Linq;
using System.Numerics;
using System.IO;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using JetBrains.Annotations;
Expand Down Expand Up @@ -64,6 +65,46 @@ int GetUniqueAstNumber(Expression expr) {

public CoverageInstrumenter Coverage;

public ProcessStartInfo PrepareProcessStartInfo(string programName, IEnumerable<string> args = null) {
var psi = new ProcessStartInfo(programName) {
UseShellExecute = false,
CreateNoWindow = false, // https://github.com/dotnet/runtime/issues/68259
};
foreach (var arg in args ?? Enumerable.Empty<string>()) {
psi.ArgumentList.Add(arg);
}
return psi;
}

public int WaitForExit(Process process, TextWriter outputWriter, string errorMessage = null) {
process.WaitForExit();
if (process.ExitCode != 0 && errorMessage != null) {
outputWriter.WriteLine("{0} Process exited with exit code {1}", errorMessage, process.ExitCode);
}
return process.ExitCode;
}

public Process StartProcess(ProcessStartInfo psi, TextWriter outputWriter) {
string additionalInfo = "";

try {
if (Process.Start(psi) is { } process) {
return process;
}
} catch (System.ComponentModel.Win32Exception e) {
additionalInfo = $": {e.Message}";
}

outputWriter.WriteLine($"Error: Unable to start {psi.FileName}{additionalInfo}");
return null;
}

public int RunProcess(ProcessStartInfo psi, TextWriter outputWriter, string errorMessage = null) {
return StartProcess(psi, outputWriter) is { } process ?
WaitForExit(process, outputWriter, errorMessage) : -1;
}


protected static void ReportError(ErrorReporter reporter, IToken tok, string msg, ConcreteSyntaxTree/*?*/ wr, params object[] args) {
Contract.Requires(msg != null);
Contract.Requires(args != null);
Expand Down
Loading

0 comments on commit 944c359

Please sign in to comment.