示例#1
0
        protected override BlockTargetWriter /*?*/ CreateMethod(Method m, bool createBody, TargetWriter wr)
        {
            if (!createBody)
            {
                return(null);
            }
            wr.Indent();
            wr.Write("{0}{1}(", m.IsStatic ? "static " : "", IdName(m));
            int nIns = WriteFormals("", m.Ins, wr);
            var w    = wr.NewBlock(")");

            if (!m.IsStatic)
            {
                w.Indent(); w.WriteLine("let _this = this;");
            }
            if (m.IsTailRecursive)
            {
                w.Indent();
                w = w.NewBlock("TAIL_CALL_START: while (true)");
            }
            var r = new TargetWriter(w.IndentLevel);

            EmitReturn(m.Outs, r);
            w.BodySuffix = r.ToString();
            return(w);
        }
示例#2
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Microsoft.Armada.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Assert(dafnyProgramName != null);
            Console.WriteLine("Running CompileDafnyProgram : {0}", dafnyProgramName);
            Console.WriteLine("Number of modules = {0}", dafnyProgram.CompileModules.Count);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Microsoft.Armada.Compiler compiler;

            switch (ArmadaOptions.O.CompileTarget)
            {
            case ArmadaOptions.CompilationTarget.Clight:
            default:
                compiler = new Microsoft.Armada.ClightTsoCompiler(dafnyProgram.reporter, otherFileNames);
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            string targetProgramText;
            var    otherFiles = new Dictionary <string, string>();
            {
                var fileQueue = new Queue <FileTargetWriter>();
                using (var wr = new TargetWriter(0)) {
                    compiler.Compile(dafnyProgram, wr);
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    targetProgramText = sw.ToString();
                }

                while (fileQueue.Count > 0)
                {
                    var wr = fileQueue.Dequeue();
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    otherFiles.Add(wr.Filename, sw.ToString());
                }
            }
            string baseName   = Path.GetFileNameWithoutExtension(dafnyProgramName);
            string callToMain = null;

            if (hasMain)
            {
                using (var wr = new TargetWriter(0)) {
                    compiler.EmitCallToMain(mainMethod, wr);
                    callToMain = wr.ToString(); // assume there aren't multiple files just to call main
                }
            }
            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 (ArmadaOptions.O.SpillTargetCode > 0 || otherFileNames.Count > 0 || (invokeCompiler && !compiler.SupportsInMemoryCompilation))
            {
                var p = callToMain == null ? targetProgramText : targetProgramText + callToMain;
                targetFilename = WriteDafnyProgramToFiles(dafnyProgramName, p, completeProgram, otherFiles, outputWriter);
            }

            // compile the program into an assembly
            if (!completeProgram || !invokeCompiler)
            {
                // don't compile
                // Caller interprets this as success/fail and returns an error if false,
                //  but we didn't actually hit an error, we just didn't invoke the compiler
                return(true);
            }

            // compile the program into an assembly
            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames,
                                                                     hasMain, hasMain && ArmadaOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && ArmadaOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    if (ArmadaOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Running...");
                        outputWriter.WriteLine();
                    }
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
                else
                {
                    // make sure to give some feedback to the user
                    if (ArmadaOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Program compiled successfully");
                    }
                }
            }
            return(compiledCorrectly);
        }
示例#3
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Assert(dafnyProgramName != null);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Dafny.Compiler compiler;
            switch (DafnyOptions.O.CompileTarget)
            {
            case DafnyOptions.CompilationTarget.Csharp:
            default:
                compiler = new Dafny.CsharpCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.JavaScript:
                compiler = new Dafny.JavaScriptCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Go:
                compiler = new Dafny.GoCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Java:
                compiler = new Dafny.JavaCompiler(dafnyProgram.reporter);
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            string targetProgramText;
            var    otherFiles = new Dictionary <string, string>();
            {
                var fileQueue = new Queue <FileTargetWriter>();
                using (var wr = new TargetWriter(0)) {
                    compiler.Compile(dafnyProgram, wr);
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    targetProgramText = sw.ToString();
                }

                while (fileQueue.Count > 0)
                {
                    var wr = fileQueue.Dequeue();
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    otherFiles.Add(wr.Filename, sw.ToString());
                }
            }
            string baseName   = Path.GetFileNameWithoutExtension(dafnyProgramName);
            string callToMain = null;

            if (hasMain)
            {
                using (var wr = new TargetWriter(0)) {
                    if (DafnyOptions.O.CompileTarget is DafnyOptions.CompilationTarget.Java)
                    {
                        dafnyProgramName = dafnyProgramName.Replace('-', '_');
                        wr.WriteLine($"public class {baseName.Replace('-', '_')} {{");
                    }
                    compiler.EmitCallToMain(mainMethod, wr);
                    if (DafnyOptions.O.CompileTarget is DafnyOptions.CompilationTarget.Java)
                    {
                        wr.WriteLine("}");
                    }
                    callToMain = wr.ToString(); // assume there aren't multiple files just to call main
                }
            }
            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 || (invokeCompiler && !compiler.SupportsInMemoryCompilation))
            {
                var p = callToMain == null ? targetProgramText : targetProgramText + callToMain;
                if (DafnyOptions.O.CompileTarget is DafnyOptions.CompilationTarget.Java && callToMain == null)
                {
                    p = null;
                }
                targetFilename = WriteDafnyProgramToFiles(dafnyProgramName, p, completeProgram, otherFiles, outputWriter);
            }

            if (DafnyOptions.O.CompileTarget is DafnyOptions.CompilationTarget.Java)
            {
                string targetBaseDir    = baseName;
                string targetDir        = Path.Combine(Path.GetDirectoryName(dafnyProgramName), targetBaseDir);
                var    assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
                Contract.Assert(assemblyLocation != null);
                var codebase = System.IO.Path.GetDirectoryName(assemblyLocation);
                Contract.Assert(codebase != null);
                string dest = targetDir + "/dafny";
                Directory.CreateDirectory(dest);
                var jcompiler = (JavaCompiler)compiler;
                jcompiler.CompileTuples(dest);
                jcompiler.CreateFunctionInterface(dest);
                jcompiler.CompileDafnyArrays(dest);
                jcompiler.CompileArrayInits(dest);
            }

            if (!completeProgram)
            {
                return(false);
            }
            // If we got until here, compilation to C# succeeded
            if (!invokeCompiler)
            {
                return(true); // If we're not asked to invoke the C# to assembly compiler, we can report success
            }

            // compile the program into an assembly
            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames,
                                                                     hasMain, hasMain && DafnyOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && DafnyOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Running...");
                        outputWriter.WriteLine();
                    }
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
                else
                {
                    // make sure to give some feedback to the user
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Program compiled successfully");
                    }
                }
            }
            return(compiledCorrectly);
        }
示例#4
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
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Dafny.Compiler compiler;
            switch (DafnyOptions.O.CompileTarget)
            {
            case DafnyOptions.CompilationTarget.Csharp:
            default:
                compiler = new Dafny.CsharpCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.JavaScript:
                compiler = new Dafny.JavaScriptCompiler(dafnyProgram.reporter);
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            var    sw      = new TargetWriter();

            compiler.Compile(dafnyProgram, sw);
            if (hasMain)
            {
                compiler.EmitCallToMain(mainMethod, 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 /nowarn:0168"; // warning CS0164 complains about unreferenced labels, CS0219/CS0168 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);
            }
        }
示例#5
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Assert(dafnyProgramName != null);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Dafny.Compiler compiler;
            switch (DafnyOptions.O.CompileTarget)
            {
            case DafnyOptions.CompilationTarget.Csharp:
            default:
                compiler = new Dafny.CsharpCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.JavaScript:
                compiler = new Dafny.JavaScriptCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Go:
                compiler = new Dafny.GoCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Java:
                compiler = new Dafny.JavaCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Cpp:
                compiler = new Dafny.CppCompiler(dafnyProgram.reporter, otherFileNames);
                break;
            }

            var hasMain = compiler.HasMain(dafnyProgram, out var mainMethod);

            if (hasMain)
            {
                mainMethod.IsEntryPoint = true;
                dafnyProgram.MainMethod = mainMethod;
            }
            string targetProgramText;
            var    otherFiles = new Dictionary <string, string>();
            {
                var fileQueue = new Queue <FileTargetWriter>();
                using (var wr = new TargetWriter(0)) {
                    compiler.Compile(dafnyProgram, wr);
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    targetProgramText = sw.ToString();
                }

                while (fileQueue.Count > 0)
                {
                    var wr = fileQueue.Dequeue();
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    otherFiles.Add(wr.Filename, sw.ToString());
                }
            }
            string callToMain = null;

            if (hasMain)
            {
                using (var wr = new TargetWriter(0)) {
                    string baseName = Path.GetFileNameWithoutExtension(dafnyProgramName);
                    compiler.EmitCallToMain(mainMethod, baseName, wr);
                    callToMain = wr.ToString(); // assume there aren't multiple files just to call main
                }
            }
            Contract.Assert(hasMain == (callToMain != null));
            bool targetProgramHasErrors = dafnyProgram.reporter.Count(ErrorLevel.Error) != oldErrorCount;

            compiler.Coverage.WriteLegendFile();

            // blurt out the code to a file, if requested, or if other target-language files were specified on the command line.
            string targetFilename = null;

            if (DafnyOptions.O.SpillTargetCode > 0 || otherFileNames.Count > 0 || (invokeCompiler && !compiler.SupportsInMemoryCompilation) ||
                (invokeCompiler && compiler.TextualTargetIsExecutable && !DafnyOptions.O.RunAfterCompile))
            {
                targetFilename = WriteDafnyProgramToFiles(compiler, dafnyProgramName, targetProgramHasErrors, targetProgramText, callToMain, otherFiles, outputWriter);
            }

            if (targetProgramHasErrors)
            {
                return(false);
            }
            // If we got here, compilation succeeded
            if (!invokeCompiler)
            {
                return(true); // If we're not asked to invoke the target compiler, we can report success
            }

            // compile the program into an assembly
            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames,
                                                                     hasMain && DafnyOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && DafnyOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Running...");
                        outputWriter.WriteLine();
                    }
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
                else
                {
                    // make sure to give some feedback to the user
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Program compiled successfully");
                    }
                }
            }
            return(compiledCorrectly);
        }
示例#6
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Assert(dafnyProgramName != null);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            bool runRequiresSpill = false;

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Dafny.Compiler compiler;
            switch (DafnyOptions.O.CompileTarget)
            {
            case DafnyOptions.CompilationTarget.Csharp:
            default:
                compiler = new Dafny.CsharpCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.JavaScript:
                compiler = new Dafny.JavaScriptCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.Go:
                compiler         = new Dafny.GoCompiler(dafnyProgram.reporter);
                runRequiresSpill = true;
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            string targetProgramText;
            var    otherFiles = new Dictionary <string, string>();
            {
                var fileQueue = new Queue <FileTargetWriter>();
                using (var wr = new TargetWriter(0)) {
                    compiler.Compile(dafnyProgram, wr);
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    targetProgramText = sw.ToString();
                }

                while (fileQueue.Count > 0)
                {
                    var wr = fileQueue.Dequeue();
                    var sw = new StringWriter();
                    wr.Collect(sw, fileQueue);
                    otherFiles.Add(wr.Filename, sw.ToString());
                }
            }
            string callToMain = null;

            if (hasMain)
            {
                using (var wr = new TargetWriter(0)) {
                    compiler.EmitCallToMain(mainMethod, wr);
                    callToMain = wr.ToString(); // assume there aren't multiple files just to call main
                }
            }
            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 || (runRequiresSpill && DafnyOptions.O.RunAfterCompile))
            {
                var p = callToMain == null ? targetProgramText : targetProgramText + callToMain;
                targetFilename = WriteDafnyProgramToFiles(dafnyProgramName, p, completeProgram, otherFiles, outputWriter);
            }

            // compile the program into an assembly
            if (!completeProgram || !invokeCompiler)
            {
                // don't compile
                return(false);
            }

            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames,
                                                                     hasMain, hasMain && DafnyOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && DafnyOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Running...");
                        outputWriter.WriteLine();
                    }
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, callToMain, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
                else
                {
                    // make sure to give some feedback to the user
                    if (DafnyOptions.O.CompileVerbose)
                    {
                        outputWriter.WriteLine("Program compiled successfully");
                    }
                }
            }
            return(compiledCorrectly);
        }
示例#7
0
        /// <summary>
        /// Generate a C# program from the Dafny program and, if "invokeCompiler" is "true", invoke
        /// the C# compiler to compile it.
        /// </summary>
        public static bool CompileDafnyProgram(Dafny.Program dafnyProgram, string dafnyProgramName,
                                               ReadOnlyCollection <string> otherFileNames, bool invokeCompiler,
                                               TextWriter outputWriter = null)
        {
            Contract.Requires(dafnyProgram != null);
            Contract.Requires(dafnyProgramName != null);

            if (outputWriter == null)
            {
                outputWriter = Console.Out;
            }

            // Compile the Dafny program into a string that contains the target program
            var oldErrorCount = dafnyProgram.reporter.Count(ErrorLevel.Error);

            Dafny.Compiler compiler;
            switch (DafnyOptions.O.CompileTarget)
            {
            case DafnyOptions.CompilationTarget.Csharp:
            default:
                compiler = new Dafny.CsharpCompiler(dafnyProgram.reporter);
                break;

            case DafnyOptions.CompilationTarget.JavaScript:
                compiler = new Dafny.JavaScriptCompiler(dafnyProgram.reporter);
                break;
            }

            Method mainMethod;
            var    hasMain = compiler.HasMain(dafnyProgram, out mainMethod);
            var    sw      = new TargetWriter();

            compiler.Compile(dafnyProgram, sw);
            if (hasMain)
            {
                compiler.EmitCallToMain(mainMethod, sw);
            }
            var  targetProgramText = 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, targetProgramText, completeProgram, outputWriter);
            }

            // compile the program into an assembly
            if (!completeProgram || !invokeCompiler)
            {
                // don't compile
                return(false);
            }

            object compilationResult;
            var    compiledCorrectly = compiler.CompileTargetProgram(dafnyProgramName, targetProgramText, targetFilename, otherFileNames,
                                                                     hasMain, hasMain && DafnyOptions.O.RunAfterCompile, outputWriter, out compilationResult);

            if (compiledCorrectly && DafnyOptions.O.RunAfterCompile)
            {
                if (hasMain)
                {
                    outputWriter.WriteLine("Running...");
                    outputWriter.WriteLine();
                    compiledCorrectly = compiler.RunTargetProgram(dafnyProgramName, targetProgramText, targetFilename, otherFileNames, compilationResult, outputWriter);
                }
            }
            return(compiledCorrectly);
        }
示例#8
0
        protected override void DeclareDatatype(DatatypeDecl dt, TargetWriter wr)
        {
            // $module.Dt = class Dt {
            //   constructor(tag) {
            //     this.$tag = tag;
            //   }
            //   static create_Ctor0(field0, field1, ...) {
            //     let $dt = new Dt(0);
            //     $dt.field0 = field0;
            //     $dt.field1 = field1;
            //     ...
            //     return $dt;
            //   }
            //   static create_Ctor1(...) {
            //     let $dt = new Dt(1);
            //     ...
            //   }
            //   ...
            //
            //   get is_Ctor0 { return this.$tag == 0; }
            //   get is_Ctor1 { return this.$tag == 1; }
            //   ...
            //
            //   toString() {
            //     ...
            //   }
            //   equals(other) {
            //     ...
            //   }
            // }
            // TODO: need Default member (also for co-datatypes)
            // TODO: if HasFinitePossibleValues, need enumerator of values

            string DtT           = dt.CompileName;
            string DtT_protected = IdProtect(DtT);

            wr.Indent();
            // from here on, write everything into the new block created here:
            wr = wr.NewNamedBlock("$module.{0} = class {0}", DtT_protected);

            wr.Indent();
            wr.WriteLine("constructor(tag) { this.$tag = tag; }");


            // query properties
            var i = 0;

            foreach (var ctor in dt.Ctors)
            {
                // collect the names of non-ghost arguments
                var argNames = new List <string>();
                var k        = 0;
                foreach (var formal in ctor.Formals)
                {
                    if (!formal.IsGhost)
                    {
                        argNames.Add(FormalName(formal, k));
                        k++;
                    }
                }
                // static create_Ctor0(params) { return {$tag:0, p0: pararms0, p1: params1, ...}; }
                wr.Indent();
                wr.Write("static create_{0}(", ctor.CompileName);
                wr.Write(Util.Comma(argNames, nm => nm));
                var w = wr.NewBlock(")");
                w.Indent();
                w.WriteLine("let $dt = new {0}({1});", DtT_protected, i);
                foreach (var arg in argNames)
                {
                    w.Indent();
                    w.WriteLine("$dt.{0} = {0};", arg);
                }
                w.Indent();
                w.WriteLine("return $dt;");
                i++;
            }

            // query properties
            i = 0;
            foreach (var ctor in dt.Ctors)
            {
                // get is_Ctor0() { return _D is Dt_Ctor0; }
                wr.Indent();
                wr.WriteLine("get is_{0}() {{ return this.$tag === {1}; }}", ctor.CompileName, i);
                i++;
            }

            if (dt is IndDatatypeDecl && !(dt is TupleTypeDecl))
            {
                // toString method
                wr.Indent();
                var w = wr.NewBlock("toString()");
                i = 0;
                foreach (var ctor in dt.Ctors)
                {
                    var cw = EmitIf(string.Format("this.$tag == {0}", i), true, w);
                    cw.Indent();
                    cw.Write("return \"{0}.{1}\"", dt.Name, ctor.Name);
                    var sep        = " + \"(\" + ";
                    var anyFormals = false;
                    var k          = 0;
                    foreach (var arg in ctor.Formals)
                    {
                        if (!arg.IsGhost)
                        {
                            anyFormals = true;
                            cw.Write("{0}this.{1}.toString()", sep, FormalName(arg, k));
                            sep = " + \", \" + ";
                            k++;
                        }
                    }
                    if (anyFormals)
                    {
                        cw.Write(" + \")\"");
                    }
                    cw.WriteLine(";");
                    i++;
                }
                w = w.NewBlock("");
                w.Indent();
                w.WriteLine("return \"<unexpected>\";");
            }

            // equals method
            wr.Indent();
            using (var w = wr.NewBlock("equals(other)")) {
                using (var thn = EmitIf("this === other", true, w)) {
                    EmitReturnExpr("true", thn);
                }
                i = 0;
                foreach (var ctor in dt.Ctors)
                {
                    var thn = EmitIf(string.Format("this.$tag == {0}", i), true, w);
                    using (var guard = new TargetWriter()) {
                        guard.Write("other.$tag == {0}", i);
                        var k = 0;
                        foreach (Formal arg in ctor.Formals)
                        {
                            if (!arg.IsGhost)
                            {
                                string nm = FormalName(arg, k);
                                if (IsDirectlyComparable(arg.Type))
                                {
                                    guard.Write(" && this.{0} === oth.{0}", nm);
                                }
                                else
                                {
                                    guard.Write(" && _dafny.areEqual(this.{0}, other.{0})", nm);
                                }
                                k++;
                            }
                        }
                        EmitReturnExpr(guard.ToString(), thn);
                    }
                    i++;
                }
                using (var els = w.NewBlock("")) {
                    els.Indent();
                    els.WriteLine("return false; // unexpected");
                }
            }
        }