Пример #1
0
        /// <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);
            }
        }
Пример #2
0
    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();
          }
        }
      }
    }