/// <summary> /// Generate a C# program from the Dafny program and, if "invokeCsCompiler" is "true", invoke /// the C# compiler to compile it. /// </summary> public static bool CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName, ReadOnlyCollection <string> otherFileNames, bool invokeCsCompiler, TextWriter outputWriter = null) { Contract.Requires(dafnyProgram != null); if (outputWriter == null) { outputWriter = Console.Out; } // Compile the Dafny program into a string that contains the C# program StringWriter sw = new StringWriter(); var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error); Dafny.Compiler compiler = new Dafny.Compiler(dafnyProgram.reporter); var hasMain = compiler.HasMain(dafnyProgram); compiler.Compile(dafnyProgram, sw); var csharpProgram = sw.ToString(); bool completeProgram = dafnyProgram.reporter.Count(ErrorLevel.Error) == oldErrorCount; // blurt out the code to a file, if requested, or if other files were specified for the C# command line. string targetFilename = null; if (DafnyOptions.O.SpillTargetCode > 0 || otherFileNames.Count > 0) { targetFilename = WriteDafnyProgramToFile(dafnyProgramName, csharpProgram, completeProgram, outputWriter); } // compile the program into an assembly if (!completeProgram || !invokeCsCompiler) { // don't compile return(false); } else if (!CodeDomProvider.IsDefinedLanguage("CSharp")) { outputWriter.WriteLine("Error: cannot compile, because there is no provider configured for input language CSharp"); return(false); } else { var provider = CodeDomProvider.CreateProvider("CSharp", new Dictionary <string, string> { { "CompilerVersion", "v4.0" } }); var cp = new System.CodeDom.Compiler.CompilerParameters(); cp.GenerateExecutable = hasMain; if (DafnyOptions.O.RunAfterCompile) { cp.GenerateInMemory = true; } else if (hasMain) { cp.OutputAssembly = Path.ChangeExtension(dafnyProgramName, "exe"); cp.GenerateInMemory = false; } else { cp.OutputAssembly = Path.ChangeExtension(dafnyProgramName, "dll"); cp.GenerateInMemory = false; } cp.CompilerOptions = "/debug /nowarn:0164 /nowarn:0219 /nowarn:1717 /nowarn:0162"; // warning CS0164 complains about unreferenced labels, CS0219 is about unused variables, CS1717 is about assignments of a variable to itself, CS0162 is about unreachable code cp.ReferencedAssemblies.Add("System.Numerics.dll"); cp.ReferencedAssemblies.Add("System.Core.dll"); cp.ReferencedAssemblies.Add("System.dll"); var libPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar; if (DafnyOptions.O.UseRuntimeLib) { cp.ReferencedAssemblies.Add(libPath + "DafnyRuntime.dll"); } var immutableDllFileName = "System.Collections.Immutable.dll"; var immutableDllPath = libPath + immutableDllFileName; if (DafnyOptions.O.Optimize) { cp.CompilerOptions += " /optimize /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE"; cp.ReferencedAssemblies.Add(immutableDllPath); cp.ReferencedAssemblies.Add("System.Runtime.dll"); } int numOtherSourceFiles = 0; if (otherFileNames.Count > 0) { foreach (var file in otherFileNames) { string extension = Path.GetExtension(file); if (extension != null) { extension = extension.ToLower(); } if (extension == ".cs") { numOtherSourceFiles++; } else if (extension == ".dll") { cp.ReferencedAssemblies.Add(file); } } } CompilerResults cr; if (numOtherSourceFiles > 0) { string[] sourceFiles = new string[numOtherSourceFiles + 1]; sourceFiles[0] = targetFilename; int index = 1; foreach (var file in otherFileNames) { string extension = Path.GetExtension(file); if (extension != null) { extension = extension.ToLower(); } if (extension == ".cs") { sourceFiles[index++] = file; } } cr = provider.CompileAssemblyFromFile(cp, sourceFiles); } else { cr = provider.CompileAssemblyFromSource(cp, csharpProgram); } if (DafnyOptions.O.RunAfterCompile && !hasMain) { // do no more return(cr.Errors.Count == 0 ? true : false); } var assemblyName = Path.GetFileName(cr.PathToAssembly); if (DafnyOptions.O.RunAfterCompile && cr.Errors.Count == 0) { outputWriter.WriteLine("Program compiled successfully"); outputWriter.WriteLine("Running..."); outputWriter.WriteLine(); var entry = cr.CompiledAssembly.EntryPoint; try { object[] parameters = entry.GetParameters().Length == 0 ? new object[] { } : new object[] { new string[0] }; entry.Invoke(null, parameters); } catch (System.Reflection.TargetInvocationException e) { outputWriter.WriteLine("Error: Execution resulted in exception: {0}", e.Message); outputWriter.WriteLine(e.InnerException.ToString()); } catch (Exception e) { outputWriter.WriteLine("Error: Execution resulted in exception: {0}", e.Message); outputWriter.WriteLine(e.ToString()); } } else if (cr.Errors.Count == 0) { outputWriter.WriteLine("Compiled assembly into {0}", assemblyName); if (DafnyOptions.O.Optimize) { var outputDir = Path.GetDirectoryName(dafnyProgramName); if (string.IsNullOrWhiteSpace(outputDir)) { outputDir = "."; } var destPath = outputDir + Path.DirectorySeparatorChar + immutableDllFileName; File.Copy(immutableDllPath, destPath, true); outputWriter.WriteLine("Copied /optimize dependency {0} to {1}", immutableDllFileName, outputDir); } } else { outputWriter.WriteLine("Errors compiling program into {0}", assemblyName); foreach (var ce in cr.Errors) { outputWriter.WriteLine(ce.ToString()); outputWriter.WriteLine(); } return(false); } return(true); } }
public static void CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName, ReadOnlyCollection<string> otherFileNames, TextWriter outputWriter = null) { Contract.Requires(dafnyProgram != null); if (outputWriter == null) { outputWriter = Console.Out; } // Compile the Dafny program into a string that contains the C# program StringWriter sw = new StringWriter(); Dafny.Compiler compiler = new Dafny.Compiler(); compiler.ErrorWriter = outputWriter; var hasMain = compiler.HasMain(dafnyProgram); if (DafnyOptions.O.RunAfterCompile && !hasMain) { // do no more return; } compiler.Compile(dafnyProgram, sw); var csharpProgram = sw.ToString(); bool completeProgram = compiler.ErrorCount == 0; // blurt out the code to a file, if requested, or if other files were specified for the C# command line. string targetFilename = null; if (DafnyOptions.O.SpillTargetCode || (otherFileNames.Count > 0)) { targetFilename = WriteDafnyProgramToFile(dafnyProgramName, csharpProgram, completeProgram, outputWriter); } // compile the program into an assembly if (!completeProgram) { // don't compile } else if (!CodeDomProvider.IsDefinedLanguage("CSharp")) { outputWriter.WriteLine("Error: cannot compile, because there is no provider configured for input language CSharp"); } else { var provider = CodeDomProvider.CreateProvider("CSharp", new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); var cp = new System.CodeDom.Compiler.CompilerParameters(); cp.GenerateExecutable = hasMain; if (DafnyOptions.O.RunAfterCompile) { cp.GenerateInMemory = true; } else if (hasMain) { cp.OutputAssembly = Path.ChangeExtension(dafnyProgramName, "exe"); cp.GenerateInMemory = false; } else { cp.OutputAssembly = Path.ChangeExtension(dafnyProgramName, "dll"); cp.GenerateInMemory = false; } cp.CompilerOptions = "/debug /nowarn:0164 /nowarn:0219"; // warning CS0164 complains about unreferenced labels, CS0219 is about unused variables cp.ReferencedAssemblies.Add("System.Numerics.dll"); cp.ReferencedAssemblies.Add("System.Core.dll"); cp.ReferencedAssemblies.Add("System.dll"); var libPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar; var immutableDllFileName = "System.Collections.Immutable.dll"; var immutableDllPath = libPath + immutableDllFileName; if (DafnyOptions.O.Optimize) { cp.CompilerOptions += " /optimize /define:DAFNY_USE_SYSTEM_COLLECTIONS_IMMUTABLE"; cp.ReferencedAssemblies.Add(immutableDllPath); cp.ReferencedAssemblies.Add("System.Runtime.dll"); } int numOtherSourceFiles = 0; if (otherFileNames.Count > 0) { foreach (var file in otherFileNames) { string extension = Path.GetExtension(file); if (extension != null) { extension = extension.ToLower(); } if (extension == ".cs") { numOtherSourceFiles++; } else if (extension == ".dll") { cp.ReferencedAssemblies.Add(file); } } } CompilerResults cr; if (numOtherSourceFiles > 0) { string[] sourceFiles = new string[numOtherSourceFiles + 1]; sourceFiles[0] = targetFilename; int index = 1; foreach (var file in otherFileNames) { string extension = Path.GetExtension(file); if (extension != null) { extension = extension.ToLower(); } if (extension == ".cs") { sourceFiles[index++] = file; } } cr = provider.CompileAssemblyFromFile(cp, sourceFiles); } else { cr = provider.CompileAssemblyFromSource(cp, csharpProgram); } var assemblyName = Path.GetFileName(cr.PathToAssembly); if (DafnyOptions.O.RunAfterCompile && cr.Errors.Count == 0) { outputWriter.WriteLine("Program compiled successfully"); outputWriter.WriteLine("Running..."); outputWriter.WriteLine(); var entry = cr.CompiledAssembly.EntryPoint; try { object[] parameters = entry.GetParameters().Length == 0 ? new object[] { } : new object[] { new string[0] }; entry.Invoke(null, parameters); } catch (System.Reflection.TargetInvocationException e) { outputWriter.WriteLine("Error: Execution resulted in exception: {0}", e.Message); outputWriter.WriteLine(e.InnerException.ToString()); } catch (Exception e) { outputWriter.WriteLine("Error: Execution resulted in exception: {0}", e.Message); outputWriter.WriteLine(e.ToString()); } } else if (cr.Errors.Count == 0) { outputWriter.WriteLine("Compiled assembly into {0}", assemblyName); if (DafnyOptions.O.Optimize) { var outputDir = Path.GetDirectoryName(dafnyProgramName); if (string.IsNullOrWhiteSpace(outputDir)) { outputDir = "."; } var destPath = outputDir + Path.DirectorySeparatorChar + immutableDllFileName; File.Copy(immutableDllPath, destPath, true); outputWriter.WriteLine("Copied /optimize dependency {0} to {1}", immutableDllFileName, outputDir); } } else { outputWriter.WriteLine("Errors compiling program into {0}", assemblyName); foreach (var ce in cr.Errors) { outputWriter.WriteLine(ce.ToString()); outputWriter.WriteLine(); } } } }