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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
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"); } } }